Script powershell import multiple CSV - powershell

I'm doing a script to import CSVs (commands) that update the stock in SQL Server. But I encounter this error when I run the following script:
Invoke-Sqlcmd : La conversion de la valeur varchar '2200100001' a dépassé une colonne int.
L'instruction a été arrêtée.
Au caractère C:\Users\admin\Desktop\updateDb.ps1:36 : 19
+ ... $impcsv = Invoke-Sqlcmd -Database $db_name -Query $query -ServerIns ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
+ FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Here is my powershell script:
$sql_instance_name = 'SERVER\SAGE100'
$db_name = 'SERVER_DB'
$table = "dbo.F_ARTSTOCK"
$csv_folder = 'F:\EUR'
$csv_completed_folder = 'F:\EUR\done'
$batchsize = 50000
$csv_files = Get-Childitem -Path $csv_folder -Filter '*.csv'
$connectionstring = "Data Source=$sql_instance_name;Integrated Security=true;Initial Catalog=$db_name;"
$bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($connectionstring, [System.Data.SqlClient.SqlBulkCopyOptions]::TableLock)
$bulkcopy.DestinationTableName = $table
$bulkcopy.bulkcopyTimeout = 0
$bulkcopy.batchsize = $batchsize
foreach($file in $csv_files) {
$impcsv = $file.FullName
write-host "Processing file ..........$impcsv" -foregroundcolor green
$data = import-csv -Delimiter ";" $impcsv
$count = 1
foreach($i in $data) {
Write-Host $i.Reference
$reference = $i.Reference
$quantity = $i.Quantity
$query = "UPDATE dbo.F_ARTSTOCK (AR_Ref,AS_QteSto)
SET dbo.F_ARTSTOCK.AS_QteSto = dbo.F_ARTSTOCK.AS_QteSto - $quantity
WHERE dbo.F_ARTSTOCK.AR_Ref = $reference"
Write-Host $query
$impcsv = invoke-sqlcmd -Database $db_name -Query $query -ServerInstance $sql_instance_name
write-host "Processing row ..........$count" -foregroundcolor green
$count = $count + 1
}
}
Do you have any idea where the problem would come from?
Thank you for your help.

The error message is in french. Translated it reads: The conversion of the '2200100001' varchar value has exceeded an int column. The instruction has been stopped.
Basically what that means is you have a 32-bit int column on that table and it needs to be of bigint type to handle a larger value... Or go through the data that you're trying to submit and verify that it is accurate (aka: remove that row from the csv. Depending on how sensitive of data you are working on).

Related

Powershell scrip to run a query in multiple servers

Trying to run the following query in multiple databases but receiving the following error : Invoke-SqlCmd : Value cannot be null.
$query = #' SQL SCRIPT ' #
$csvFilePath = 'PATH FOR CSV FILE'
$serverlist = echo (list of servers )
$queryresults = $null
$InvokeParams = #{
SERVER = $serverlist
Database = 'TEST DATABASE'
Username = 'username '
Password = 'password1'
Query = $query
QueryTimeout = 100
}
foreach($server in $serverlist)
{
write-host "Executing query against server: " $server
$queryResults = Invoke-SqlCmd #InvokeParams -Erroraction stop
}
write-host "Saving Query Results in CSV format..."
$queryResults | export-csv $csvFilePath -NoTypeInformation
write-host "Converting CSV output to Excel..."
Do I always have to specify parameters ? What if my query is about creating a table for example ?

Powershell connectivity to SQL server and count extract

I am trying to fetch count of table from SQL server by connecting using Powershell, but I am getting the below error message, but if I just do select on the table instead of count then the same code is returning results, please suggest as I am not getting a solution to this problem.
Error Message:
Exception calling "Fill" with "1" argument(s): "Execution Timeout
Expired. The timeout period elapsed prior to completion of the
operation or the server is not responding."
+ $DataAdapter.Fill($Dataset)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException
Script:
[string] $Server= "Server_nm"
[string] $Database = "DB_nm"
[string] $UserSqlQuery = $("SELECT count(1) AS cnt FROM [tbl]")
##$resultsDatatable = ExecuteSqlQuery $Server $Database $UserSqlQuery
function GenericSqlQuery ($Server, $Database, $SQLQuery) {
$Datatable = New-Object System.Data.DataTable
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$Server';database='$Database';trusted_connection=true;"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = $SQLQuery
$DataAdapter = new-object System.Data.SqlClient.SqlDataAdapter $Command
$Dataset = new-object System.Data.Dataset
$DataAdapter.Fill($Dataset)
$Connection.Close()
return $Dataset.Tables[0]
} $resultsDatatable = GenericSqlQuery $Server $Database $UserSqlQuery
#validate we got data
Write-Host ("The table contains: " + $resultsDatatable.Rows.Count + " rows")
You can use the Invoke-Sqlcmd function instead.
# initialize Variables
[string] $Server= "Server_nm"
[string] $Database = "DB_nm"
[string] $UserSqlQuery = $("SELECT count(1) AS cnt FROM [tbl]")
# Invoke-SqlCmd
$resultsDatatable = Invoke-Sqlcmd -ServerInstance $Server -Database $Database -Query $UserSqlQuery
# validate we got data
Write-Host ("The table contains: " + $resultsDatatable.cnt + " rows")

Confirm existence of subdirectories

I am writing a script to query a SQL server to aggregate data that I can use to search through various directories. If the folder does not exist it should write the path that does not exist to a text file at the end of the code.
I created an array to prefill the strings of the paths which are completed by using the SQL data. I'm coming into the issue of input sting was not in a correct format and the issue of it not correctly filling the text document. It will fill the text document with folders that both do and do not exist.
I have tried various configurations. I believe the array could be my issue but I am currently unsure.
Error is as follows:
Cannot convert value "Walker" to type "System.Int32". Error: "Input string was not in a correct format."
At \\cottonwood\users\C.B\My Documents\Untitled1.ps1:36 char:115
+ ... Address)#> + $($Row.'Last Name') + $array[$i]
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToInteger
Code is as follows:
$SQLServer = "REDWOOD" #use Server\Instance for named SQL instances!
$SQLDBName = "MARS"
$SqlQuery = "select Account, IsActive, [Last Name] FROM vw_loans WHERE ( Account NOT IN ('100040A','100041A','100044A','100044B','100044C','100079A','100040A','100041A','100044A','100044B','100044C','100079A','100153B','100413B')) AND LEFT(Account,1)<>'_' AND (Account NOT like '%B%') AND (LoanStatus != 'PRELIM') ORDER BY Account"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
$DataSet.Tables[0]
$array = "\I. Originations\Final Originations Package","\II. Servicing\A. Communications", "\II. Servicing\B. Foreclosure Documents","\II. Servicing\C. Bankruptcy Documents", "\II. Servicing\D. Amendments & Extensions", "\II. Servicing\E. Property", "\II. Servicing\F. Previous Servicer Data", "\III. Loan Documents", "\IV. Taxes, Insurance, HOA\HOA", "\IV. Taxes, Insurance, HOA\Insurance","\IV. Taxes, Insurance, HOA\Insurance\PMI","\IV. Taxes, Insurance, HOA\Taxes"
foreach ($Row in $dataset.Tables[0].Rows)
{
for($i=0;$i -lt $array.Length; $i++)
{
if($Row.IsActive -eq $True)
{
$CorrPath = "U:\Shared\Loan Documents - Active\" + $($Row.Account) + " - " + <#$(Row.Address)#> + $($Row.'Last Name') + $array[$i]
}
if($Row.IsActive -eq $False)
{
$CorrPath = "U:\Shared\Loan Documents - Inactive\" + $($Row.Account) + " - " + <#$(Row.Address)#> + $($Row.'Last Name') + $array[$i]
}
$FileExist = Test-Path $CorrPath
If($FileExist -eq $False)
{Add-Content $Corrpath -Path "\\cottonwood\users\IT\Missing Folder Location\MissingSubFolders.txt"}
}
}
Looks to me like the parser is confused by what the + operator is supposed to be doing. It's trying to add when it should be concatenating. Try forcing everything to a string:
if($Row.IsActive) {
$CorrPath = "U:\Shared\Loan Documents - Active\" + $($Row.Account.ToString()) + " - " + <#$(Row.Address)#> + $($Row.'Last Name'.ToString()) + $array[$i].ToString()
} else {
$CorrPath = "U:\Shared\Loan Documents - Inactive\" + $($Row.Account.ToString()) + " - " + <#$(Row.Address)#> + $($Row.'Last Name'.ToString()) + $array[$i].ToString()
}
Or else try formatting the filename differently:
$CorrPath = "U:\Shared\Loan Documents - Active\{0} - {1}{2}" -f $Row.Account,$Row.'Last Name',$array[$i]

How do I get around this error in PowerShell? Exception setting "Rtf": "Error creating window handle."

This has no issue with SQL. it's when creating the rtf object.
I am connecting to a sql database and pulling information. Some of the information is html,rtf, and plain text. After about 10 mins of running I get this:
Exception setting "Rtf": "Error creating window handle."
At line:24 char:76
+ ... Name System.Windows.Forms.RichTextBox; $rtf.Rtf = $convo.Body; $body ...
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
Has anyone else ran into this issue?
Here is the script itself.
#Who are you searching for?
#Example User ID: user#domain.com
$Subject = "changeme#domain.com"
#Set the date to search from
#Example date format: 2016-08-16.
#Leave it blank if you don't want to search for just dates.
$Date = ""
#Blank array to store the conversation history
$arr = #()
#Lync Archive Server
$SQLSvr = "ServerName Goes Here"
#Lync Archive Database
$Database = "LcsLog"
#Get the UserId's
$UserUri = Invoke-Sqlcmd -Query "Select UserUri,UserId From dbo.Users u;" -ServerInstance $SQLSvr -Database $Database
#Build the Select Statement
$select = "Select * from dbo.Users d left join dbo.Messages m on FromId = d.UserId or ToId = d.UserId Where d.UserUri = '$Subject' "
if($Date)
{
$select = $select +"and m.MessageIdTime >= '$Date 00:00:01.550' order by m.MessageIdTime asc;"
}
else
{
$select = $select + "order by m.MessageIdTime asc;"
}
#Get the conversation history
$ConvoData = Invoke-Sqlcmd -Query ($select) -ServerInstance $SQLSvr -Database $Database;
#Loop through each conversation
foreach($convo in $ConvoData)
{
#Loop through each user.
foreach($user in $UserUri)
{
#Verify the FromId
if($convo.FromId -eq $user.UserId)
{
$FromID = $user.UserUri
}
#Verify the ToId
if($convo.ToId -eq $user.UserId)
{
$ToId = $user.UserUri
}
}
#Parse the body for legible reading
switch ($convo.ContentTypeId)
{
'1' {$html = New-Object -ComObject "HTMLFile"; $html.IHTMLDocument2_write($convo.Body);$body = $html.IHTMLDocument2_body.innerText; $html.close();}
'2' {$rtf = New-Object -TypeName System.Windows.Forms.RichTextBox; $rtf.Rtf = $convo.Body; $body = $rtf.Text; $rtf.Clear();}
'3' {$body = $convo.Body}
}
#Build the Message Output
$obj = New-Object -TypeName psobject -Property #{User = $Subject; "Message Time" = $convo.MessageIdTime; From = $FromID; To = $ToId; Body = $body}
#Add data to the array
$arr += $obj
}
$arr | Select User,"Message Time",From,To,Body | Export-csv "$env:userprofile\desktop\$Subject - conversation report.csv"
Not really an answer, but a recommendation that you should turn your parameters into a Param block. It would be more useful if you wanted to call the script from the command line or turn it into a function.
Param (
# Parameter Subject
[Parameter(Mandatory = $true,
HelpMessage = 'Who are you searching for? e.g. User ID: user#domain.com')]
$Subject = 'changeme#domain.com',
# Parameter Date
[Parameter(HelpMessage = 'Set the date to search from. e.g. "2016-08-16"')]
[String]
$Date,
# Parameter SQLSvr
[Parameter(Mandatory = $true,
HelpMessage = 'ServerName Goes Here')]
$SQLSvr,
# Parameter Database
[Parameter(Mandatory = $true,
HelpMessage = 'Lync Archive Database')]
$Database = 'LcsLog'
)
I figured it out. By creating one instance of my RTF object at the beginning it corrected my error.
#Who are you searching for?
#Example User ID: user#domain.com
$Subject = "changeme#domain.com"
#Set the date to search from
#Example date format: 2016-08-16.
#Leave it blank if you don't want to search for just dates.
$Date = ""
#Blank array to store the conversation history
$arr = #()
#Create RTF and HTML Objects
$html = New-Object -ComObject "HTMLFile";
$rtf = New-Object -TypeName System.Windows.Forms.RichTextBox;
#Lync Archive Server
$SQLSvr = "Server Name goes here"
#Lync Archive Database
$Database = "LcsLog"
#Get the UserId's
$UserUri = Invoke-Sqlcmd -Query "Select UserUri,UserId From dbo.Users u;" -ServerInstance $SQLSvr -Database $Database
#Build the Select Statement
$select = "Select * from dbo.Users d left join dbo.Messages m on FromId = d.UserId or ToId = d.UserId Where d.UserUri = '$Subject' "
if($Date)
{
$select = $select +"and m.MessageIdTime >= '$Date 00:00:01.550' order by m.MessageIdTime asc;"
}
else
{
$select = $select + "order by m.MessageIdTime asc;"
}
#Get the conversation history
$ConvoData = Invoke-Sqlcmd -Query ($select) -ServerInstance $SQLSvr -Database $Database;
#Loop through each conversation
foreach($convo in $ConvoData)
{
#Loop through each user.
foreach($user in $UserUri)
{
#Verify the FromId
if($convo.FromId -eq $user.UserId)
{
$FromID = $user.UserUri
}
#Verify the ToId
if($convo.ToId -eq $user.UserId)
{
$ToId = $user.UserUri
}
}
#Parse the body for legible reading
switch ($convo.ContentTypeId)
{
'1' {$html.IHTMLDocument2_write($convo.Body);$body = $html.IHTMLDocument2_body.innerText; $html.close();}
'2' {$rtf.Rtf = $convo.Body; $body = $rtf.Text; $rtf.Clear();}
'3' {$body = $convo.Body}
}
#Build the Message Output
$obj = New-Object -TypeName psobject -Property #{User = $Subject; "Message Time" = $convo.MessageIdTime; From = $FromID; To = $ToId; Body = $body}
#Add data to the array
$arr += $obj
}
$arr | Select User,"Message Time",From,To,Body | Export-csv "$env:userprofile\desktop\$Subject - conversation report.csv"

Shortcut to add files into local sql database

I would like to be able to right click on a file(s) and "send-to" a local MSSQL database. The details are that I would like to store the file contents in "contents" column and the file name in the "filename" column ... how novel :)
*In most cases the file contents is HTML.
It seems like it should be possible through windows shell/SQL Shell using a shortcut to a command in the "shell:sendto" folder.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$Server1 = New-Object ("Microsoft.SqlServer.Management.Smo.Server") 'SQLSERVER'
$Server1.databases["DB"].tables["Table"].rowcount
$RowCount = $server1.databases["DB"].tables["Table"].rowcount.ToString()
$TotalRecords = [int]$RowCount
$wc = New-Object system.net.WebClient
$url = ""
$files = #(Get-ChildItem c:\test\*.*)
"Number of files $($files.length)"
# Errors out when no files are found
if($files.length -lt 1) { return }
foreach($file1 in $files) {
# $txt = Get-Content($file1)
# $txt = $txt.Replace("'", "''")
# Write-Host $file1.name + " - - " + $Txt
$url1 = $url + $file1
Write-Host("URL is " + $url1)
$webpage = $wc.DownloadData($url1)
$string = [System.Text.Encoding]::ASCII.GetString($webpage)
$string = $string.Replace("'", "''")
Invoke-SqlCmd -ServerInstance SERVER -Query "Insert into DATABASE.dbo.Table(text,filename) Values ('$string','$file1')"}