speed up inserting data from Data Set to SQL powershell - powershell

When I run this script to insert data into table in SQL from DataSet, the process takes a long time to insert it (row by row) .the inserting time depend on the row counts , more rows more time .
is there any way to speed up the process or split the rows to multiple records and insert it parallel on same time .
for ( $i = 0; $i -lt $DataSet.Tables[0].Rows.Count; $i++) {
try {
$valuestr = New-Object -TypeName System.Text.StringBuilder
for ( $x = 0; $x -lt 11; $x++) {
if ($x -lt 10) {
[void]$valuestr.Append("'" + $DataSet.Tables[0].Rows[$i][$x].ToString().Trim().Replace("'", "/") + "',")
}
else {
[void]$valuestr.Append("'" + $DataSet.Tables[0].Rows[$i][$x].ToString().Trim().Replace("'", "/") + "'")
}
}
[string]$inputstr = $valuestr.ToString()
[char[]]$values = $inputstr.ToCharArray()
[string]$output = ''
foreach ($letter in $values) {
[int]$value = [Convert]::ToInt32($letter)
[string]$hexOutput = [String]::Format("{0:X}", $value)
switch ($hexOutput) {
"627" { $output += "ا"; Break }
default { $output += [Convert]::Tostring($letter); break }
}
}
$sqlCmdd.CommandText = "INSERT INTO $sqlTable ([ICN],[ICN_NODE],[PARTITION_ID],[ICN_CREATE_DT] ,[ICN_SEQ_NUM],[ICN_SUBNUM],[ICN_TAG_ID],[ICN_TAG_VER],[BLK_NUM],[BLK_LEN] ,[FREE_FORM_TXT]) Values (" + $output.ToString() + ")"
$sqlCmdd.ExecuteNonQuery()
}
catch { $_.Exception.Message | Out-File C:\log\log.txt -Append }
}

Related

PowerShell 5.0 Class Method Returns "Not all code path returns value within method"

As an experiment with PowerShell 5.0 classes I tried to translate JavaScript code for the Stable Marriage problem at Rosetta Code. It seemed very straight forward, but The second method (Rank) returns the error: Not all code path returns value within method.
class Person
{
# --------------------------------------------------------------- Properties
hidden [int]$CandidateIndex = 0
[string]$Name
[person]$Fiance = $null
[person[]]$Candidates = #()
# ------------------------------------------------------------- Constructors
Person ([string]$Name)
{
$this.Name = $Name
}
# ------------------------------------------------------------------ Methods
static [void] AddCandidates ([person[]]$Candidates)
{
[Person]::Candidates = $Candidates
}
[int] Rank ([person]$Person)
{
for ($i = 0; $i -lt $this.Candidates.Count; $i++)
{
if ($this.Candidates[$i] -eq $Person)
{
return $i
}
return $this.Candidates.Count + 1
}
}
[bool] Prefers ([person]$Person)
{
return $this.Rank($Person) -lt $this.Rank($this.Fiance)
}
[person] NextCandidate ()
{
if ($this.CandidateIndex -ge $this.Candidates.Count)
{
return $null
}
return $this.Candidates[$this.CandidateIndex++]
}
[int] EngageTo ([person]$Person)
{
if ($Person.Fiance)
{
$Person.Fiance.Fiance = $null
}
return $this.Fiance = $Person
}
[void] SwapWith ([person]$Person)
{
Write-Host ("{0} and {1} swap partners" -f $this.Name, $Person.Name)
$thisFiance = $this.Fiance
$personFiance = $Person.Fiance
$this.EngageTo($personFiance)
$Person.EngageTo($thisFiance)
}
}
The error is because if $this.Candidates.Count is 0, no return will execute.
Should the second return be outside of your for loop?
The current way, if it does not match the first candidate, it will return $this.Candidates.Count + 1.
[int] Rank ([person]$Person)
{
for ($i = 0; $i -lt $this.Candidates.Count; $i++)
{
if ($this.Candidates[$i] -eq $Person)
{
return $i
}
}
return $this.Candidates.Count + 1
}

IndexOutOfRange

I'm getting this error:
Array assignment failed because index '3' was out of range.
At Z:\CSP\deploys\aplicacional\teste.ps1:71 char:12
+ $UNAME[ <<<< $i]= $line
+ CategoryInfo : InvalidOperation: (3:Int32) [], RuntimeException
+ FullyQualifiedErrorId : IndexOutOfRange
I really can't find why the index end there.
$CSNAME = #(KPScript -c:GetEntryString $PASSHOME\$PASSFILE -pw:$PASS -Field:csname $SEARCH)
$UNAME = #()
$i = 0
Write-Host "Length="$CSNAME.Length
while($i -le $CSNAME.Length)
{
Write-Host "Start "$i
#$CSNAME[$i].GetType()
if ($CSNAME[0].StartsWith("OK:")) {
Write-Host "ACES $ACES does not exist" -Foreground "red"
}
if ($CSNAME[$i].StartsWith("OK:")) {
break
}
Write-Host "CSNAME="$CSNAME[$i]
$UNAME = $UNAME + $i
$UNAME = KPScript -c:GetEntryString $PASSHOME\$PASSFILE -pw:$PASS -Field:UserName -ref-csname:$CSNAME[$i]
foreach ($line in $UNAME) {
if (! ($line.StartsWith("OK:"))) {
Write-Host $i
$UNAME = $UNAME + $i
Write-Host "uname var"$i
$UNAME[$i] = $line
} else {
Write-Host "break"
break
}
}
#$UNAME[$i].GetType()
#if ($UNAME[$i].StartWith("OK:*")){
# break
#}
Write-Host "UNAME="$UNAME[$i]
#$UNAME[$i]
Write-Host "End "$i
$i += 1
Write-Host "switch"
}
Since the second while is based in the first array length and it has values, why is the it getting out of range?
PowerShell arrays are zero-based, so an array of length 3 has index values from 0 through 2. Your code, however, would iterate from 0 to 3, because the loop condition checks if the variable is less or equal the length (-le):
while($i -le $CSNAME.Length)
{
...
}
You need to check if the variable is less than the length (or less or equal the length minus one):
while($i -lt $CSNAME.Length)
{
...
}
Also, you'd normally use a for loop for iterating over an array, so you can handle the index variable in one place:
for ($i=0; $i -lt $CSNAME.Length; $i++) {
...
}
Edit: You initialize $UNAME as an array, but inside the loop you assign $UNAME = KPScript ..., which replaces the array with whatever the script returns (another array, a string, $null, ...). Don't use the same variable for different things in a loop. Assign the script output to a different variable. Also, your way of appending to the array is rather convoluted. Instead of $UNAME = $UNAME + $i; $UNAME[$i] = $line simply do $UNAME += $line.
$res = KPScript -c:GetEntryString $PASSHOME\$PASSFILE -pw:$PASS -Field:UserName -ref-csname:$CSNAME[$i]
foreach ($line in $res) {
if (! ($line.StartsWith("OK:"))) {
$UNAME += $line
} else {
break
}
}

Append number to end of string in Powershell for loop

Trying to append the index value of a for loop to the end of a string, but I'm having some trouble getting the desired result.
Here's a short code block of what I'm working with:
EDIT:
$apiKey = "ZZZ-ZZZZZ"
$octoHeader = #{ "X-Octopus-ApiKey" = $apiKey }
# GET Source deployment process from Deployment Scaffold project
$json = irm "http://octopusserver/api/deploymentprocesses/deploymentprocess-projects-123" -Headers $octoHeader
$DeploymentSteps = $json.Steps
# Hash table to hold steps
$steps = #{}
function Get-StepType
(
$StepType
)
{
foreach ( $Step in $DeploymentSteps | where { $_.Name -eq $StepType } )
{
return $Step
}
}
function Copy-Steps
(
$StepType,
$StepCount
)
{
$Step = Get-StepType -StepType $StepType
1..$StepCount | % {
$Step.Id = ''
$Step.Name += $_
# Add step to hash
$steps.Add("step$($steps.Count + 1)", $step)
}
}
Copy-Steps -StepType 'Service' -StepCount 2
$steps
And this is the result:
Name Value
---- -----
step1 #{Id=; Name=Service12; Actions=S...
step2 #{Id=; Name=Service12; Actions=S...
The result I'm after is: Name=Service - 1, Name=Service - 2, etc. I see what's happening, but I'm not sure the proper way to get what I'm after.
Any help is greatly appreciated.
In your function Copy-Steps you need to actually copy steps:
function Copy-Steps
(
$StepType,
$StepCount
)
{
$OriginalStep = Get-StepType -StepType $StepType
1..$StepCount | % {
$Step=$OriginalStep.PSObject.Copy()
$Step.Id = ''
$Step.Name += $_
# Add step to hash
$steps.Add("step$($steps.Count + 1)", $step)
}
}
1..5 | % { [String]::Format("Step {0}", $_) }
or thereabouts

PowerShell DataTable removing empty columns logic incorrect

This is the first time that I'm writing a function that can call itself. I'm trying to remove all the columns of a DataTable where the rows are empty.
The code works fine but spits out some errors. For one reason or another it's looping one last time through the for loop with the old $Columns number still in memory. Although I'm filling it again each time the function is called... I don't understand why..
The code:
Function Remove-EmptyColumns {
$Columns = $DataTable.Columns.Count
$Rows = $DataTable.Rows.Count
for ($c = 0; $c -lt $Columns; $c++) {
$Empty = 0
for ($r = 0; $r -lt $Rows; $r++) {
if ($DataTable.Rows[$r].Item($c).ToString() -eq '') {
$Empty++
}
}
if ($Empty -eq $Rows) {
$DataTable.Columns.Remove($DataTable.Columns[$c])
Remove-EmptyColumns
}
}
}
Thank you for your help.
Why is it a recursive method? Try removing the Remove-EmptyColumns and it should work, no?
EDIT: Try
Function Remove-EmptyColumns {
$Columns = $DataTable.Columns.Count
$Rows = $DataTable.Rows.Count
$columnsToRemove = #()
for ($c = 0; $c -lt $Columns; $c++) {
$Empty = 0
for ($r = 0; $r -lt $Rows; $r++) {
if ($DataTable.Rows[$r].Item($c).ToString() -eq '') {
$Empty++
}
}
if ($Empty -eq $Rows) {
$columnsToRemove.Add($DataTable.Columns[$c])
}
}
$columnsToRemove | ForEach-Object {
$DataTable.Columns.Remove($_) }
}
Just a thought, but I like to use the String static method of IsNullOrEmpty.
if ([string]::IsNullOrEmpty($DataTable.Rows[$r].Item($c).ToString()))
{ ... }
This removes issues where the value may not equal '' but be $Null instead and it does it in a single line.

Combination without Repetition using powershell?

I am new in powershell but was wondering how do you get combination of given numbers without repetition ?
for e.g
$a = (1,2,3,4)
$n = 4
$k = 2
output :-
12
13
14
23
24
34
if K = 3 then
123
124
134
234
Just a quick solution for that particular case, I don't see much value in it because I feel there are tools designed for such exercises... ;)
$a = (1,2,3,4)
$rest = New-Object Collections.ArrayList
$a[1..($a.Length - 1)] | foreach { $rest.Add($_) | Out-Null }
$prefix = $a[0]
$(while ($rest) {
foreach ($suffix in $rest) {
-join ($prefix, $suffix)
}
$prefix = $rest[0]
$rest.RemoveAt(0)
}) -join ', '
You can try this :
$List = "A","B","C","D","E","F","G","H"
$k = 3
Add-Type #"
public class Shift {
public static int Right(int x, int count) { return x >> count; }
public static uint Right(uint x, int count) { return x >> count; }
public static long Right(long x, int count) { return x >> count; }
public static ulong Right(ulong x, int count) { return x >> count; }
public static int Left(int x, int count) { return x << count; }
public static uint Left(uint x, int count) { return x << count; }
public static long Left(long x, int count) { return x << count; }
public static ulong Left(ulong x, int count) { return x << count; }
}
"#
function CombinationWithoutRepetition ([int]$k, $List)
{
Function IsNBits ([long]$value, $k, $length)
{
$count = 0
for ($i = 0 ; $i -le $length ; $i++)
{
if ($value -band 1)
{
$count++
}
$value = [shift]::Right($value,1)
}
if ($count -eq $k)
{
return $true
}
else
{
return $false
}
}
Function BitsToArray ([long]$value, $List)
{
$res = #()
for ($i = 0 ; $i -le $List.length ; $i++)
{
if ($value -band 1)
{
$res += $List[$i]
}
$value = [shift]::Right($value,1)
}
return ,$res
}
[long]$i = [Math]::Pow(2, $List.Length)
$res = #()
for ([long]$value=0 ; $value -le $i ; $value++)
{
if ((IsNBits $value $k $List.Length) -eq $true)
{
#write-host $value
$res += ,(BitsToArray $value $List)
}
}
return ,$res
}
Clear-Host
$res = CombinationWithoutRepetition $k $List
$res.count
$res | %{$_ |% {}{Write-Host -NoNewline $_}{Write-Host ""}}
I thought of this as binary strings with 1's and 0's, generated each binary string from 1 to Length of the array, and then use the value at the same index if there is a 1.
$items = 1,2,3,4;
$k = 3;
$output = #();
for ($i = 1; $i -lt [Math]::Pow(2, $items.Count); $i++) {
$binary = [Convert]::ToString($i, 2).PadLeft($items.Count, "0");
# if number of 1's in the entire string is not equal to "1" * $k, then skip
if (($binary -replace "0", "") -ne ("1" * $k)) {
continue;
}
#foreach char in binary
$outputSet = #()
$outputSet += $items | ForEach-Object {
if ($binary[$items.IndexOf($_)] -eq "1") {
$_
}
}
$output += [PSCustomObject]#{
Set = $outputSet;
Binary = $binary;
Count = $outputSet.Count;
Concatenated = $outputSet -join "";
}
}
$output | Sort-Object -Property Count, Set
#SAMPLE OUTPUT
Set Binary Count Concatenated
--- ------ ----- ------------
{1, 2, 3} 1110 3 123
{1, 2, 4} 1101 3 124
{1, 3, 4} 1011 3 134
{2, 3, 4} 0111 3 234