I am currently debugging a scenario in which dates need to be read from a string in a stored procedure.
The code that we have used is a simple convert statement.
e.g.
SELECT CONVERT(DATETIME, #dateInput)
The problem comes when I need to test the dates coming from the Chinese date format (yyyy.mm.dd) which is ISO 102.
What settings in Windows 10 / SQL Server must be set so that running SELECT CONVERT(DATETIME, '2020.05.16') will not return
"The conversion of a varchar data type to a datetime data type resulted in an out-of-range value."
I understand that using SELECT CONVERT(DATETIME, '2020.05.16', 102) would work but that would make the universal stored procedure incorrect when running with different windows date formats
Along with changing my windows settings to reflect the same date format I also changed:
My default language of my SQLEXPRESS server in Properties > Advanced > Default Language
My default language of my SQL User Login Properties > General > Default Language
This meant that it could read the direct string value without needed the ISO 102 identifier.
If the input value is always in the format yyyy.MM.dd then use the appropriate style code (don't rely on the language setting of the LOGIN):
DECLARE #StringInput varchar(10) = '2020.05.16';
SELECT CONVERT(datetime,#StringInput,102);
Ideally, however, instead of defining your parameter as a varchar define it as a datetime in the first place and have the application pass the correct data type; not a string. But that is a different question for the language your application is written in.
Related
I have created this table:
CREATE TABLE HUL
(
Company_name varchar(50),
Purchase_date date,
Quantity int,
Price float,
Age int,
profit_and_loss float
)
While I am trying to insert date values am getting an error. Am providing the insert query I have tried and the error as well
INSERT INTO HUL (Company_name, Purchase_date, Quantity, Price, Age, profit_and_loss)
VALUES ('Hindusthan_Unilever', '25-03-2022', 1, 1950.40, 125, 669.45);
Conversion failed when converting date and/or time from character string
INSERT INTO HUL (Company_name, Purchase_date, Quantity, Price, Age, profit_and_loss)
VALUES ('Hindusthan_Unilever', (CAST('25032022', AS DATE)), 1, 1950.40, 125, 669.45);
Incorrect syntax near the keyword 'AS'.
INSERT INTO HUL (Purchase_date)
VALUES ('25-03-2022');
Conversion failed when converting date and/or time from character string.
Can any one please me get the right query to fix this in Microsoft SQL Server.
SQL Server will happily parse strings into dates if they meet a certain set of formats.
Some of those formats depend upon your regional settings. For example, people in some parts of the world (mostly the USA) seem to like dates in month-day-year format, aka MM-dd-yyyy.
In other, slightly more sensible parts of the world people are used to day-month-year format, aka dd-MM-yyyy. This is what you are currently using.
But which of those SQL will accept depends on the regional settings of the system. It can't just accept both, because what would '01-02-2022' mean? Is it the first of Febrary, or the second of January? How can SQL Server know what you meant?
Then there are formats which are unambiguous. They only get interpreted one way no matter what your regional settings are. The simplest example is yearMonthDay, ie, yyyyMMdd. If you provide this format then the interpretation doesn't depend upon your regional settings. The value '20220201' is always interpreted as "the first of February".
So that explains the problem with your first query and your third query. In your second query you have an unnecessary comma. To fix the syntax error...
cast('25032022', AS DATE) -- no good, syntax error
cast('25032022' AS DATE) -- comma removed
But this would be interpreted as the value "22nd day of the 20th month (??) in the year 2503", because you have the numbers the wrong way around.
If necessary * you can force SQL to interpret text the way you want using set dateformat. Example:
set dateformat mdy; -- tell sql to read the text as month then day then year
select cast('01-02-2022' as date); -- SQL will now read this as January 2 2022
set dateformat dmy; -- now tell it to read it as day then month then year
select cast('01-02-2022' as date); -- now it's February 1, 2022
You can also "force" a particular interpretation using convert with a style argument, or try_parse with a culture.
* "Necssary" here meaning "you might not have the option of changing the incoming format, because developers aren't normally the ones adding data, users are, and you could be receiving the data in a csv, or by some other mechanism over which you have no control, but from which you still need to ingest"
One thing to understand here is different cultures and languages have different expectations around how dates are formatted.
SQL is no different. It is its own language, and just like any other language it has its own native date format for string literals. When writing SQL, it’s wrong to put your own cultural expectations into this very different language.
So for dates in SQL Server, the correct format is yyyMMdd (no separators). For dates with a time component, there are two accepted formats: yyyyMMdd HH:mm:ss[.fff] and yyyy-MM-ddTHH:mm:ss[.fff]. Anything else is not correct and there are times of the year when the value will be interpreted incorrectly.
Of course, this assumes you're including the the value as a literal in the string. If you're building this string in client code, it is never okay to use string concatenation to include these values in the SQL in the first place. Instead, you must always use parameterized queries/prepared statements.
Done properly, this means a strongly-typed datetime object in whatever client platform you prefer, assigned to a strong-typed DateTime parameter value sent directly to the server, such that the datetime value is never at any point even converted to a string.
https://blogs.msmvps.com/jcoehoorn/blog/2022/07/13/sql-and-dates/
In SQL Server insert into keyword is used to add up some values in a table.
INSERT INTO HUL
(
Company_name,
Purchase_date,
Quantity,
Price,
Age,
profit_and_loss
)
VALUES
(
'A Worldwide Company',
'28-07-2022',
1000,
175.20,
35,
70.50
)
I created a small script that works in SQL Server Management Studio, then I created a SQL Server Agent job with that same script; but after I run it, I get an error:
The conversation of a varchar data type to a datetime data type resulted in an out-of-range
I fixed the problem by change the format of date to ISO 8601, but I don't release how my first script works on SSMS and not in SQL Server Agent.
First script:
declare #teste datetime
set #teste = '31/12/2099 00:00:00'
select #teste
Fix error:
declare #teste datetime
set #teste = '20991231 00:00:00'
select #teste
This is one reason why using unambiguous formats are so important when using date(time) datatypes. The only formats that an unambgious in SQL Server, regardless of language and datatype are the formats yyyyMMdd and yyyy-MM-ddThh:mm:ss.
For the date '31/12/2099 00:00:00' and the language your Login is using it appears that SQL Server is interpreting the value as the 12th day, of the 31st month, of the year 2099. There aren't 31 months in the year, and hence the error. (DB<>Fiddle). It's worth noting that date (and the other "new" datetime data types) behave differently and also can unambiguously understand the format yyyy-MM-dd; notice in this DB<>fiddle the difference in the values for the datetime values simply due to the language setting.
As you can see, the solution is to use a unambiguous format. So, as you're using a date and time, I would suggest the string '2099-12-31T00:00:00'.
I have this query in SQL Server 2008:
SELECT DATEADD(mm, -2, '2017-05-10');
I have run my code today and remarked that the result looks like '2017-08-05' instead of '2017-03-10' expected. It seems like date format turned into yyyy-dd-mm before conversion and returned back to yyyy-mm-dd to display the result.
Is there any explanation? How to fix this definitely?
What are you talking about is not a date format issue, but datetime issue, in fact, if you try this code you'll ALWAYS get the same result:
set dateformat ymd
SELECT DATEADD(mm, -2, cast('2017-05-10' as date));
set dateformat ydm
SELECT DATEADD(mm, -2, cast('2017-05-10' as date));
While using datetime you'll get different results depending on your language/dateformat setting:
set language us_english
SELECT DATEADD(mm, -2, '2017-05-10');
set language russian
SELECT DATEADD(mm, -2, '2017-05-10');
The format yyyy-mm-dd is language neutral when using with date type but it's language dependent when using with datetime.
Explanation:
It is important to note that some character string formats of date and
time literals are language dependent, meaning that when you convert
them to a date and time data type, SQL Server might interpret the
value differently based on the language setting in effect in the
session. Each logon defined by the database administrator has a
default language associated with it, and unless it is changed
explicitly, that language becomes the effective language in the
session. You can overwrite the default language in your session by
using the SET LANGUAGE command, but this is generally not recom-
mended because some aspects of the code might rely on the user’s
default language. The effective language in the session sets several
language-related settings behind the scenes, among them one called
DATEFORMAT, which determines how SQL Server interprets the liter- als
you enter when they are converted from a character string type to a
date and time type. The DATEFORMAT setting is expressed as a
combination of the characters d, m, and y. For example, the
us_english language setting sets the DATEFORMAT to mdy, whereas the
British language setting sets the DATEFORMAT to dmy. You can override
the DATEFORMAT setting in your session by using the SET DATEFORMAT
command, but as mentioned earlier, changing language-related settings
is generally not recommended. Consider, for example, the literal
‘02/12/2007’. SQL Server can interpret the date as either February
12, 2007 or December 2, 2007 when you convert this literal to one of
the following types: DATETIME, DATE, DATETIME2, or DATETIMEOFFSET.
The effective LANGUAGE/DATEFORMAT setting is the determining factor.
To demonstrate different interpretations of the same character string
literal, run the following code. SET LANGUAGE British; SELECT
CAST('02/12/2007' AS DATETIME); SET LANGUAGE us_english; SELECT
CAST('02/12/2007' AS DATETIME);
Related article: Working with Date and Time Data by Itzik Ben-Gan
Following the link you'll find the table with language-neutral formats for different date/time types
Try this : SELECT DATEADD(mm, -2, '2017-10-05') =>2017-03-10
I'm getting a cast failure and I can't fathom why.
Here's what is failing :
select cast('16/04/2012' as datetime)
The error is :
"The conversion of a char data type to a datetime data type resulted
in an out-of-range datetime value."
If I use CONVERT with a 103 for format it works without issue as you would expect.
The server is set to british date format, therefore the MSSQL account should also be defaulting to britsh format. It's been rebooted, so it shouldn't be that the service is using a different date format.
This is a SQL2005 instance.
What I really want to know is, what could be causing the CAST to fail?
Use this code:
SELECT convert(datetime, '16/04/2012',105)
Have you tried SET DATEFORMAT DMY?
Date format and datetime format are not necessarily the same. While it may implicitly add the 00:00:00 for hh:mm:ss, maybe try adding that. Type 103 only includes dd/mm/yyyy, so it of course works.
You have a data format as MM:dd:YY, and cast tries to convert you '16/04/2012' which is 'dd/MM/yy' and throws exception because 16 is less then 12 monthes.
You can either change your data format in server settings or use SET DATEFORMAT statement before your query
Are you sure the server is British language format? If I run:
set language british
select cast('16/04/2012' as datetime)
Then I get:
2012-04-16 00:00:00.000
You can check the current session language with
select ##language
The session language defaults from the login in use, assuming it's a SQL Server-provisioned login (i.e. not a Windows user). To check the language for a given user:
select loginproperty('myuser', 'DefaultLanguage')
To make a permanent server change for all newly created logins:
EXEC sp_configure 'default language', 23
reconfigure
...where 23 is the langid obtained via sp_helplanguage.
Always use a language neutral date format - it will always work regardless of any settings:
CAST('YYYYMMDD', AS DATE);
4 digit year, 2 digit month, 2 digit day and NO separators. You will never again have to worry about default language settings.
I'm having a lot of difficulty with locale's in a particular instance of SQL Server 2008 R2 Express.
I'm in the UK and the following fails:
SELECT CAST('2012-12-31' AS DATETIME)
Error message:
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The Windows server locale is British English. My login locale is British English. Collation 'if that matters' is Latin1_General_CI_AS.
The database 'language' is English (United States) but then this is the same as another instance on a different server and the above SQL doesnt fail.
Any thoughts?
For the user making the database connection -- the SQL user -- set the language to English.
This is a setting specific to the SQL user of the connection issuing the query
One way to check if this is a problem... Run this in Management Studio and login as the SQL user who issues the query
SET LANGUAGE English
SELECT CAST('2012-12-31' AS DATETIME)
If this works, set the default language of the SQL user appropriately
Don't use YYYY-MM-DD for date literals, always use YYYYMMDD. This will never fail, regardless of locale, dateformat settings, language settings, regional settings, etc:
SELECT CAST('20121231' AS DATETIME);
A worthwhile read perhaps:
Bad habits to kick : mis-handling date / range queries
You should explicitly define the date format on your convert, in this case is 120:
SELECT CONVERT(DATETIME,'2012-12-31',120)
You can take a look at this page to see more date formats:
http://msdn.microsoft.com/en-us/library/ms187928.aspx