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

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.

Related

TSQL return predefined row when no rows found

Working with Microsoft SQL Server: There are multiple systems, each one has set of errors (four digit numbers) that map to an Error Group (string). There is one exception: if the error string is NOT in the list below, it should fall into a predefined Error Group.
Example:
System 1:
Error Group 1: 2001, 2003, 6538, 6540, 6542, 6544, 6546
Error Group 2: 2002, 6539, 6541, 6543, 6545, 6547, 6549
Error Group 3: 1000, 1001, 1002, 4001, 4007, 5001, 5002 AND ANYTHING ELSE!
System 2:
Error Group 1: 6016, 6533, 6540, 6542, 6544, 6546
Error Group 2: 6541, 6543, 6545, 6547, 6549 AND ANYTHING ELSE!
Error Group 3: 1002, 4001, 4007, 5001, 5002
The table:
SystemId (int): 1, 2, etc
ErrorGroup (string): "Error Type 1", ...
Error (int?): the four digit number
Finding the errorGroup is straight forward:
SELECT ErrorGroup
FROM table
WHERE SystemId = 1 AND Error = 2002
The goal is one query that will return the error group when the error is found and the "default" error group when the error is not found. There is flexibility in changing or modifying the data to make this happen.
What would it look like in Linq?
You can use the T-SQL ISNULL system function to return a predefined constant value if the result of the query is empty.
SELECT ISNULL(
(SELECT ErrorGroup FROM table
WHERE SystemId = 1 AND Error = 2002),
'Default Group')
Instead of the string literal, another query can also be used.
As for Linq, DefaultIfEmpty can be used to set the default value of the query if there is no result.
If you know you will always just return one row the best way to do this is to use coalesce -- this will work on all versions and platforms of SQL.
SELECT COALESCE(ErrorGroup,'Default Group') AS ErrorGroup
FROM tablename
WHERE SystemId = 1 and Error = 2002
As far as a SQL solution goes here is a possibility.
I created the table as:
CREATE TABLE ErrorData (SystemID int NOT NULL,
ErrorGroupID int NOT NULL,
ErrorCode int NULL)
I added data based on you info above:
INSERT INTO ErrorData (SystemID, ErrorGroupID, ErrorCode)
values (1,1,3001),(1,1,3003),(1,1,6538),(1,1,6540),(1,1,6542),(1,1,6544),(1,1,6546),
(1,2,2002),(1,2,6539),(1,2,6541),(1,2,6543),(1,2,6545),(1,2,6547),(1,2,6549),
(1,3,1000),(1,3,1001),(1,3,1002),(1,3,4007),(1,3,6542),(1,3,5001),(1,3,5002),
(1,3,null),
(2,1,6016),(2,1,6533),(2,1,6540),(2,1,6542),(2,1,6544),(2,1,6546),
(2,2,6541),(2,2,6543),(2,2,6545),(2,2,6547),(2,2,6549),
(2,3,1002),(2,3,4001),(2,3,4007),(2,3,5001),(2,3,5002),
(2,2,null)
You will notice I inserted a value with NULL for the error code to identify the default Error Group
I can then query the data and get the proper ErrorGroup, or the default one using this query
SELECT TOP 1 ErrorGroupID FROM ErrorData WHERE SystemID = 1 AND (ErrorCode = 3003 OR ErrorCode IS NULL) ORDER BY ISNULL(ErrorCode,99999)
If i query for an Error Code that doesn't exist i will get the default Error Group
SELECT TOP 1 ErrorGroupID FROM ErrorData WHERE SystemID = 1 AND (ErrorCode = 9999 OR ErrorCode ISNULL) ORDER BY ISNULL(ErrorCode,99999)

Hibernate HQL query error: The conversion of a varchar data type to a smalldatetime

I try to get result from Hibernate HQL query:
from StopsRegister s where s.startTime>='2018-04-25 07:59:00.0' and s.endTime<='2018-04-26 07:59:00.0'
from StopsRegister s where s.startTime between '2018-04-25 08:42:00' and '2018-04-26 08:42:00'
The issue starts when a add a secound date: and s.endTime<='2018-04-26 07:59:00.0' With only one value everything works correct.
But get the SQL Error:
The conversion of a varchar data type to a smalldatetime data type resulted in an out-of-range value.
That is the way i get the date values:
Timestamp.valueOf(LocalDateTime.of(toDatePicker.getDate(), toTimePicker.getTime()));
data types is: java.sql.Timestamp;
database: MS SQL Server.
In me opinion date format is correct, I do not understan this error.
That solve the issue:
Session session = HibernateUtil.getSessionFactory().openSession();
Query q = session.createQuery("from StopsRegister s where s.startTime >= :from and s.startTime <= :to");
q.setTimestamp("from", from);
q.setTimestamp("to", to);
stopRegisterList = (ArrayList<StopsRegister>) q.list();

What are all values ISNUMERIC function finds as TRUE in sql server?

Below part of my query was failing initially:
WHEN ISNUMERIC(npx.nvcAnswer) = 1
THEN CASE
WHEN ABS(CONVERT(DECIMAL(38,2),npx.nvcAnswer)) < 1
THEN CONVERT(VARCHAR,CONVERT(DECIMAL(38,2),npx.nvcAnswer))
ELSE npx.nvcAnswer
END
Below was the error we were getting:
com.microsoft.sqlserver.jdbc.SQLServerException: Error converting data type nvarchar to numeric.
rootCause=SQLException #1: errorCode: 8114 sqlState: S0005 message: Error converting data type nvarchar to numeric.
I realized that it considers '.' & '-' as NUMERIC too.
So I added "NOT npx.nvcAnswer in( '.' , '-')" to it and it worked.
WHEN ISNUMERIC(npx.nvcAnswer) = 1 AND NOT npx.nvcAnswer in( '.' , '-')
THEN CASE
WHEN ABS(CONVERT(DECIMAL(38,2),npx.nvcAnswer)) < 1
THEN CONVERT(VARCHAR,CONVERT(DECIMAL(38,2),npx.nvcAnswer))
ELSE npx.nvcAnswer
END
After some day it started failing again with below error.
com.microsoft.sqlserver.jdbc.SQLServerException: Error converting data type nvarchar to numeric.
rootCause=SQLException #1: errorCode: 8114 sqlState: S0005 message: Error converting data type nvarchar to numeric.
Then I changed below block and it worked: (But I failed to find what values were causing this issue)
OLD:
WHEN ABS(CONVERT(DECIMAL(38,2),npx.nvcAnswer)) < 1
THEN CONVERT(VARCHAR,CONVERT(DECIMAL(38,2),npx.nvcAnswer))
NEW:
WHEN ABS(CONVERT(DECIMAL(38,2),PATINDEX('%[^0-9]%', npx.nvcAnswer))) < 1
THEN CONVERT(VARCHAR,CONVERT(DECIMAL(38,2),PATINDEX('%[^0-9]%', npx.nvcAnswer)))
Ask :
What are all values ISNUMERIC function finds as TRUE in sql server?
I will suggest you should your Try_Cast() function instead of using complex logic to check numeric values.
ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). Please refer below links for further detail -
https://learn.microsoft.com/en-us/sql/t-sql/functions/isnumeric-transact-sql

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.

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

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

Resources