Trying to use SQL results as variables. This will return the results to the host, but I would like to use each value as a variable.
$job = "22940"
$SQLServer = "my-sql" #use Server\Instance for named SQL instances!
$SQLDBName = "MyDatabase"
$SqlQuery = "DECLARE #Job VARCHAR(5);
SET #Job = '$job'
SELECT dbo.Job.Job, dbo.Job.Customer,
dbo.Job.Note_Text,
dbo.User_Values.Date1 AS 'Setup Date',
dbo.User_Values.Date2 AS 'Due Date'
FROM dbo.Job INNER JOIN
dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
WHERE (dbo.Job.Job = #Job) AND (dbo.Job.User_Values = dbo.User_Values.User_Values)"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
$DataSet.Tables[0]
How can I put each column into a variable that I can use for something else?
I work with data tables directly. You should also look into handling parameters correctly. It helps with handling special characters in the variable value. And, it protects from SQL Injection Attacks:
$Sql = 'select top 100 first_name, Last_name from person where last_name=#lastname'
$Database = 'XXX'
$Server = 'XXX'
$LastName = 'Jones'
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = "Server=$Server;Database=$Database;Integrated Security=True"
$Connection.Open()
$cmd = new-object system.Data.SqlClient.SqlCommand($Sql, $Connection)
$null = $cmd.Parameters.AddWithValue('#lastname', $LastName)
$DataTable = New-Object System.Data.DataTable
$SqlDataReader = $cmd.ExecuteReader()
$DataTable.Load($SqlDataReader)
$Connection.Close()
$Connection = $null
$DataTable.Rows.Count
foreach ($r in $DataTable.Rows)
{
$fn = $r.first_name
$ln = $r.last_name
"$fn $ln"
}
Not sure if this is really the correct way but it does give me the results I am looking for. Looked through some of my notes on working with CSV files and I added the foreach at the end. The above comments from #notjustme and #jcoehoorn got me looking in the right direction. Thanks
$job = "22940"
$SQLServer = "my-sql" #use Server\Instance for named SQL instances!
$SQLDBName = "MyDatabase"
$SqlQuery = "DECLARE #Job VARCHAR(5);
SET #Job = '$job'
SELECT dbo.Job.Job, dbo.Job.Customer,
dbo.Job.Note_Text,
dbo.User_Values.Date1 AS 'Setup Date',
dbo.User_Values.Date2 AS 'Due Date'
FROM dbo.Job INNER JOIN
dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
WHERE (dbo.Job.Job = #Job) AND (dbo.Job.User_Values = dbo.User_Values.User_Values)"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
foreach($Job in $DataSet.Tables[0])
{
$MyJobNumber = $Job.Job
$MyCustomer = $Job.Customer
$MyNotes = $Job.Note_Text
$MySetupDate = $Job.Setup_Date
$MyDueDate = $Job.Due_Date
}
Related
I have a powershell script in which I am trying to establish a connection to an azure sql db. When Building my connection string in the following way, the creation of the SqlConnection object always fails with an error stating that the format of the connection string does not conform to specification (the variable cred is of type "PSCredential").
$connString = “Server=$($serverName).database.windows.net;”
$connString = $connString + “Database=$($dbName);”
$connString = $connString + “Integrated Security=False;”
$connString = $connString + “User ID=$($cred.Username)#$($serverName);”
$connString = $connString + “Password=$($cred.GetNetworkCredential().Password);”
$connString = $connString + “Trusted_Connection=False;”
$connString = $connString + “Encrypt=True;”
$connString = $connString + “Connection Timeout=30;”
$SqlConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection($connString)
Anyone got an idea what goes wrong here?
Try the following:
$SQLServer = "aaaa.database.windows.net"
$SQLDBName = "Database"
$uid ="john"
$pwd = "pwd123"
$SqlQuery = "SELECT * from table;"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = False; User ID = $uid; Password = $pwd;"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$DataSet.Tables[0] | out-file "C:\Scripts\xxxx.csv"
I'm pulling data from SQL using System.Data.SqlClient and eventaully end up with a dataset stored into a variable:
$SqlQuery = "select * from my_Table"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$amManagedFolders = New-Object System.Data.DataSet
$SqlAdapter.Fill($dataset)
I then access the table via $dataset.Tables[0] which is of type: System.ComponentModel.MarshalByValueComponent
I need to be able to use ForEach in order to loop through that table and store the results into a CustomPSObject for later use, however, I am not sure of a method to use in order to achieve this.
Using this page I found the following code helpful. I'm taking a SQL query and producing an Excel workbook with the results.
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
$DataSetTable = $DataSet.Tables["Table"]
## - Build the Excel column heading:
[Array] $getColumnNames = $DataSetTable.Columns | Select ColumnName
## - Build column header:
[Int] $RowHeader = 1
foreach ($ColH in $getColumnNames)
....
foreach ($rec in $DataSetTable.Rows)
{
foreach ($Coln in $getColumnNames)
{
## - Next line convert cell to be text only:
$xlsSh.Cells.NumberFormat = "#"
## - Populating columns:
$xlsSh.Cells.Item($rowData, $colData) = $rec.$($Coln.ColumnName).ToString()
$ColData++
}
$rowData++; $ColData = 1
}
-Edit, saw your comment. You might be able to adapt the answer to this question
I have a stored procedure returning a string and I need the result as a powershell variable. I'm stuck on the output parameter syntax.
Powershell script:
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=myserver;Database=mydb;Integrated Security=True"
$SqlConnection.Open()
$SqlConnection.State
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "testsp3"
$SqlCmd.Connection = $SqlConnection
$op = new-object System.Data.SqlClient.SqlParameter;
$op.ParameterName = "#answer";
$op.Direction = [System.Data.ParameterDirection]'Output';
$op.DbType = [System.Data.DbType]'String';
$op.Size = 2500
$SqlCmd.Parameters.Add($op);
$what = $SqlCmd.ExecuteScalar();
$what
Error message:
Exception calling "ExecuteScalar" with "0" argument(s): "Procedure or function 'testsp3' expects parameter '#answer', which was not supplied."
Stored procedure if it matters:
CREATE PROCEDURE [dbo].[testsp3]
#answer nvarchar(max) output
AS
BEGIN
SET NOCOUNT ON;
SELECT #answer = 'blah blah blah'
RETURN
END
GO
Modify your script to be like below
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=myserver;Database=mydb;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "testsp3"
$SqlCmd.Connection = $SqlConnection
$SqlCmd.CommandType = [System.Data.CommandType]'StoredProcedure'; <-- Missing
$outParameter = new-object System.Data.SqlClient.SqlParameter;
$outParameter.ParameterName = "#answer";
$outParameter.Direction = [System.Data.ParameterDirection]'Output';
$outParameter.DbType = [System.Data.DbType]'String';
$outParameter.Size = 2500;
$SqlCmd.Parameters.Add($outParameter) >> $null;
$SqlConnection.Open();
$result = $SqlCmd.ExecuteNonQuery();
$truth = $SqlCmd.Parameters["#answer"].Value;
$SqlConnection.Close();
$truth;
I have the following code which returns what I need but I am struggling to output this to a table from which I can further query.
$instances = invoke-sqlcmd –ServerInstance "myserver" –Database "my db" –query "select instanceconnectname from [dbo].[smytable] WHERE InstanceConnectName LIKE '%CLU%' and connect = 1"
Write-Host $instances.instanceconnectname
foreach ($svr in $instances.instanceconnectname){
$dt = new-object "System.Data.DataTable"
$cn = new-object System.Data.SqlClient.SqlConnection "server=$svr;database=master;Integrated Security=sspi"
$cn.Open()
$sql = $cn.CreateCommand()
$sql.CommandText = "SELECT ##SERVERNAME AS ServerName, SERVERPROPERTY('ComputerNamePhysicalNetBIOS') As ActiveNode"
$rdr = $sql.ExecuteReader()
$dt.Load($rdr)
$cn.Close()
$dt | Format-Table -autosize
}
I have been reading about some custom functions out there is that the only way to do this really? I had thought I could just do some kind of SQL Insert but not figured out how to do it.
Instead of outputting to a DataTable, I would output to a DataSet, which you can then further query. e.g.:
$cn = new-object System.Data.SqlClient.SqlConnection "server=$svr;database=master;Integrated Security=sspi"
#Create the SQL Command from a connection string
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "SELECT ##SERVERNAME AS ServerName, SERVERPROPERTY('ComputerNamePhysicalNetBIOS') As ActiveNode"
$SqlCmd.Connection = $cn
#Create the SQL DataAdapter
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
#Fill the DataSet
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
Now with it in a DataSet, you can query it, like this:
$DataSet.tables[0].select("ServerName like 'Bob%'")
Hopefully that is enough to get you started...
Can someone tell me why the following code only returns one row from the DataSet (for the master db) instead of one for each database on the server?
$SQLConn = New-Object System.data.SqlClient.SqlConnection
$SQLConn.ConnectionString = "Data Source = $SQLServer; Initial Catalog = master;
Integrated Security = True"
$SQLConn.Open()
$query = "exec sp_msForEachDb 'use [?] SELECT TOP 1 [name] FROM sysusers'"
$SQLCmd = New-Object System.Data.Sqlclient.SqlCommand($query, $SQLConn);
$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SQLAdapter.SelectCommand = $SQLCmd
$DataSet = New-Object System.Data.Dataset
$SQLAdapter.Fill($DataSet) | out-null
ForEach ($row in $DataSet.Tables[0])
{
$Name = $row["name"]
write-host $Name
}
$SQLConn.Close()
Your code shows your using the index position 0 of $dataset.tables. Change it to $DataSet.Tables
ForEach ($row in $DataSet.Tables[0])
{
$Name = $row["name"]
write-host $Name
}
Change to...
ForEach ($row in $DataSet.Tables)
{
$Name = $row["name"]
write-host $Name
}
You're returning getting multiple datatables in your result set, but only showing the first one Tables[0]. Try this:
$DataSet.Tables | foreach {$_.name}
Here's some completed and tested code to combine result set:
$SQLServer = ".\SQL1"
$query = #"
create table #output
(DB varchar(128),
name varchar(128)
)
exec sp_MSforeachdb #command1='USE [?];
insert #output SELECT TOP 1 ''?'' AS ''DB'', [name]
FROM sysusers';
select * from #output
"#
$SQLConn = New-Object System.data.SqlClient.SqlConnection
$SQLConn.ConnectionString = "Data Source = $SQLServer; Initial Catalog = master;
Integrated Security = True"
$SQLConn.Open()
$SQLCmd = New-Object System.Data.Sqlclient.SqlCommand($query, $SQLConn);
$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SQLAdapter.SelectCommand = $SQLCmd
$DataSet = New-Object System.Data.Dataset
$SQLAdapter.Fill($DataSet) | out-null
$DataSet.Tables[0]
$SQLConn.Close()
I think I needed to do something like this to get all of the records into one dataset:
$query = "DECLARE #users TABLE ([name] varchar(100)) INSERT #db_roles
exec sp_msForEachDB 'USE [?] SELECT [name] FROM sysusers'
SELECT [name] FROM #db_roles"