"Cursor type changed" error on Perl OLE32 MSSQL dateadd function results - sql-server

The following sql "select DATEADD(day, DATEDIFF(day, 2, GETDATE()), '20:00:00') as A" runs perfectly fine in Microsoft sql query.
However in perl, it complains with the following error "Description: [Microsoft][ODBC SQL Server Driver]Cursor type changed".
I double checked and my code can run select and update statements with no issues so I am a bit stumbled about the cursor error.
Note that I have not included my connection string but have illustrated that I am using win32::OLE.
use Win32::OLE;
$conn->{ConnectionString} = "...";
$conn->open; # open connection to the DB
$state = $conn ->state; #1 means connected
if($state ne "1"){...
$mssql_select = "select DATEADD(day, DATEDIFF(day, 2, GETDATE()), '20:00:00')
as A";
$rs->Open( $mssql_select, $conn);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
my ($is_message, $real_error_found);
foreach my $error (in $error_collection)
{
#output error statements
$is_message = ($error->{SQLState} eq "01000" && $error->{NativeError}==0);
$real_error_found=1 unless $is_message;
$status = "ERROR # " . $error->{Number}
. "\n Description: " . $error->{Description}
. "\nSource: " . $error->{Source} . "\n";
}
Results in "Description: [Microsoft][ODBC SQL Server Driver]Cursor type changed".
Any brainstormnig ideas the group can provide would be appreciated.
I figured it out, see below

Solved it, turns out this is just a warning, sql server does not know what type of cursor will be returned, the results actually get returned. See http://social.msdn.microsoft.com/Forums/sqlserver/en-US/e15141e7-3084-487d-a60f-47afac046a55/odbcsql-cursor-error

Related

Compare two dates in sql query giving error - Codeigniter Query Builder

Here is my code:
function get_late_jobs($date1, $date2) {
$this->db->select('Delivery.Packlist, Delivery.Job, Delivery.Promised_Date, Delivery.Shipped_Date, Job.Customer');
$this->db->join('Job', 'Delivery.Job = Job.Job', 'inner');
$this->db->where('Delivery.Promised_Date <', 'Delivery.Shipped_Date');
$this->db->where('Delivery.Job IS NOT NULL', NULL);
$this->db->where('Delivery.Shipped_Date IS NOT NULL', NULL);
$this->db->where('Delivery.Shipped_Date >=', $date1);
$this->db->where('Delivery.Shipped_Date <=', $date2);
$this->db->order_by('Delivery.Shipped_Date');
$query = $this->db->get( 'Delivery' );
return $query->result_array();
}
I keep getting this error:
Error Number: 22007/241
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Conversion failed when converting date and/or time from character string.
SELECT
"Delivery"."Packlist",
"Delivery"."Job",
"Delivery"."Promised_Date",
"Delivery"."Shipped_Date",
"Job"."Customer"
FROM "Delivery"
INNER JOIN "Job"
ON "Delivery"."Job" = "Job"."Job"
WHERE
"Delivery"."Promised_Date" < 'Delivery.Shipped_Date'
AND "Delivery"."Job" IS NOT NULL
AND "Delivery"."Shipped_Date" IS NOT NULL
AND "Delivery"."Shipped_Date" >= '2018-08-08'
AND "Delivery"."Shipped_Date" <= '2018-08-15'
ORDER BY
"Delivery"."Shipped_Date"
Filename: C:/inetpub/wwwroot/portalci/system/database/DB_driver.php
Line Number: 691
I have already tested the query in SQL Management Studio and the query is an exact copy from an old procedural php page that exist.
I'd suggest replacing
'Delivery.Shipped_Date'
with
"Delivery"."Shipped_Date"
The former is a string constant which cannot be converted to a date.

getting incomplete result executing mssql stored procedure in codeigniter

this gives accurate result in mssql server
execute proc_Attn_Mon_General 801, '2018-04-14', '2018-05-14', 0
but this gives incomplete result
$query = $this->db->query("execute proc_Attn_Mon_General #emp_id='$emp_id', #date_from='$start_date', #date_to='$end_date', #Aflag=0");
return $query->result_array();
or this
$query = $this->db->query("execute proc_Attn_Mon_General ".$emp_id.",'".$start_date."','".$end_date."', ".$Aflag." ");
return $query->result_array();
am i doing something wrong?
the query works fine but this could be issue of your slow network connection

Why do I get "Conversion failed when converting date and/or time from character string" when subtracting a number from GETDATE()?

I cannot figure out what I am doing incorrect here. I have the following values for these variables.
my $sql = qq~
SELECT COUNT(*)
FROM tableName u
WHERE 1=1 AND u.ManufacturerPartNumber IN ('X','Y','Z')
AND CAST(u.InspectionStartDate AS DATETIME) > (GETDATE() - ?)
~;
my $argsRef->{lookBack} = 30;
And when I try to run a selectrow_array on the sql like such:
my $qnCount = $dbh->selectrow_array($sql, undef, $argsRef->{lookBack});
I get the following error:
DBD::ODBC::db selectrow_array failed: [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting date and/or time from character string. (SQL-22007) [for Statement "
SELECT COUNT(*)
FROM tableName u
WHERE 1=1 AND u.ManufacturerPartNumber IN ('X','Y','Z')
AND CAST(u.InspectionStartDate AS DATETIME) > (GETDATE() - ?)
"]
So, it is my understanding that the third parameter in the selectrow_array call from a database handle should be the bind variables. Yet, they seem not to be binding....
the database handle is created as such:
my $dbh = DBI->connect_cached("dbi:ODBC:$dsn", undef, undef, {
PrintError => 0,
RaiseError => 1,
ShowErrorStatement => 1,
LongReadLen => 500000,
})
$dsn is the correct DSN but not shown for various reasons, but we know it works due the error message coming back from SQL Server.
Any idea what I am doing wrong?
Thanks in advance for your help.
First, a shout out to ThisSuitIsBlackNot for pointing out that the problem. I made the assumption that the DBI/driver would be able to determine the value type. That was wrong. So, I explicitly stated the type:
$sth = $dbh->prepare($sql);
$sth->bind_param( 1, ($argsRef->{lookBack} * -1), { TYPE => SQL_INTEGER });
$sth->execute();
my $qnCount = $sth->fetchrow_array();
This allowed it to go through as an integer and the SQL ran without problem.
In case you were wondering why I am multiplying by -1, is because I changed the query to use DATEADD:
SELECT COUNT(*)
FROM tableName u
WHERE 1=1 AND u.ManufacturerPartNumber IN ('x')
AND CAST(u.InspectionStartDate AS DATETIME) > DATEADD(dd, ?, GETDATE())
Although there seems to be some continuing discussion in regards to its use, it is working here.
Thank you all for your help.

SSIS SQL statement error

I created an SSIS package with source being a SQL query, destination being a flat file.
The SQL statement executes properly in SQL Server Management Studio, however it errors out when run from SSIS.
The statement is:
use Echo_active
select
DATEFROMPARTS(year(getdate()) - 1, month(getdate()) + 2, 1) as StartDate,
eomonth(DATEFROMPARTS(year(getdate()) - 1, month(getdate()) + 4, 1) ) as EndDate,
pd.[PA-PT-NO-WOSCD],
pd.[PA-PT-NO-SCD],
REPLACE(di.[PA-DX2-CODE],'.','') DiagCode,
REPLACE(STR(di.[PA-DX2-PRIO-NO], 2, 0),' ', 0) DiagSeqNo,
di.[PA-DX2-PRESENT-ON-ADM-IND] POA,
di.[PA-DX2-CODING-SYS-IND] DiagVersion
from
patientdemographics pd
left join
DiagnosisInformation di on pd.[PA-REGION-CD] = di.[PA-REGION-CD]
and pd.[PA-HOSP-CD] = di.[PA-HOSP-CD]
and pd.[PA-PT-NO-WOSCD] = di.[PA-PT-NO-WOSCD]
where
[pa-dsch-date] > = DATEFROMPARTS(year(getdate()) -1, month(getdate()) + 2, 1)
and [pa-dsch-date] <= eomonth(DATEFROMPARTS(year(getdate()) - 1, month(getdate()) + 4, 1))
and di.[PA-DX2-PRESENT-ON-ADM-IND] <> ''
order by
di.[PA-DX2-CODE]
The error message I am receiving is :
[Execute SQL Task] Error: Executing the query "
use Echo_active
select
DATEFROMPARTS(year(getda..." failed with the following error: "Cannot construct data type date, some of the arguments have values which are not valid.".
Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.
How could the same statement execute in one place but errors out in the other?
Any suggestions would be greatly appreciated.

Perl ADO thinks printed output in stored procedure is an error!

First of all (in case this is important) I'm using ActiveState's Perl (v5.8.7 built for MSWin32-x86-multi-thread).
I've just emerged from a three hour long debugging session, trying to find the source of an error. I found there was simply no error, but for some reason ADO's connection object was getting the Errors.Count increased with each printed message in my stored procedure's output.
Consider following Transact SQL code:
CREATE PROCEDURE dbo.My_Sample() AS
BEGIN TRAN my_tran
-- Does something useful
if ##error <> 0 BEGIN
ROLLBACK TRAN my_tran
RAISERROR( 'SP My_Sample failed', 16, 1)
END ELSE BEGIN
COMMIT TRAN my_tran
PRINT 'SP My_Sample succeeded'
END
Now imagine a Perl sub more or less like:
sub execute_SQL {
# $conn is an already opened ADO connection object
# pointing to my SQL Server
# $sql is the T-SQL statement to be executed
my($conn, $sql) = #_;
$conn->Execute($sql);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
if ($ecount == 0 ) { return 0; }
print "\n" . $ecount . " errors found\n";
print "Executed SQL Code:\n$sql\n\n";
print "Errors while executing:\n";
foreach my $error (in $error_collection){
print "Error: [" . $error->{Number} . "] " . $error->{Description} . "\n";
}
return 1;
}
Somewhere else, in the main Perl code, I'm calling the above sub as:
execute_SQL( $conn, 'EXEC dbo.My_Sample' );
In the end I got it that every PRINT statement causes a new pseudo-error to be appended to the ADO Errors collection. The quick fix I implemented was to change that PRINT in the SP into a SELECT, to bypass this.
The questions I'd like to ask are:
Is this behaviour normal?
Is there a way to avoid/bypass it?
This is to be expected as it's what ADO does and the Win32::ADO is quite a thin layer above it.
ref: knowledge base note that the RAISERROR and PRINT statements are returned through the ADO errors collection
OK, after a lot of testing and reading, I came to found it explained in the BOLs' article "Using PRINT" (my emphasis):
The PRINT statement is used to return messages to applications. PRINT takes either a character or Unicode string expression as a parameter and returns the string as a message to the application. The message is returned as an informational error to applications using the SQLClient namespace or the ActiveX Data Objects (ADO), OLE DB, and Open Database Connectivity (ODBC) application programming interfaces (APIs). SQLSTATE is set to 01000, the native error is set to 0, and the error message string is set to the character string specified in the PRINT statement. The string is returned to the message handler callback function in DB-Library applications.
Armed with this knowledge I adapted this VB6 from this DevX article until I got this:
sub execute_SQL {
# $conn is an already opened ADO connection object
# pointing to my SQL Server
# $sql is the T-SQL statement to be executed
# Returns 0 if no error found, 1 otherwise
my($conn, $sql) = #_;
$conn->Execute($sql);
my $error_collection = $conn->Errors();
my $ecount = $error_collection->Count;
if ($ecount == 0 ) { return 0; }
my ($is_message, $real_error_found);
foreach my $error (in $error_collection){
$is_message = ($error->{SQLState} eq "01000" && $error->{NativeError}==0);
$real_error_found=1 unless $is_message;
if( $is_message) {
print "Message # " . $error->{Number}
. "\n Text: " . $error->{Description} ."\n";
} else {
print "Error # " . $error->{Number}
. "\n Description: " . $error->{Description}
. "\nSource: " . $error->{Source} . "\n";
}
}
print $message_to_print;
return $real_error_found;
}
So now my Perl sub correctly sorts out real errors (emitted from SQL Server via a RaisError) and a common message outputted via "PRINT".
Thanks to Richard Harrison for his answer which lead me to the way of success.

Resources