Unable to insert PowerShell variables from array into Invoke-Sqlcmd call - powershell

I have an array that loops through a string assigning values to elements. If I then assign those elements to a variable and pass that variable into the invoke-sqlcmd I get an error. However, if I assign the value directly to the variable and pass it in it works fine:
Assign value to array:
for ($i=0; $i -lt $somearray.length; $i++) {
$somearray[$i] = $somearray[$i].Replace('$(query)', $query.text)
}
Lets say somearray[0] = "select * from DB". We'll assign to a variable:
$query = somearray[0]
Now I pass this to my Invoke-Sqlcmd:
Invoke-Sqlcmd -Query $query -Database "local" -ServerInstance "somedb" |
Export-Csv ".\somefile.csv"
This fails:
Invoke-Sqlcmd : Could not find stored procedure 'select * from ALERTS'.
At C:\Migration\ExportTool\ExportTool\Gavs.ps1:95 char:17
+ ... Invoke-Sqlcmd -Query $query -Database $db -ServerInstance ...
However, if I do this:
$query = "select * from DB"
Invoke-Sqlcmd -Query $query -Database "local" -ServerInstance "somedb" |
Export-Csv ".\somefile.csv"
it works perfectly.

So the reason appears to be, if you do this:
$query = somearray[0]
When you view $query in the Invoke-sql command it looks like this:
"select * from DB"
And when you do this:
$query = "select * from DB"
It looks like this:
select * from DB
So directly referencing a string removes the quotes in the Invoke-sqlcmd command. Seems very odd.
Hope this helps someone in the future.

Related

Powershell Invoke-Sqlcmd Use result in another query

I'm attempting to use a result returned from Invoke-Sqlcmd $ORDUNIQ as a variable in a second query. However the second $query2 returns 0 records. Substituting the variable for the actual string value '35973189' works fine.
I'm assuming that $ORDUNIQ.ORDUNIQ is the wrong way to use this?, although running $ORDUNIQ.ORDUNIQ on the command line does return '35973189' correctly
Here is my code
$RAWFiles = Get-ChildItem D:\Imports\Test\*.csv
$content = Import-Csv $RAWFiles | Where-Object 'Order Type' -eq 'B2B'
ForEach ($row in $content) {
$ORDNUMBER = $row.'OrderRef'
$SQLServer = "XXXXX-XXX"
$db1 = "XXXXXX"
$query1 = "SELECT ORDUNIQ FROM OEORDH WHERE ORDNUMBER = '$ORDNUMBER'"
$query2 = "SELECT OEORDD.ITEM FROM OEORDD WHERE ORDUNIQ = '$ORDUNIQ.ORDUNIQ'"
$ORDUNIQ = Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db1 -Query $query1
$ORDDATA = Invoke-SQLcmd -ServerInstance $SQLServer -Database $db1 -Query $query2
}

Powershell SQL Database

Good morning everyone. I am currently in school, working on a PowerShell project, part 2. I was able to get the script to work but now I'm being asked to do this, Check for the existence of a database named ClientDB. Output a message to the console that indicates if the database exists or if it does not. If it already exists, delete it and output a message to the console that it was deleted.Create a new database named “ClientDB” on the Microsoft SQL server instance. Output a message to the console that the database was created. Then go through the rest in creating the table and importing the csv as I've done that much. My problem is how to use the invoke-sqlcmd in an if/else, else/if statement. Thank you so much.
Try {
$DBname = "ClientDB"
$SqlServer = ".\SQLEXPRESS"
if([bool] (Get-SQLDatabase -Filter * | ? {$SqlServer -eq $DBname} ))
{ Write-Host 'ClientDB exists' }
else { Write-Host 'ClientDB does not exists' }
$CreateTableQuery = #"
use $DBname
CREATE TABLE Client_A_Contacts
(
first_name varchar(20),
last_name varchar(20),
city varchar(20),
county varchar(20),
zip varchar(20),
officePhone varchar(20),
mobilePhone varchar(20)
)
"#
Import-Module sqlps -DisableNameChecking
$ServerObject = New-Object Microsoft.SqlServer.Management.Smo.Server($SqlServer)
$DBobject = New-Object Microsoft.SqlServer.Management.Smo.Database($ServerObject, $DBname)
$DBobject.Create()
Write-Host $DBobject "create success # " $DBobject.CreateDate
Invoke-sqlcmd -ServerInstance $SqlServer -Database $DBname -Query $CreateTableQuery
Pop-Location
Import-Csv "NewClientData.csv" | ForEach-Object {Invoke-sqlcmd -ServerInstance $SqlServer -
Database $DBname -Query "insert into dbo.Client_A_Contacts values
('$($_.first_name)','$($_.last_name)','$($_.city)','$($_.county)',
'$($_.zip)','$($_.officePhone)','$($ _.mobilePhone)')"}
}
catch [System.OutOfMemoryException] {
Write-Host "Caught: System.OutOfMemoryException"
}
Invoke-Sqlcmd -Database ClientDB –ServerInstance .\SQLEXPRESS -Query ‘SELECT * FROM dbo.Client_A_Contacts’ > .\SqlResults.txt

Passing a single value from a SQL query to a PowerShell variable

I am trying to a single value from a SQL query to a PowerShell variable. I know the connection and query are running successfully because I am getting the output I expected when using Invoke-DbaQuery or Invoke-Sqlcmd. But when I try to assign the query results to a variable, all I see is System.Data.DataRow
Any suggestions on how to get this query's results assigned to a variable?
$SQLInstance = "SQLInstance"
$Database = "DatabaseName"
$Query = "SELECT TOP (1) Password FROM dbo.Connections WHERE VendorName = 'YYY' ORDER BY VendorName;"
#Invoke-DbaQuery -SqlInstance $SQLInstance -Database $Database -Query $Query
#$password = (Invoke-DbaQuery -SqlInstance $SQLInstance -Database $Database -Query $Query)
$password = Invoke-Sqlcmd -ServerInstance $SQLInstance -Database $Database -Query $Query
Write-Host $password
You've seen that $password is a [DataRow], and Write-Host can only use [string]. Try one of these two:
Output the result by itself (no write-host). Powershell will format all of the fields and rows for you:
$password
# outputs:
password
--------
hunter2
Output just the string from your query result instead of the table format above:
$password.Password
# Outputs:
hunter2
DataRow objects are made to contain multiple rows and multiple fields, so it can get confusing when you're expecting just a single value as a result.

How to process multiple columns from sql in powershell

I have this PowerShell script:
$QUERY = "SELECT name FROM sys.databases";
$Databases = invoke-sqlcmd -serverinstance "SQLInstanceName" -database "master" -Query $QUERY
foreach ($dbname in $Databases)
{
$dbname
}
Let's say I want the recovery model for the databases as below, how do I get them into PowerShell variables?
$QUERY = "SELECT name, recovery_model_desc FROM sys.databases";
May be you are looking for
$QUERY = "SELECT * from sys.databases";
$Databases = invoke-sqlcmd -serverinstance "SQLInstanceName" -database "master" -Query $QUERY
# This is just to print the individual value of column (name and recovery_model)
$Databases | ForEach {
Write-Host '----------------------------------------'
Write-Host 'Database :' $_.name
Write-Host 'Recovery model :' $_.recovery_model
Write-Host '----------------------------------------'
Write-Host
}
# This will give you name and recovery_model of database
$Databases | Select name, recovery_model

powershell - variable inside a string variable shall update even after it was declared

As you can see, the variable $SQLRCNumberNew is inside another variable $SQLUpdateRC which has been declared before $SQLRCNumberNew did.
When I am running the script $SQLRCNumberNew is empty, which makes sense because it is declared inside $SQLUpdateRC at the beginning.
What I want to ask if someone has an idea how I can update $SQLRCNumberNew even it is declared at the beginning.
I know I can just put the string Variable right below, but this is not what I am looking for.
Thanks for any help!
$RCFirstDigit = 0
$RCSecondDigit = 0
$PhoenixDBServer = "Servername"
$PhoenixDBName = "Databasename"
$ProductionDBServer = "Servername"
$ProductionDBName = "Databasename"
$SQLSelectRC = $("SELECT [Char_Value_01] FROM [dbo].[TABLENAME] WHERE [Keyword] = 'Version Number'")
$SQLUpdateRC = $("UPDATE TABLENAME set Char_Value_01 = '$SQLRCNumberNew' where Keyword = 'Version Number'")
Switch ($env:COMPUTERNAME) {
$PhoenixDBServer {
$Server = $PhoenixDBServer + "." + $env:USERDNSDOMAIN
$Database = $PhoenixDBName
}
$ProductionDBServer {
$Server = $ProductionDBServer + "." + $env:USERDNSDOMAIN
$Database = $ProductionDBName
}
default {
Write-Verbose "This script does not run on this computer"
exit
}
}
$SQLRCNumber = Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $SQLSelectRC
[int]$RCFirstDigit = $SQLRCNumber.Char_Value_01.split(".")[1]
[int]$RCSecondDigit = $SQLRCNumber.Char_Value_01.split(".")[2]
$RCSecondDigit++
# put string back together with updated RC number
[string]$SQLRCNumberNew = $SQLRCNumber.Char_Value_01.Split(".")[0] + "." + $RCFirstDigit + "." + $RCSecondDigit
# Update RC Version on Database
Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $SQLUpdateRC
Just to be clear - this is not how PowerShell scripting works. When you assign data to your variables, at least when working with strings.
You could have a function inside your script file, that you could call and have it return the concatenated string.
Function StringBuilder {
Param ($Value)
"UPDATE TABLENAME set Char_Value_01 = '$Value' where Keyword = 'Version Number'"
}
...
$SQLRCNumber = Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $SQLSelectRC
$SQLUpdateRC = StringBuild $SQLRCNumber
Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $SQLUpdateRC
...
Something like that should work. But I would say you should have a string format defined in the top and simply format when you need it.
$SQLUpdateRCBase = "UPDATE TABLENAME set Char_Value_01 = '{0}' where Keyword = 'Version Number'"
...
$SQLRCNumber = Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $SQLSelectRC
$SQLUpdateRC = $SQLUpdateRCBase -f $SQLRCNumber
Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $SQLUpdateRC