Invoke-Sqlcmd cmdlet throws exception when using -Variable parameter - sql-server

When I try to use the Invoke-Sqlcmd cmdlet from SQL Server 2008 to execute a query that contains scripting variables, ex. $(MyVar), I receive the following exception:
Invoke-Sqlcmd : Object reference not set to an instance of an object.
Here's the code I'm trying to run (which is copy/paste from the Books Online example with only the connection parameters added).
$MyArray = "MyVar1 = 'String1'", "MyVar2 = 'String2'"
Invoke-Sqlcmd -Query "SELECT `$(MyVar1) AS Var1, `$(MyVar2) AS Var2;" -Variable $MyArray -ServerInstance "localhost" -Database "master" -UserName "who" -Password "me"
If I replace $(MyVar1) and $(MyVar2) in the -Query with 'x' and 'y' then it runs perfectly.
$MyArray = "MyVar1 = 'String1'", "MyVar2 = 'String2'"
Invoke-Sqlcmd -Query "SELECT 'x' AS Var1, 'y' AS Var2;" -Variable $MyArray -ServerInstance "localhost" -Database "master" -UserName "who" -Password "me"
Can anyone tell me why this is not working?

Indeed this is a bug in SQL Server - tracked and fixed here
https://connect.microsoft.com/sqlserver/feedback/details/358291/invoke-sqlcmd-powershell-cmdlet-fails-when-array-passed-via-variable
However, there's a posted workaround. Remove the spaces around the assignment. So instead of
$MyArray = "MyVar1 = 'String1'", "MyVar2 = 'String2'"
use
$MyArray = "MyVar1='String1'", "MyVar2='String2'"

Ok. I posted this same question on the SQL Server forums and, apparently, this is a bug in SQL Server 2008's PowerShell cmdlets... follow the thread here.

Try this alone:
PS>$MyArray = "MyVar1 = 'String1'", "MyVar2 = 'String2'"
Now:
PS>$MyArray
and
PS>MyVar1
Now:
PS>$MyArray|get-member
PowerShell thinks you've assigned 2 string objects to $MyArray, nothing more. This approach does not result in defining the variables $MyVar1 and $MyVar2 to PowerShell.
Sorry, I can't fire up my SQL2008 VM right now to comment on the other parts...

Related

Passing Powershell variable into a SQL INSERT

I'm quite new when it comes to Powershell and I'm not sure if my method is the best.
How can I pass Powershell variables into SQL using Invoke SQL or the .Net method? All I'm trying to do is to Insert data from the Get-AzureADGroup Display Name and Object Id into a SQL table.
$Groups = Get-AzureADGroup -All $true
foreach($Group in $Groups){
$DN = $Group.DisplayName
$ID = $Group.ObjectId
$insertquery="
INSERT INTO [dbo].[Table]([DsiplayName],[ObjectId])
VALUES(''$DN'',''$ID'')
"
Invoke-Sqlcmd -ServerInstance "Server" -Database "Database" -Query $insertquery
}
However, it comes up with the error 'Incorrect syntax near 'GroupDisplayName'. I've tried using " and ' interchangeably in the query with no luck. Am I missing something?

Connecting powershell to SQL Server

I'm quite new to both SQL and Power shell, but I want to run a script which pulls data from a server within SQL - Any advice on where to start?
I tried using this as a starting point, but got no luck as it doesn't like my credentials even though they are correct
Test:
SqlConnection -ServerName 'END-HDSQ02\DEV4' -DatabaseName 'tbl_cert_expiry' -Credential (Get-Credential)
EDIT: Since Powershell V2, you are required to manually load the necessary Snap-Ins;
Powershell - Invoke-Sqlcmd unable to run
Add-PSSnapin SqlServerCmdletSnapin100
Add-PSSnapin SqlServerProviderSnapin100
This is what we use to query a SQL View;
[string] $Server= "ServerName"
[string] $Database = "DatabaseName"
[string] $SQLQuery= $("SELECT * FROM schema.TableView order by column")
$data = Invoke-Sqlcmd -ServerInstance $server -Database $database -Username $username -Password $value1 -Query $SQLQuery
Obviously you'll need to pass the connecting user and password as well, but I've omitted them from my example.

Powershell - Output SQL Messages to file

I have a Powershell script that invokes a saved SQL Query file and runs it on a specific Server & Database. That part is working well, the issue is that I would like to save the SQL Messages that it generates to a log file (see picture).
SQL Output from after Query is run
This is not working with my current code, and I believe that's because since it's technically not Query output but instead reindexing and updating tables, not fetching data.
My current relevant code is:
{
Import-Module SQLPS
$Data = Invoke-Sqlcmd -InputFile $SQLQuery -ServerInstance $Server -Database $Database -QueryTimeout 0
$Data | out-file "$Output$Database$date.txt"
}
But that just generates an empty text file. I'm looking to get the info on rebuilding indexes and the updates it's doing saved off into a different file through Powershell. You can do this through SSMS by right clicking in the Messages window and clicking "Save Results As..." but looking to include this in my automation since it's running as a Scheduled Task and no one is on SSMS.
Powershell v3/Windows Server 2012/SQL SSMS 2014
Any help would be appreciated!! This is my first post so sorry for odd formatting.
It looks like the following link explains exactly this problem:
https://sqlnotesfromtheunderground.wordpress.com/2015/09/09/powershell-outputting-a-sql-server-query-result-from-the-message-tab/
Essentially, what you are seeing in the 'Messages' tab are not results from the query, but rather just PRINT statements (essentially the same as Write-Host or Console.WriteLine). If you use Invoke-SqlCommand2, its -Verbose option will capture these PRINT statements to the Verbose PowerShell stream. To then write this stream to a text file, you have to specify the specific stream (in this case, 4):
Invoke-Sqlcmd2 -ServerInstance . -Database master -Query "PRINT 'Export This result'" -Verbose 4> Out-File C:\Temp\Test.txt
I had the same issue but instead in powershell script i use it in a command and i used -verbose.
like this
Invoke-Sqlcmd -ServerInstance '.\Your_server_instance' -Database 'DATABASE_Name' -InputFile "D:\Your_script.sql" verbose 4> "C:\sql\YOUR_OUTPUT_FILE.txt"
so i think this code should work for you
{
Import-Module SQLPS
$Data = Invoke-Sqlcmd -InputFile $SQLQuery -ServerInstance $Server -Database $Database -QueryTimeout 0
$Data -verbose *> "$Output$Database$date.txt"
}
for -verbose *> it streams All output you can redirect specific streams :
1 Success output
2 Errors
3 Warning messages
4 Verbose output
5 Debug messages

Error passing variable SQL instance name into Invoke-SQLcmd

I'm working on a project that pulls a list of SQL instances from server A and then loops through the returned list and runs a query (eventually to audit users and insert results into table) but getting an error instance not found. It seems I'm not defining the variable correctly in the loop because if I hardcode the instance name it works.
I appreciate any input on how to fix this.
$Serverlist = invoke-sqlcmd -ServerInstance TESTSERVER1 -Database TESTDB -Query "SELECT instancename from testtable"
foreach ($SQLInst in $Serverlist)
{
$Inst = $SQLInst.INSTANCE
Invoke-Sqlcmd -ServerInstance ${$Inst} -Database Master -Query "select ##servername as servername" | select -ExpandProperty servername
} #end foreach loop
Invoke-Sqlcmd : A network-related or instance-specific error occurred
while establishing a connection to SQL Server. The server was not
found or was not accessible. Verify that the instance name is correct
and that SQL Server is configured to allow remote connections.
(provider: Named Pipes Provider, error: 40 - Could not open a
connection to SQL Server) At line:12 char:1
+ Invoke-Sqlcmd -ServerInstance ${$SQLInst} -Database Master -Query "select ##serv ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExectionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
There's no reason to use curly braces like that ${$Inst} in this instance.
Simply using $Inst will work fine. If you do use curly braces, then you don't use the $ inside: ${Inst}.
Invoke-Sqlcmd -ServerInstance $Inst
# or
Invoke-Sqlcmd -ServerInstance ${Inst}
I would check to make sure that each instance is the correct one:
$Serverlist = invoke-sqlcmd -ServerInstance TESTSERVER1 -Database TESTDB -Query "SELECT instancename from testtable"
foreach ($SQLInst in $Serverlist)
{
$Inst = $SQLInst.INSTANCE
Write-Host $Inst
} #end foreach loop
I noticed some problems with my previous statement. Can you try this?
$Serverlist = invoke-sqlcmd -ServerInstance TESTSERVER1 -Database TESTDB -Query "SELECT instancename from testtable"
foreach ($SQLInst in $Serverlist)
{
$Inst = $SQLInst.instancename
Invoke-Sqlcmd -ServerInstance "$Inst" -Database Master -Query "select ##servername as servername" | select -ExpandProperty servername
} #end foreach loop
When you are referencing a result from a query, you must specify the column name even if there is only one column in the query. Enclosing the query in parentheses and using dot notation with the column name will convert the rows to a list of values. Your original problem was you had the column name incorrect.
Try this:
$Serverlist = ( invoke-sqlcmd -ServerInstance TESTSERVER1 -Database TESTDB -Query "SELECT instancename from testtable").instancename
$Serverlist | ForEach-Object {
( Invoke-Sqlcmd -ServerInstance $SQLInst -Database Master -Query 'select ##servername as servername' ).servername
}

Need help getting Invoke-Sqlcmd, -InputFile & -Variable working nicely together

I have File1.ps1 containing the command as follows:
$VariableArray = "PrincipleName='Jack'"
Invoke-Sqlcmd -InputFile "C:\Amit\Test.sql" -Variable $VariableArray -ServerInstance "3STOOGES"
my Test.sql contains
--Test.sql
declare #PrincipleName varchar(20)
SELECT 'PrincipleName=' + #PrincipleName
This gives me output as
Column1
-------
I tried something mentioned here
I tried the options for $(PrincipleName) inside the Test.sql but it complained the SQL server Management Studio.
Please advise as I Have SQL server 2012 with Powershell 3.0 on Windows 2012
The syntax is all wrong. SELECT #PrincipleName will just return nothing since variable is not set.
Use this syntax in a powershell ISE.
Import-Module “sqlps” -DisableNameChecking
$MyArray = "MyVar1 = 'String1'", "MyVar2 = 'String2'"
Invoke-Sqlcmd -InputFile "C:\temp\john.sql" -Variable $MyArray
Use this syntax in the sql file.
SELECT $(MyVar1) AS Var1, $(MyVar2) AS Var2;
The output is shown here and works correctly.

Resources