For example the following query works fine:
SELECT *
FROM quotes
WHERE expires_at <= '2010-10-15 10:00:00';
But this is obviously performing a 'string' comparison - I was wondering if there was a function built in to MySQL that specifically does 'datetime' comparisons.
...this is obviously performing a 'string' comparison
No - if the date/time format matches the supported format, MySQL performs implicit conversion to convert the value to a DATETIME, based on the column it is being compared to. Same thing happens with:
WHERE int_column = '1'
...where the string value of "1" is converted to an INTeger because int_column's data type is INT, not CHAR/VARCHAR/TEXT.
If you want to explicitly convert the string to a DATETIME, the STR_TO_DATE function would be the best choice:
WHERE expires_at <= STR_TO_DATE('2010-10-15 10:00:00', '%Y-%m-%d %H:%i:%s')
But this is obviously performing a 'string' comparison
No. The string will be automatically cast into a DATETIME value.
See 11.2. Type Conversion in Expression Evaluation.
When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly. For example, MySQL automatically converts numbers to strings as necessary, and vice versa.
I know its pretty old but I just encounter the problem and there is what I saw in the SQL doc :
[For best results when using BETWEEN with date or time values,] use CAST() to explicitly convert the values to the desired data type. Examples: If you compare a DATETIME to two DATE values, convert the DATE values to DATETIME values. If you use a string constant such as '2001-1-1' in a comparison to a DATE, cast the string to a DATE.
I assume it's better to use STR_TO_DATE since they took the time to make a function just for that and also the fact that i found this in the BETWEEN doc...
Related
'dd-mm-yy' being NLS_DATE_FORMAT it is implicitly converted to Date data type during comparison, insertion but why is not converted during a arithmetic operation.
sysdate>'01-01-17' //is valid
sysdate-'01-01-17' //is in valid
First I assumed the operators(+,-,..) are only for numeric data type. Later I got to know these operators are used even in Date Arithmetic and even operands with Datedata type are also valid.
"During arithmetic operations on and comparisons between character and noncharacter datatypes, Oracle converts from any character datatype to a numeric, date, or rowid, as appropriate" -
doc
Using to_date solves the issue. I am looking for the reason why it is not implicitly converted.
Forget implicit conversion. Just express your dates using explicit date literals:
sysdate > date '2017-01-01'
sysdate - date '2017-01-01'
The code is clearer and less ambiguous as well.
As to why Oracle doesn't do implicit conversion in the second case. Oracle doesn't know what type to expect. The second operand could be either a date or a number, so it doesn't know how to convert the string. In the first case, the comparison should be to a date.
Adding more detail on Gordon Lindoff's answer with an example.
During sysdate>'010117' as your comparing with a date '010117' surely should be date and is implicitly converted. Same going during insert.
But during sysdate-'010117' the system has the possibilities of converting it Number or Date, and it chooses to convert into Number. So 'dd-mm-yy' format is tried to convert into Number in this context.
One of the columns my_column in my table is of type varchar where i store value of date in string. The format is 'MM/DD/YY'. I want to use cast function of hibernate to convert this column value to date. But it appears that the cast function accepts string of 'yy-mm-dd' format to convert. Is it possible to use cast for string with specific date format for conversion. Something like this: cast(am.my_column as date format 'mm/dd/yy')
cast function in hibernate is used this way: cast(am.my_column as date).
My use case is basically converting the column value from string to date and making a date comparison. cast(am.my_column as date format 'mm/dd/yy') > '12/30/2017'
Instead of casting a column value inside the query, you may consider to give '12/30/2017' as parameter (with type of Java Date). So that you can directly write am.my_column > :parameterDate
I have a question regarding SQL dates.
The table I am working with has a date field in the following format: "22-SEP-08". The field is a date column.
I am trying to figure out how to output records from 1/1/2000 to present day.
The code below is not filtering the date field:
Select distinct entity.lt_date
from feed.entitytable entity
where entity.lt_date >= '2000-01-01'
Any help regarding this issue is much appreciated. Thanks!
Edit: I am using Oracle SQL Developer to write my code.
DATEs do not have "a format". Any format you see is applied by the application displaying the date value.
You can either change the configuration of SQL Developer to display dates in a different format, or you can use to_char() to format the date the way you want.
The reason your statement does not work, is most probably because of the implicit data type conversion that you are relying on.
'2000-01-01' is a string value, not a date. And the string is converted using the NLS settings of your session. Given the fact that you see dates displayed as DD-MON-YY means that that is the format that is used by the evil implicit data type conversion. You should supply date values always as real date literals.
There are two ways of specifying a real date literal. The first is ANSI SQL and simple uses the keyword DATE in front of an ISO formatted string:
where entity.lt_date >= DATE '2000-01-01'
Note the DATE keyword in front of the string, wich makes it a real date literal not a string expression.
The other option is to use to_date() to convert a character value into a date:
where entity.lt_date >= to_date('2000-01-01', 'yyyy-mm-dd');
More details about specifying date literals can be found in the manual:
Date literals
to_date function
My guess is the data type isn't a Date. Just in case its a char type, try to convert it using the Oracle TO_DATE() function. The Oracle documentation below should help you with parameters.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions183.htm
An implicit datatype conversion bites once again.
You're right. The predicate is not doing the comparison you are expecting,
Oracle is performing an implicit datatype conversion, from DATE to VARCHAR, so that it can do a comparison to the string literal.
If lt_date column is DATE datatype, then Oracle is seeing your where clause:
where entity.lt_date >= '2000-01-01'
Oracle is actually seeing it as if it's written like this:
where TO_CHAR(entity.lt_date) >= '2000-01-01'
And that's where the "format" problem comes in. The column itself does not have a "format". Because the second argument to the TO_CHAR function is not supplied, Oracle is using the value of the NLS_DATE_FORMAT parameter (from your session). And that's probably set to DD-MON-YY. Which is why that's the "format" you're seeing when you a run a SELECT statement in SQL*Plus. Because the DATE value is (again) being run through a TO_CHAR function to get a string that can be displayed.
To get the "filtering" you want, don't do a comparison to a string literal. Instead, do the comparison to an expression that has DATE datatype.
You can use the Oracle TO_DATE function. And you don't want to rely on setting of NLS_DATE_FORMAT, explicitly specify the format model as the second argument to the function. For example:
DO THIS
where entity.lt_date >= TO_DATE('2000-01-01','YYYY-MM-DD')
DON'T DO THIS
It's also possible to specify the format model as the second argument to the TO_CHAR function.
where TO_CHAR(entity.lt_date,'YYYY-MM-DD') >= '2001-01-01'
But you don't want to do that because that's going to force Oracle to evaluate that expression on the left side for every flipping row in the table, so it has a string value to do the comparison. (That's true unless someone created a function-based index for you.) If you do the comparison on the bare column, using the TO_DATE on the literal side, Oracle can make effective use of an appropriate index (with lt_date as the leading column) to satisfy the predicate.
This question already has answers here:
SQL Server and implicit conversion of types
(2 answers)
Closed 8 years ago.
What is the difference between implicit conversion and explicit conversion in SQL Server?
An explicit conversion occurs when you use the CONVERT or CAST keywords explicitly in your query.
An implicit conversion arises when you have differing datatypes in an expression and SQL Server casts them automatically according to the rules of datatype precedence.
For example nvarchar has higher precedence than varchar
CREATE TABLE Demo
(
X varchar(50) PRIMARY KEY
)
/*Explicit*/
SELECT *
FROM Demo
WHERE CAST(X AS NVARCHAR(50)) = N'Foo'
/*Implicit*/
SELECT *
FROM Demo
WHERE X = N'Foo' /*<-- The N prefix means nvarchar*/
The second execution plan shows a predicate of
CONVERT_IMPLICIT(nvarchar(50),[D].[dbo].[Demo].[X],0)=[#1]
Both the explicit and implicit conversions prevent an index seek in this case.
Implicit conversions are not visible to the user. SQL Server automatically converts the data from one data type to another. For example, when a smallint is compared to an int, the smallint is implicitly converted to int before the comparison proceeds.
GETDATE() implicitly converts to date style 0. SYSDATETIME() implicitly converts to date style 21.
Explicit conversions use the CAST or CONVERT functions.
The CAST and CONVERT functions convert a value (a local variable, a column, or another expression) from one data type to another. For example, the following CAST function converts the numeric value of $157.27 into a character string of '157.27':
CAST ( $157.27 AS VARCHAR(10) )
Implicit means that the database engine will convert the data type automatically, a process invisible to the user.
Explicit means that you must specify how the data type should be converted. If you don’t specify how SQL Server should convert the data types to do what you want (explicitly), it will try to guess your intentions (implicitly).
link
Implicit conversion is a conversion in which you don't have to bother about the conversion. SQL Server automatically converts the data from one data type to another. For example, if a smallint is compared to an int, the smallint is implicitly converted to int before the comparison proceeds. Suppose two column exist such as num1 in smallint and num2 in int.
you want to compare them(whether equal). You have to write:
Select ..... where num1 = num2
nothing required for the conversion.
Explicit conversion is a conversion in which you have to describe the conversion in your hand. Explicit conversions use the CAST or CONVERT functions. For example, a column date1 written in '21.01.2013'. it is in a varchar format according to the provided data/table. you want to compare with another column date2 which is in '21/01/2013' format. It is a date but provided in a varchar format as well. To compare them(whether equal) you have to write:
select ....... where cast(date1 as date) =cast(date2 as date)
I want to use Like operator in a column of datetime. The values of the column is as follows:
2013-08-31 17:54:52.000
2013-08-31 17:54:52.000
My query is as below:
SELECT * FROM table where created_date Like '%54%'
It works fine. but when I search for '%52%' instead of '%54%', it gives me nothing. (It is working when I search till the minutes, but when I search for seconds or milli seconds it does not work.)
I have looked at the following url and it is working
SQL LIKE Statement on a DateTime Type
I want to know the reason, why this is happening and how like operator works with datetime type column.
I think it would be a better idea to use the DATEPART operator of SQL SERVER to extract the portion of date.
And example could be like:-
SELECT * FROM table
where DATEPART(minute,created_date)=54
EDIT:-
I want to know the reason, why this is happening and how like operator
works with datetime type column.
Actually there is no direct support given by SQL Server for LIKE operator for DATETIME variable but you can always cast the DATETIME to a VARCHAR and then try to use the LIKE operator as you want.
On a side note:-
MSDN says:-
DATEPART can be used in the select list, WHERE, HAVING, GROUP BY and
ORDER BY clauses.
In SQL Server 2012, DATEPART implicitly casts string literals as a
datetime2 type. This means that DATEPART does not support the format
YDM when the date is passed as a string. You must explicitly cast the
string to a datetime or smalldatetime type to use the YDM format.
The 'LIKE' operator and any regular expression operators provided by other databases are used to process text values. A date is definitely not a text value, it is a separata type by itself.
It makes little sense to apply a text operator to a non-text type (like int or DATETIME or DATETIMEOFFSET), which is why you can't use LIKE on dates in any database. First of all, the values are not stored as text but in an implementation-specific binary form.
Then, while you can use LIKE on a specific text representation of a date, eg using CAST you have to absolutely certain what that representation is. Different locales display dates differently, with year first, year last, month first or last or whatever. What would you search against?
Moreover, what is 54? 54 minutes, 54 seconds or 654 milliseconds?
The only sensible solution is to use DATEPART to check specific parts of a date, or the BETWEEN operator to check for ranges.