SQL Server DATEADD function not working with PDO Sqlsrv extension - sql-server

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.

Related

SQL Server Query in PowerShell, limit my results based on date

I am using PowerShell to connect to a SQL Server database, and I want to limit my result.
I use the SqlServer Module, and Invoke-Sqlcmd. I don't want data where the date is older than 90 days. The following code is used to get the complete data
$DataRange = ((Get-date) + (New-TimeSpan -Days -90))
$Database = DB02_Tool.dbo.Cert
$ServerInstans = DBClu01\DbClu01Cert
$Query = "SELECT encoded, not_before, not_after FROM " + $Database
$Data = Invoke-SqlCmd -ServerInstance $ServerInstans -Query $Query -As DataRows
The limit, I want to implement is on the not_before, which is of the datatype datetime, and I want it to limit on dates not older than 90 days back, as the $Daterange is used for.How do I limit the query? Any ideas?
You can do this in the SQL Query. Using DATEADD to add or substract days, and GetDate() to get the current datetime.
$Query = "SELECT encoded, not_before, not_after FROM " + $Database + " WHERE not_before >= DATEADD(Day, -90, GetDate())"
Or you can pass in a parameter from Powershell using -Variable switch. See the example 3 in the documentation.
You first need to convert the string to a universal datetime using ToString("u")
$StringArray = "MYVAR1='$($DataRange.ToString("u"))'"
$Query = "SELECT encoded, not_before, not_after FROM " + $Database + " WHERE not_before >= `$(MYVAR1)"
$Data = Invoke-SqlCmd -ServerInstance $ServerInstans -Query $Query -Variable $StringArray -As DataRows

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.

Stored procedure called from Powershell does not execute via SMO object

I'm trying to execute a stored procedure from a Powershell terminal by using the following code, but the procedure does not seem to execute and there is no error thrown in the terminal.
add-type -AssemblyName "Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
$so = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -argumentList 'PC-1001'
$db = New-Object Microsoft.SqlServer.Management.Smo.Database($so, "TestDB")
$sproc = $db.StoredProcedures.Item("dproc")
$sproc.Execute
The supporting SQL code is:
create table dummytable (id int identity(1,1), ranwhen datetime default getdate(), dummyval varchar(10));
create procedure dproc as
begin
set nocount on
insert into dummytable (dummyval)
select char(datepart(hour, getdate()) * datepart(minute, getdate()) * datepart(second, getdate()) % 256)
end
If I execute the procedure in SSMS (exec dproc) it works (data is inserted into the table).
Any ideas why it's not working from Powershell? (no data is being inserted into the dummy table)
Update:
I've changed the declaration of the $db and $sproc variable to:
$db = $so.Databases.Item("TestDB")
$sproc = $db.StoredProcedures.Item("dproc")
And when checking the contents of the $sproc object, I can see that every property is correct (T-SQL code is there, URN value is correct and references the correct DB and schema).
The StoredProcedure class does not provide a means of executing the stored procedure it represents.
You might try, and I have taken no steps to validate this is possible, using:
$so.ConnectionContext.ExecuteNonQuery("dproc")
Failing that, you might simply fall back to using System.Data.SqlClient.
I suggest you to use System.Data.SqlClient as well. I used to run stored procedures like this:
$SQL = New-Object System.Data.SqlClient.SqlConnection
$ConnectionStrig = "Server=localhost;Database=testtaskdb;Integrated Security=True;"
$SQL.ConnectionString = $ConnectionStrig
$SQL.Open()
$CMD = $SQL.CreateCommand()
$CMD.CommandText = "exec myproc"
#if you need to just run the stored procedure
$null=$CMD.ExecuteReader()
#if you need to get the output
$Table = New-Object System.Data.DataTable
$Table.Load($CMD.ExecuteReader())
Write-Output $Table

Unable to Get Information using PowerShell to Query Oracle

I use PowerShell to query SQL databases, and I am quite familiar with that process. However, I am now tasked with building an automated task that queries Oracle for information.
It seems straight forward: Install proper Oracle DLL's, import them into PS, execute the query much like SQL. However, this is not the case. All I get when I request information is a list called FieldCount. This seems to imply that I am able to see the information, it's just not displaying correctly. I'd like the actual values, and nothing seems to get this for me.
Thanks to anyone who knows anything about this, as my hands are tied and this is the only way I can think of to get this information from Oracle on a scheduled basis. I am not the Oracle admin, I only have read access to this view.
function Get-OracleData($cmdText){
Add-Type -Path 'C:\app\client\username\product\12.1.0\client_1\odp.net\managed\common\Oracle.ManagedDataAccess.dll'
$username = 'username'
$password = 'password'
$con = New-Object Oracle.ManagedDataAccess.Client.OracleConnection('User Id=$username;Password=$password;Data Source=OracleServerName')
$con.Open()
$cmd = New-Object Oracle.ManagedDataAccess.Client.OracleCommand
$cmd.Connection = $con
$cmd.CommandText = $cmdText
$rdr = $cmd.ExecuteReader()
if($rdr.Read()){
return $rdr
}else{return 0}
}
Get-OracleData -cmdText '
SELECT em.employee_number,
em.last_name,
em.first_name,
em.middle_names,
em.email_address,
em.start_date,
em.term_date,
em.location_addr_line_1,
em.location_city,
em.location_work_state,
FROM CustomView em
'
Found the answer in the link below. I was able to get what I needed by inserting the below code at the line where $cmd.CommandText = $cmdText is located in my original post, and getting rid of what's below it.
$ds = New-Object system.Data.DataSet
$da = New-Object Oracle.ManagedDataAccess.Client.OracleDataAdapter($cmd)
[void]$da.fill($ds)
return $ds.Tables[0] | Select *
This returns to a variable, and I can get the first entry using $results[0], and $results[0].EMPLOYEE_NUMBER, etc.
Reference: http://poshcode.org/3965 #line55

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