Accessing Data Table Column Value for Use in Arithmetic Operartions - powershell

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

Related

powershell - get a keyword from query string

I'm learning PowerShell scripting & want to extract tableName from SQL Query String. For example, I've this query -
$q = "SELECT * FROM [TestDB].[dbo].Invoice_Details where Clientname='ABC'"
where I want to extract table name i.e. it should output this - Invoice_Details
Currently, I'm doing this with following working code -
$q1 = $q -split '\[dbo\]\.'
$q2 = $q1[1] -split ' where '
write-host $q2[0] #here I get it right (Invoice_Details)
But, sometimes the query may/ may not have bracketed names like - [TestDB].[dbo].
So, I want to optimize this code so that it will work even if query containing any combination of bracketed/ bracketless tableNames
Try something like this:
$res = ([regex]'(?is)\b(?:from|into|update)\s+(\[?.+\]?\.)?\[?(\[?\w+)\]?').Matches($q)
write-host $res[0].Groups[2].Value

PhpOrient query returns negative Rid-s by default

I'm trying to retrieve a simple graph consisting of some Assignments that are linked to each other, however after querying one set of those assignments, the Rid-s that are returned are all negative and have nothing to do with the Rid-s in the database, so I can't run other query-s based on those Rid-s, how should I go around this, or am I doing something wrong?
Here is the code snippet responsible:
$records = $this->client->queryAsync('select rID, value, schedule, priority, type from Assignment where type = 5');
foreach ($records as $record)
{
$id = $record->getRid();
$rid = $id->__toString();
$return[$rid] = $this->client->query('TRAVERSE out("Assignment") FROM ' . $rid . ' WHILE $depth <= 5');
}
and the error that I receive:
com.orientechnologies.orient.core.exception.ORecordNotFoundException: The record with id '#-2:0' was not found
However in the database the first id is: #18:0
Hi Pirate's Lost Pearl,
is probably a problem with the transactions, orientdb makes negative RID-s when they are temporary. After the commit, the RID-s are changed to positive, here the doc
There are a couple of errors in your code:
First off you should change your __toString(); into _toString(); using a single underscore.
Then fix the $this->client->query by either switching quotation marks at the end such as " WHILE $depth <= 5" or concatenate the variable while keeping the same quotes ' WHILE ' . $depth . ' <= 5'.
OrientDB Docs | getRid()

Indexing into a PowerShell value collection

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

Add data to csv column based on row value

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'

DBI::Sybase data-conversion resulted in overflow

I am writing a Perl script that is using the DBI module and is connecting to a Sybase DB. I am calling a stored procedure (one that I don't have access to so I cannot post sample code) and when I get data back I get an error that reads "error_handler: Data-conversion resulted in overflow". I still get data back and after doing some intensive research it seems that some data types in the columns (such as BigInt, nvarchar, etc) are the culprits. Now the question is, how can I fix this? Can this be fixed on the client side or can it only be fixed on the server side?
my $dbh = DBI->connect("DBI:Sybase:server=$server", $username, $password, {PrintError => 0}) or die;
$dbh->do("use $database") or die;
my $sql = &getQuery;
my $sth = $dbh->prepare($sql) or die;
$sth->execute() or die;
while ($rowRef = $sth->fetchrow_arrayref) #Error seems to occur here
{
#Parse through each row
}
Part of the FreeTDS 0.82 log that explains the problem:
_ct_bind_data(): column 7 is type 38 and has length 8
_ct_get_server_type(0)
_ct_get_client_type(type 38, user 0, size 8)
cs_convert(0x18dfed40, 0x7fff73216050, 0x18e44250, 0x7fff73215fa0, 0x18e387c0, 0x18e45a64)
_ct_get_server_type(30)
_ct_get_server_type(0)
converting type 127 (8 bytes) to type = 47 (9 bytes)
cs_convert() calling tds_convert
cs_convert() tds_convert returned 10
cs_prretcode(0)
cs_convert() returning CS_FAIL
cs_convert-result = 1
The problem is on the FreeTDS side. I've had the same problem before and successfully fixed it by converting the returned fields to varchar in the select statement.
Given you don't have access to modify the original query, you can do some regex search and replace on the returned $sql variable in your code. In particular, if the original query has a part that looks like
SELECT field1, field2, field3 FROM ...
After you retrieve the query statement, you may run
my $new_sql;
if ($sql =~ /SELECT\s+(.*)\s+FROM/i) { # match selected field string
my $field_str = $1;
my #fields = split ",", $field_str; # parse individual fields
map s/\s//g, #fields; # get rid of spaces
my $new_str = join ", ", (map {sprintf "convert(varchar, $_)"} #fields); # construct new query string
my $quoted_field_str = quotemeta($field_str); # prepare regex replacement string
$new_sql = $sql;
$new_sql =~ s/$quoted_field_str/$new_str/i # actual replacement
}
print $new_sql;
Of course, if your original statement is more complex, you should print it out and check how to modify it with a generic replacement bearing the same spirit. Alternatively, you can ask your DBA (or whoever has access to the stored procedure) to modify the actual query directly.
Hope this helps.