how to pass datetime format using perl script to sql server? - sql-server

#!/usr/bin/perl
use DBI;
use Data::Dumper;
use strict;
my $DSN = q/dbi:ODBC:SQLSERVER/;
my $uid = q/username/;
my $pwd = q/password/;
my $first_param=723454;
my $current_date="2012-10-25 00:30:21";
my $after_2min="2012-10-25 05:47:41";
my $dbh = DBI->connect($DSN,$uid,$pwd) or die "Coudn't Connect SQL";
my $sql2 = "insert reverise_call_main_menu call_number,call_originate_time,call_inbetween_time,call_after_2min_time) values(?,?,?,?)";
my $sth2 = $dbh->prepare($sql2);
$sth2->execute($first_param,$current_date,'null',$after_2min);
$sth2->finish;
$dbh->disconnect;
whenever i execute a program i got following error:
output:-
DBD::ODBC::st execute failed: [unixODBC][FreeTDS][SQL Server]Conversion failed when converting datetime from character string. (SQL-22007)

The error message indicates that SQL Server does not like the format of your datetime strings. You may wish to use DateTime::Format::DBI to help get the formatting right.

Related

How to stream web service data via PowerShell into a SQL Server VarBinary column

We have a working solution in PowerShell to stream web service (WS) data into a SQL Server 2019 table with a column of datatype NVARCHAR(max). This WS data is just business data in Json format. I'd like to enhance this solution to also be able to stream the WS data into a VARBINARY(max) column.
The currently working code looks like this (abbreviated):
$SQL_ImpInsert = #"
Insert Into [Database].dbo.ImportTable (SeqNo, BulkDataNVarChar)
Values (#SeqNo, #WSData)
"#
# Create the SQL objects.
$SQLConn = New-Object System.Data.SqlClient.SqlConnection $ConnStr
$SQLConn.Open()
$SQLCommand = $SQLConn.CreateCommand()
$SQLCommand.CommandText = $SQL_ImpInsert
# Prep the stream
$WS_URL = 'https://a_valid_ws_request'
$WebRequest = [System.Net.WebRequest]::Create($WS_URL)
$WebRequest.ClientCertificates.Add($WS_Cert) | Out-Null
$WebRequest.Method = "Get"
$WebResponse = $WebRequest.GetResponse()
$WebStream = $WebResponse.GetResponseStream()
$WebStreamRdr = New-Object System.IO.StreamReader $WebStream
# Prep the SQL command to use the stream
$SeqNo = 1
$SQLCommand.Parameters.Clear()
$SQLCommand.Parameters.Add("#SeqNo", [Data.SQLDBType]::INT, -1).Value = $SeqNo
$SQLCommand.Parameters.Add("#WSData", [Data.SQLDBType]::NVARCHAR, -1).Value = $WebStreamRdr
# Perform the streamed insert from the WS into the SQL table
$ExecOutput = $SQLCommand.ExecuteNonQuery();
To attempt to enhance the solution I added a VARBINARY column to the table and changed the command parameter datatype to VARBINARY as follows (only changes to above code shown):
$SQL_ImpInsert = #"
Insert Into [Database].dbo.ImportTable (SeqNo, BulkDataBlob)
Values (#SeqNo, #WSData)
"#
$SQLCommand.Parameters.Add("#WSData", [Data.SQLDBType]::VARBINARY, -1).Value = $WebStreamRdr
When I run the new version of the PowerShell script I get the following error raised during the ExecuteNonQuery statement:
Exception calling "ExecuteNonQuery" with "0" argument(s): "Failed to convert parameter value from a StreamReader to a Byte[]."
I've looked into the command Parameters.Add arguments to see if there was anything I needed to adjust there. There are some variations to the Add method but I don't know\think they are relevant.
I don't know enough about the streaming calls to know if there is anything that should be tweaked there. Since I'm only changing the destination SQL column datatype I'm expecting the setup of the stream to remain the same.
I checked the WS data and there shouldn't be any data bigger than the SQL datatype VARBINARY can handle. I don't think the error has anything to do about the data size coming in though.
Any ideas on how to adjust this code to stream the WS data into the VARBINARY parameter and therefore the SQL column?
StreamReader implements a TextReader, which gives you a string that will fail to convert to your varbinary byte array. I am guessing that your first example using nvarchar succeeds because you get an implicit conversion of the string.
You can likely refactor this to not use the StreamReader at all, but to answer the question you will need to convert that string to a byte array:
$output = $WebStreamRdr.ReadToEnd() # todo: flush & close
$bytes = [system.Text.Encoding]::UTF8.GetBytes($output)
Then use $bytes:
$SQLCommand.Parameters.Add("#WSData", [Data.SQLDBType]::VARBINARY, -1).Value = $bytes
You could also let the string pass into the command as before:
$SQLCommand.Parameters.Add("#WSData", [Data.SQLDBType]::NVARCHAR, -1).Value = $WebStreamRdr
Then let the command convert it to varbinary:
$SQL_ImpInsert = #"
Insert Into [Database].dbo.ImportTable (SeqNo, BulkDataBlob)
Values (#SeqNo, cast(#WSData as varbinary(max)))
"#

SQL Server migration 2008 to 2016 - raiserror syntax error

We are going to migrate from SQL Server 2008 to 2016. I am in the process of identifying errors and I get the following error in a trigger:
Incorrect syntax near '51001'.
I looked through the Raiserror documentation on the Microsoft website and it did not help. The following is the SQL. Any help would be appreciated.
IF (SELECT count(*) FROM dbo.u_sample_concrete ref, deleted
WHERE ref.lab_cd = deleted.lab_id) > 0
BEGIN
RAISERROR 51001 ''Trigger td_tblLAB on table dbo.tblLAB: Primary key values found in table dbo.u_sample_concrete (lab_cd). Delete restricted; the transaction is being rolled back.''
ROLLBACK TRANSACTION
RETURN
END
Adding to #DaleK's answer with the proper syntax, the problem RAISERRROR syntax is long obsolete. IIRC, it was deprecated 20 years ago (with the SQL Server 2000 release) and removed entirely in SQL Server 2012.
Below is a powershell script that uses the T-SQL Script DOM (also available with the Dacfx NuGet package) to identify existing T-SQL modules with invalid syntax. It won't catch problems in dynamic SQL, though.
$connectionString = "Data Source=.;Initial Catalog=YourDatabase;Integrated Security=SSPI"
try {
$query = #"
SELECT
QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + N'.' + QUOTENAME(OBJECT_NAME(object_id)) AS ObjectName
, OBJECTPROPERTY(object_id, 'ExecIsQuotedIdentOn') AS ExecIsQuotedIdentOn
, definition
FROM sys.sql_modules;
"#
Add-Type -Path "C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
$connection = New-Object Data.SqlClient.SqlConnection($connectionString)
$command = New-Object Data.SqlClient.SqlCommand($query, $connection)
$connection.Open()
$reader = $command.ExecuteReader()
while ($reader.Read()) {
# use TSqlParser appropriate for your SQL Server version
$parser = New-Object Microsoft.SqlServer.TransactSql.ScriptDom.TSql130Parser($reader["ExecIsQuotedIdentOn"])
$parseErrors = New-Object Collections.Generic.List[Microsoft.SqlServer.TransactSql.ScriptDom.ParseError]
$scriptReader = New-Object IO.StringReader($($reader["definition"]))
Write-Host "Parsing $($reader["ObjectName"]) ..."
[void]$parser.Parse($scriptReader, [ref]$parseErrors)
if($parseErrors.Count -ne 0) {
Write-Host "Parsing errors for object $($reader["ObjectName"]): $($parseErrors | ConvertTo-Json)" -ForegroundColor Yellow
}
}
$connecton.Close()
}
catch {
throw
}
The Microsoft Documentation does indeed show 4 things wrong with your statement.
The parameters must be inside brackets raiserror().
4 parameters are expected when msd_id (51001) is used - you are providing 2.
Parameters should be separated by commas ,.
You are double quoting the string, when it should be single quoted.
RAISERROR (51001, -1,- 1, 'Trigger td_tblLAB on table dbo.tblLAB: Primary key values found in table dbo.u_sample_concrete (lab_cd). Delete restricted; the transaction is being rolled back.')
Note: its best practice now to use throw rather than raiserror.

How to query SQL Server using PowerShell?

I found some code online but so far I can't get it to connect to my SQL Server database. I have followed this website to the letter: https://blogs.msdn.microsoft.com/walzenbach/2010/04/14/how-to-enable-remote-connections-in-sql-server-2008/
I have allowed remote connections, added port 1433 to my firewall etc. I then run this code from PowerShell ISE:
$dataSource = “\\SCCM12-01\MSSQLSERVER”
$user = “MyID\OurDomain.org”
$pwd = “MyPassword”
$database = “CM1”
$connectionString = “Server=$dataSource;uid=$user; pwd=$pwd;Database=$database;Integrated Security=False;”
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
when I run this I get the following error.
Exception calling "Open" with "0" argument(s): "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was
not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 25 - Connection
string is not valid)"
If you have simple query to do I recommend Select-SQLView powershell module. It allows to quickly select rows from table or view. It stores your database and server name so you do not have to provide this values every time.
As usual You can push results to table or to GridView.
If more complex queries are needed use SQLCommands module.
Not sure why you are getting this error. You can refer to this link https://github.com/Tervis-Tumbler/InvokeSQL
You can try this one-
function Invoke-SQL {
param(
[string] $dataSource = ".\SQLEXPRESS",
[string] $database = "MasterData",
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$dataSource; " +
"Integrated Security=SSPI; " +
"Initial Catalog=$database"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null
$connection.Close()
$dataSet.Tables
}
The error message actually explains what's wrong:
"SQL Network Interfaces, error: 25 - Connection string is not valid".
There is something amiss on the connection string. What exactly is hard to say as you have masked most of the details. Maybe the smart quotes wreck things? Maybe you got a quote character in the password? Anyway, it looks like you have invalid parameter for the user id:
$connectionString = “Server=$dataSource;uid=$user; pwd=$pwd;Database=$database;Integrated Security=False;”
Try User Id instead of uid like so,
Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;
You properly just need to change 'Integrated Security' to 'true' when not using a db login
**Integrated Security=True**

SQL Server DATEADD function not working with PDO Sqlsrv extension

I am using PDO with Sqlsrv extension to connect to a SQL Server database. This query works fine when I run it in any SQL Server database client but in PHP source code it does not produce result.
SELECT session
FROM t_php_session
WHERE php_session_id = 'p64aqbh15u6t35tq2h8n0bluq0'
AND user_ip = '127000000001'
AND DATEADD(MINUTE, 30, created) >= GETDATE()
While debugging I observed that when I remove the DATEADD condition from the WHERE clause, then it works fine and return the result. But I am not sure what is wrong with this condition.
Here is my sample source code:
$session_id = 'p64aqbh15u6t35tq2h8n0bluq0';
$interval = 30;
$ip = '127000000001';
$query = "SELECT session FROM t_php_session WHERE php_session_id = ? AND user_ip = ? AND DATEADD(MINUTE, ?, created) >= GETDATE()";
$stmt = $conn->prepare($query);
$stmt->execute(array($session_id, $ip, $interval));
$result = $stmt->fetchAll();
echo "<pre>";
print_r($result);
This is my SQL Server database table structure:
I also tried assigning values by using bindParam method instead of passing an array in execute statement but that could not work too.
SOLUTION
After getting solution from #Your Common Sense i made following changes and it worked.
$query = "SELECT session FROM t_php_session WHERE php_session_id = ? AND user_ip = ? AND DATEADD(MINUTE, ?, created) >= GETDATE()";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $session_id, PDO::PARAM_STR);
$stmt->bindParam(3, $interval, PDO::PARAM_INT);
$stmt->bindParam(2, $ip, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll();
The other answer obviously makes the whole idea of prepared statements spoiled.
Your code should positively work, if you bind a number using PDO::PARAM_INT.
At least in emulation mode this would work.

Connect perl to SQL Server management 2012

I am new to perl. I am given a task to connect to SQL server management 2012 and print a table from the database. Can you please guide me how to install all the drivers required and advise me what is wrong with my code, as i get no error and no required output.
use DBI;
my $host = 'programer'; #servername
my $database = 'DW'; #database name
my $user = 'prg'; #username
my $pwd = 'prg#123'; #password
my $dsn = "dbi:ODBC:Driver={SQL Server};Server=$host;Database=$database";
my $dbh = DBI->connect($dsn, $user, $pwd) or die("database not found");
$query="select * from Banking_AccountSummary_Citibank";
$exe=$dbh->prepare($query) or die("cannot prepapre query");
$exe->execute()or die("cannot execute");
$dbh->disconnect
Please guide me...
There is nothing wrong with your code. You don't need to install anything if you have use strict and use warnings and your code does not issue any warnings and does not die.
All you need to do is fetch your results and output them, or do whatever you want to do.
use Data::Dump;
my $exe = $dbh->prepare("select * from Banking_AccountSummary_Citibank")
or die("cannot prepapre query");
$exe->execute()
or die("cannot execute");
while (my $res = $exe->fetchrow_hashref) {
dd $res;
}
There are several ways to fetch your data and fetchrow_hashref is only one of them. I suggest you read the documentation of DBI and look at the examples given there.
Note: the convention is to name your statement handles $sth, just like the database handle is named $dbh. That will help others read your code.

Resources