Connecting to azure sql database using powershell - powershell

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"

Related

Returning data with sqladapter returns Cannot find an overload for "Fill" and the argument count

I am trying to all the data in table from sql database using powershell. Using that data I can use for a foreach statement and use each field.
I run into the below error:
"MethodException: Multiple ambiguous overloads found for "Fill" and
the argument count: "1"."
I have no clue on how to fix this and help will be appeciated
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = $constring
$SqlConnection.AccessToken = $AccessToken
$SqlConnection.Open()
$SQLQuery = "SELECT DISTINCT servername, DBName FROM DBInfo "
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SQLQuery
$SqlCmd.Connection = $SqlConnection
$ReaderValidate
#SQL Adapter - get the results using the SQL Command
$sqlAdapter = new-object System.Data.SqlClient.SqlDataAdapter
$sqlAdapter.SelectCommand = $SQLQuery
$dataSet = new-object System.Data.Dataset
$allResults = $sqlAdapter.Fill($SqlCmd.CommandText)
Write-output = "$allResults"
#Close SQL Connection
$sqlConnection.Close();
I am using azure function and managed idenitity to access the database. That is the reason I am using "$SqlConnection.AccessToken"
Try to use $DataSet as the argument to the $Adapter.Fill() method:
$allResults = $sqlAdapter.Fill($dataSet)
A good way to think of it, you are filling the data set...
Here is the code I frequently use, though it's adapted using the ::New() method instead of using New-Object, an older version of this was written similar to yours.
$ConnStr = "Server=<ServerName>,<Port>; Database=<DBName>; Integrated Security=true"
$Query = "SELECT * FROM <TableName> WHERE <SomeCondition>"
$Conn = [System.Data.SqlClient.SqlConnection]::new( $ConnStr )
$Conn.Open()
$Adapter = [System.Data.SqlClient.SqlDataAdapter]::new( $Query, $Conn )
$DataSet = [System.Data.DataSet]::new()
[Void]$Adapter.Fill( $DataSet )
$Conn.Close()
These are the adapter overloads:
OverloadDefinitions
-------------------
System.Data.SqlClient.SqlDataAdapter new()
System.Data.SqlClient.SqlDataAdapter new(System.Data.SqlClient.SqlCommand selectCommand)
System.Data.SqlClient.SqlDataAdapter new(string selectCommandText, string selectConnectionString)
System.Data.SqlClient.SqlDataAdapter new(string selectCommandText, System.Data.SqlClient.SqlConnection selectConnection)
In my code I'm using the third one. The command text followed by the already instantiated connection object.

Powershell SQL Query to variables

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
}

PowerShell 4 SQL Server Insertions

I'm using Powershell 4 and attempting to write data into a SQL Server 2012.
Here is the script I am using
Add-Type -AssemblyName System.Data
$conn = New-Object System.Data.SqlClient.SqlConnection↵
$conn.ConnectionString = "Data Source=<SQLSERVER>;Initial Catalog=SYSINFO;Integrated Security=true;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
The error I am getting is:
New-Object : Cannot find type [System.Data.SqlClient.SqlConnection] : verify that the assembly containing this type is loaded.
I assuemd the first line (Add-Type) would load all the required assemblies under System.Data
Am I missing somethign obvious?
You can do it this way:
$Server = 'theServer'
$database = 'theDatabase'
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server=$($Server);database=$($Database);trusted_connection=true;"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = 'SELECT TOP 5 * FROM yourTable ORDER BY 1 DESC'
$Reader = $Command.ExecuteReader()
$Datatable = New-Object System.Data.DataTable
$Datatable.Load($Reader)
$Datatable | Export-Csv report.csv -NoTypeInformation
$Connection.Close()

How to get stored procedure output parameter into variable using Powershell?

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;

Output results to a SQL table

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...