Given:
$settings = #{"Env1" = "VarValue1"; "Env2" = "VarValue2" }
Write-Output "Count: $($settings.Values.Count)"
Write-Output "Value 0: '$($settings.Values[0])'"
Write-Output "Value 1: '$($settings.Values[1])'"
I get the output:
Count: 2
Value 0 : 'VarValue2 VarValue1'
Value 1 : ''
Why does the first element have both values and the second have none? How do I get the values as a collection I can index?
I figured it out. The solution is to convert the Values ICollection to an array of strings.
With:
$values = $settings.Values -as [string[]]
The output becomes as originally expected:
Count: 2
Value 0 : 'VarValue2'
Value 1 : 'VarValue1'
I cannot help but feel that this should be the default behaviour.
You can't directly index a hashtable like that. Gotta do this
($settings.GetEnumerator() | select -expand value)[0]
From help about_hash_tables
Hash table tables are not arrays, so you cannot use an integer as
an
index into the hash table, but you can use a key name to index into the
hash table. If the key is a string value, enclose the key name in quotation
marks.
Based on your $settings object, you can simply use ยป ($settings).Values
Example:
($settings).Values | % { 'โข ' + $_ }
Returns:
โข VarValue2
โข VarValue1
Related
I am loading a DataTable with data from SQL Server as such:
$queryStr = "SELECT TOP 10 ID, QueryText FROM dbo.DatabaseName";
$dataRows = Invoke-DbaQuery -SqlInstance instance.name -Database databasename -Query $queryStr -As DataSet;
In SQL Server the QueryText is nvarchar(max). In PowerShell, this becomes a string datatype, equal to varchar I think. I think this because when I try to calculate the hash in PowerShell with Get-FileHash, and in SQL Server I calculate the hash on the nvarchar column with SELECT (CONVERT([varchar](70),hashbytes('SHA2_256', QueryText),(1))), the hashes do not match.
They DO match however, if I convert the nvarchar to a varchar(max) in SQL Server.
So the question is, in PowerShell how can I convert the string datatype to match the nvarchar datatype in SQL Server? Because as far as I know, PowerShell does not have a nvarchar datatype, just the generic string datatype.
Added this part after reading comments.
In the DataTable that I retrieve from SQL Server as per the above code I add an extra column to hold the hash that I calculate in PowerShell.
Add extra column to DataTable:
$HashColumn = [System.Data.DataColumn]::new('QueryHashString', [string]);
$dataRows.Tables[0].Columns.Add($HashColumn);
Now I do a foreach to fill this column I just added:
foreach($row in $dataRows.Tables[0]) {
$stringAsStream = [System.IO.MemoryStream]::new()
$writer = [System.IO.StreamWriter]::new($stringAsStream)
$writer.write("$($row.QueryText)")
$writer.Flush()
$stringAsStream.Position = 0
$row.QueryHashString = (Get-FileHash -InputStream $stringAsStream | Select-Object -ExpandProperty Hash)
}
Your code uses StreamWriter that uses the default UTF-8 encoding, which matches what you get with hashing a VARCHAR -- if you stick to ASCII characters. To hash Unicode instead (and for variation, let's use SHA256 directly instead of going through Get-FileHash, and throw in an emoji so we have to deal with surrogates):
$s = "Hello, world! I ๐ you"
$sha256 = [System.Security.Cryptography.SHA256]::Create()
[BitConverter]::ToString(
$sha256.ComputeHash([System.Text.Encoding]::Unicode.GetBytes($s))
).Replace("-", "")
This yields the same result as
SELECT CONVERT(CHAR(64), HASHBYTES('SHA2_256', N'Hello, world! I ๐ you'), 2)
I've searched for a number of hours now and am unable to figure out how to do this.
I query an MSSQL database that returns 2 columns, one of these values is empty/null but does represent something in the SQL database(I've tested disabling it).
How would I check through what is returned from my query for the empty value and modify this to something else?
$TestQuery = Invoke-Sqlcmd -Database $DB -Query $qcd -ServerInstance "SomeInstance\Instance1" -Verbose
Result:
Activity Setting
-------- -------
All Operation Enabled
Backup Enabled
Restore Enabled
Prune Enabled
Aux Copy Enabled
Schedule Enabled
Archive Check Enabled
Tape Erase Enabled
Offline content Index Enabled
Online Content Index Enabled
Enabled
You can see the last item returned doesn't have a value but does reflect a setting in the application we use, I just want to modify that value to "Value1" for example.
Any help is greatly appreciated, I did try using hashtables but had no idea what I was doing despite several hours of googling.
Edit:
My Query:
SELECT JM.opName AS 'Activity',
CASE action
WHEN 1 THEN 'Disabled'
WHEN 2 THEN 'Enabled'
END AS 'Setting'
FROM JMJobAction AS J
LEFT JOIN JMJobOperationNames JM on JM.opType = J.opType
WHERE clientId = 1
AND appType = 0
AND J.opType != 8
AND appId = 1
You may do the following in PowerShell:
$TestQuery = Invoke-Sqlcmd -Database $DB -Query $qcd -ServerInstance "SomeInstance\Instance1"
$TestQuery |
Where { [string]::IsNullOrEmpty($_.Activity) } | Foreach-Object {
$_.Activity = 'Value1' # Update all empty or nulls with Value1
}
$TestQuery # Contains updated results
Note that this does not update the actual database. You will need a separate query that writes back to the database.
When a database table contains a NULL, it is interpreted as the System.DBNull data type in PowerShell. [System.DBNull]::Value is not the same as $null. So if you only wanted to query for NULL values, then your query could more appropriately be modified to the following:
$TestQuery | Where Activity -is [DBNUll]
I don't know if I understand your question correctly.
I understand that you want to have a default_value when there is no data in a column.
That can be solved in your SQL Query with case. Here an example
[Edit] Based on your added query
SELECT
CASE
WHEN JM.opName is null OR JM.opName = '' THEN "DefaultActivity"
ELSE JM.opName
END AS Activity,
CASE action
WHEN 1 THEN 'Disabled'
WHEN 2 THEN 'Enabled'
END AS 'Setting'
FROM JMJobAction AS J
LEFT JOIN JMJobOperationNames JM on JM.opType = J.opType
WHERE clientId = 1
AND appType = 0
AND J.opType != 8
AND appId = 1
I'm using PostgreSQL and I have a table which includes week numbers of the year in its columns. I try to update by increasing these columns' values in nested loops.
I have the following query which attempts to increase the related field of a record.
foreach ( $updateVotes as $key => $value ) {
for ( $week = 1; $week < 53 ; $week++) {
$increaseValue = $value['week_'.$week];
$this->db->set("week_".$week , "week_".$week. " +".$increaseValue, "FALSE");
}
$this->db->where('id', $id)
->update('votes');
}
To achieve my aim, I need output like the one below:
UPDATE "votes"
SET week_1 = week_1 +20,
week_2 = week_2 +50,
...
WHERE id = 1
However, when I run the query, it produces the following SQL:
UPDATE "votes"
SET "week_1" = 'week_1 +20',
"week_2" = 'week_2 +50',
...
WHERE id = 1
As it also produces single quotes, it throws errors like this:
column 'week_1 +20' cannot found
How can I escape these single quotes and run the query successfully?
According to the official document here, you should pass FALSE (Bool) instead of "FALSE" (String) like this
$this->db->set("week_".$week , "week_".$week. " +".$increaseValue, FALSE);
Hope this helps!
Remove Double quotes from "FALSE" into FALSE
I have a data table (System.Data.DataTable) that is populated with data via load of a reader variable returned by executing a SQL query for a System.Data.SQLClient.SQLCommand.
While I am able to access the row column value to print it via the Write-Host cmdlet, I am unable to access the value to be used in arithmetic operations as in the example below. I will note that the column in question is derived from the SQL COUNT function (see snippet below) and the type returned is System.Int32.
SQL Query snippet:
SELECT Day(Date) AS DayofWeek, Researcher_DisplayName, COUNT(Researcher_DisplayName) AS Total FROM ...
PowerShell code:
[int32] $sumTotal = 0
foreach ($Row in $resultsDataTable) {
Write-Host ("Total value is: " + $Row["Total"]) # this line works, the value is printed
$sumTotal = $sumTotal + $Row["Total"] # this line does not work
}
Write-Host ("sumTotal value is: " + $sumTotal) # value printed is 0
I have a CSV that I read in. The problem is that this CSV as columns that are not filled with data. I need to go through a column and when the ID number matches the ID of the content I want to add, add in the data. Currently I have,
$counter = 0
foreach($invoice in $allInvoices){
$knownName += $info | where-Object{$_.'DOCNUMBR'.trim().contains($cleanInvNum)}
$DocNumbr = $info | where-Object{$_.'DOCNUMBR'.trim() -eq $cleanInvNum}
$output = $ResultsTable.Rows.Add(" ", " ", " ", " ", $DocNumbr[$counter].'ORG', $DocNumbr[$counter].'CURNT', $knownName[$counter].'DOCNUMBR', " ")
$counter++
}
The problem with this code is that it just adds rows under the CSV and does not add the data to the row. How can I do a statement where I find ID and add the above content into that row?
I was able to resolve my issue by reworking my foreach loop and setting the values directly like so,
$output.'CheckNumber' = $DocNumbr.'ORTRXAMT'
$output.'CheckDate' = $DocNumbr.'CURTRXAM'
$output.'Invoice Number' = $knownName.'DOCNUMBR'