sql server datetime - sql-server

i have the following query:
select * from table where table.DateUpdated >='2010-05-03 08:31:13:000'
all the rows in the table being queried have the following DateUpdated:
2010-05-03 08:04:50.000
it returns all of the rows in the table - even though it should return none.
I am pretty sure this is because of some crappy date/time regional thing.
if i swap the date to be
select * from table where table.DateUpdated >='2010-03-05 08:31:13:000'
then it does as it should.
How can i force everything to be using the same settings? this is doing my head in :)
This is sql generated by NHIbernate from my WCF service if that matters.
w://

Use this format "yyyymmdd hh:nn:ss.mmmm" which is locale independent in SQL Server, all versions
Somewhere, it's 5th Feb rather then 3rd May
Why:
"yyyy-mm-dd" is not locale independent in SQL Server with datetime columns
this anomaly is fixed with datetime2 in SQL Server 2008
References:
Tibor Karaszi
Tony Rogerson
Me, on SO :-)
Example:
SET DATEFORMAT DMY --UK
SELECT
MONTH(CAST('2010-03-05 08:31:13:000' AS datetime)), --gives 5
MONTH(CAST('20100305 08:31:13:000' AS datetime)) --gives 3
SET DATEFORMAT MDY --default, USA
SELECT
MONTH(CAST('2010-03-05 08:31:13:000' AS datetime)), --gives 3
MONTH(CAST('20100305 08:31:13:000' AS datetime)) --gives 3

You could try:
select * from table
where Convert(DateTime, table.DateUpdated,103) >= Convert(DateTime, '2010-05-03 08:31:13:000',103)

The answer to this was to upgrade to 2008 and use datetime2
what a PITA!!!

Related

SQL Server stored procedure passing date parameters

ALTER PROCEDURE [dbo].[AccountsData]
#Start_Date datetime,
#End_Date datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT
a.Customer_AC_No, a.Customer_Name, a.Product_Code,
a.Product_Description, a.Sales_Person, c.HSID
FROM
(SELECT
Customer_AC_No, Customer_Name, Product_Code,
Product_Description, Sales_Person
FROM
View_Sales_Details
WHERE
([Week Ending] >=' #Start_Date') AND ([Sales Value] > 0)
GROUP BY
Customer_AC_No, Product_Code, Product_Description,
Customer_Name, Sales_Person) AS a
LEFT JOIN
(SELECT
Customer_AC_No, Product_Code
FROM
View_Sales_Details
WHERE
([Week Ending] >= '#End_Date') AND ([Sales Value] > 0)
GROUP BY
Customer_AC_No, Product_Code) AS b ON a.Customer_AC_No = b.Customer_AC_No
AND a.Product_Code = b.Product_Code
INNER JOIN
Hubspot.dbo.View_BPA_Cust_Data AS c ON a.Customer_AC_No = c.CustomerNo COLLATE Latin1_General_100_CI_AS
WHERE
b.Customer_AC_No IS NULL
ORDER BY
a.Customer_AC_No, a.Product_Code ASC
END
I am trying to pass the above date parameters to the SQL Server stored procedure above, but I keep getting this error
Msg 241, Level 16, State 1, Procedure AccountsData, Line 52
Conversion failed when converting date and/or time from character string.
Can some one please help. WeekEnding date is also in datetime format. Thanks
There are many formats supported by SQL Server for specifying a date&time as a string literal - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependent on what settings you have - therefore, these settings might work some times - and sometimes not.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
The recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible.
So in your case, either switch to using DATE as your parameter datatype (since you obviously don't use the time portion):
ALTER PROCEDURE [dbo].[AccountsData]
#Start_Date DATE,
#End_Date DATE
and then execute your stored procedure like this:
EXEC [dbo].[AccountsData] '2019-05-11', '2020-06-10'
or use this format to support DATETIME if you insist on keeping that:
EXEC [dbo].[AccountsData] '2019-05-11T00:00:00', '2020-06-10T00:00:00'
Your have an error in your select. You have change your query like this
DATEPART(wk, Ending)>=DATEPART(wk, #Start_Date) AND ([Sales Value] > 0)
DATEPART(wk, Ending)>=DATEPART(wk, #End_Date) AND ([Sales Value] > 0)

SQL Server issues when getting records starting from a date onwards

I want to obtain all records starting from a date (included) onwards.
I get different records if I use below in where clause:
SELECT * FROM MyTable WHERE DateTimeField >= '20101201'
than if I use below:
SELECT * FROM MyTable WHERE DateTimeField >= Convert(datetime, '2010-12-01')
Why don't I get the same number of registers?
I use SQL Server 2008.
Your literal constant in the second case is language dependent, here is an example:
set language [British English]
SELECT Convert(datetime, '2010-12-01');
----
-- 2010-01-12 00:00:00.000
set language us_english
SELECT Convert(datetime, '2010-12-01');
----
-- 2010-12-01 00:00:00.000
While '20121201' is language independent.
So I suppose your session language (defined by your login language unless changed explicitely) is different from us_english and to fix the issue you should use language independent date literals 'yyyymmdd'

Why does SQL server's Date format affect date conversions with Timestamps

I'm trying to convert a varchar containing a date into a datetime field in SQL server using the following script
SELECT cast('2017-12-14 14:30:41.007' as datetime)
When I ran this on my local Machine that uses DateFormat myd this worked fine and returned a valid datetime.
When I ran this statement on my server that uses Dateformat dym the server returned the following error
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
Why is '2017-12-14 14:30:41.007' a valid datetime under "myd" but not under "dym" even though it's neither a "dym" nor a "myd" date?
I have found a work around for the issue btw, I'm asking because i want to understand what is going on in SQL server
It is because SQL server is interpreting 14 as a month number and there are only 12 months. If you change the 14 to 11 and run this script you will see the difference:
SET DATEFORMAT myd
SELECT DATEPART(month,cast('2017-12-11 14:30:41.007' as datetime))
SET DATEFORMAT dym
SELECT DATEPART(month,cast('2017-12-11 14:30:41.007' as datetime))
/*
Output:
12
11
*/
To make things consistent for all time formats put a T in the middle of the date and time. This makes SQL server think the date is in ISO8601 format.
SET DATEFORMAT myd
SELECT DATEPART(month,cast('2017-12-11T14:30:41.007' as datetime))
SET DATEFORMAT dym
SELECT DATEPART(month,cast('2017-12-11T14:30:41.007' as datetime))
/*
Output:
12
12
*/
'2017-12-14 14:30:41.007' seems to follow ODBC canonical with milliseconds default standard for time, date, datetime2, and datetimeoffset. If you are using MS SQL you can use CONVERT to cope with the specific style of the string parameter:
SELECT convert(datetime,'2017-12-14 14:30:41.007' , 121 )

How to get 3 letter abbreviation for month in SQL

How to get month in 3 letters in SQL.
In SQL Table data is inserted:
2016-01-07 09:38:58.310
I need only month result in 3 letters like below:
Jan
Assuming you're using SQL Server 2012 or newer, you can use the FORMAT function:
SELECT FORMAT([Date], 'MMM', 'en-US')
Adapt the locale as needed.
Since you're on SQL Server 2008, I'd use
SELECT LEFT(DATENAME(MONTH, [Date]), 3)
Try this (I am assuming you are using Sql Server).
Select Convert(char(3), GetDate(), 0)
If you need full name of month, try
Select Datename(month, GetDate())
Or you could just do:
LEFT(GETDATE(), 3)
For instance you could declare a variable:
Declare #MONTH VARCHAR(3)
Set #MONTH = LEFT(GETDATE(), 3)

Sql Server strict convert from varchar to datetime

I'm converting varchar to datetime in Sql Server 2005. Can I force Sql Server to fail if provided varchar has unexpected format?
Example:
select convert(datetime, '01-2010-02', 103)
Expected result: query fails because 103 means dd/mm/yyyy (see msdn).
Actual result: 2010-02-01 00:00:00.000
Main purpose of requested enforcement is order of day and month. If varchar is provided in format yyyy-mm-dd then Sql Server will treat mm as day and dd as month because of day/month order in provided format (dd/mm/yyyy).
Note: I can write custom function to manually handle this case. But I hope such enterprise DB already can work strictly with data.
I am afraid you have to use CLR Function and take advantage of using DateTime.TryParseExact method. Not an elegant solution but could work.
You can compare the date with a convert to datetime and back again. I don't know for sure if there are any pitfalls doing like this but my limited tests has not discovered any.
if #StrDate = convert(varchar(10), convert(datetime, #StrDate, 103) ,103)
Whenever SQL Server sees a clear candidate for Year, it will always be used as Year.
The remaining DM parts are determined from the order within the DMY setting or the convert format. If that weren't true, then very simple conversions will fall apart.
Example
set dateformat dmy
select 1 a,CONVERT(datetime, '1-2-3') b
union all
select 2,CONVERT(datetime, '2001-2-3')
union all
select 3,CONVERT(datetime, '2001-3-2')
Output
a b
----------- -----------------------
1 2003-02-01 00:00:00.000
2 2001-03-02 00:00:00.000
3 2001-02-03 00:00:00.000
The 2nd and 3rd explicitly put the Year in front, and that is ok
EDIT
Books Online has this to say http://msdn.microsoft.com/en-us/library/ms180878.aspx#StringLiteralDateandTimeFormats
There are quite a few exceptions to SET DATEFORMAT, which plays a role regardless of the 3rd param to CONVERT.
The SET DATEFORMAT session setting does not apply to all-numeric date entries
This [ISO 8601] format is not affected by the SET DATEFORMAT, SET LANGUAGE, of login default language settings.
The SET DATEFORMAT session setting is not applied when you specify the month in alphabetical form.
etc
To specifically validate dd/mm/yyyy, use the below instead
set dateformat dmy
declare #input varchar(10) set #input = '12-2010-01'
-- convert allows the date through
select convert(datetime, #input, 103) -- 2010-01-12 00:00:00.000
-- the case below returns 0 { = invalid date }
-- this uses 8-digit format which is always interpreted YYYYMMDD regardless
-- of language or dateformat settings
select case
when #input not like '__/__/____' then 0
else isdate(right(#input,4)+right(left(#input,5),2)+left(#input,2))
end

Resources