SQL: converting datetime from character string when inserting date - sql

I have the following procedure:
ALTER PROCEDURE [dbo].[myProcedute]
#mydate VARCHAR(8000) = NULL
IF #mydate = ''
BEGIN
SET #mydate = NULL
END
ELSE
BEGIN
SET #mydate = CONVERT(DATETIME, #mydate, 103) -- dd/mm/yy
END
INSERT INTO dbo.myTable(theDate) VALUES(#mydate)
And I execute it like this:
EXEC [dbo].[myProcedure] '02/02/2012'
After execution I get this error:
Conversion failed when converting datetime from character string.
I execute it from my vb6 code and the date can vary. This time is
'02/02/2012' but next time it may be ''(empty).
When it comes as '', I need it to insert a NULL as you can see in the IF clause.
Why am I getting this error?
Thanks a lot !

Use ISDATE() to check if it is a valid date.
Conversion seems fine. And as comments suggests, it would solve a lot if you could change parameter to DATE
ALTER PROCEDURE [dbo].[myProcedute]
#mydate VARCHAR(8000) = NULL
IF ISDATE(#mydate)
BEGIN
SET #mydate = CONVERT(DATETIME, #mydate, 103) -- dd/mm/yy
END
ELSE
BEGIN
SET #mydate = NULL
END
INSERT INTO dbo.myTable(theDate) VALUES(#mydate)

It is better to format your date string to ISO format (yyyymmdd) which guaranteed to work on any sql-server. Assuming you vb code passing it like dd/mm/yyyy (as per your data). Try this;
--Format #mydate to yyyymmdd
SELECT #mydate = CASE LEN(#mydate) WHEN 10
THEN RIGHT(#mydate,4)+ SUBSTRING(#mydate,4,2)+ LEFT(#mydate,2)
ELSE NULL END
--Insert
INSERT INTO dbo.myTable(theDate) VALUES(#mydate)

Related

Convert the string '01011900' or '19990101' or any format to date and with required format '01/01/1990'

I have tried with the following sample
SELECT
FORMAT(CONVERT(DATETIME,'01011900'), 'dd/MM/yyyy')
FROM
identities
WHERE
id_type = 'VID'
Try this:
SELECT FORMAT(CONVERT(DATETIME,STUFF(STUFF('01011900',5,0,'/'),3,0,'/')),'dd/MM/yyyy')
Insert / using STUFF, and then convert it.
STUFF(STUFF('01011900',5,0,'/'),3,0,'/') -- 01/01/1900
Update:
I tried the following also,
DECLARE #DateString varchar(10) = '12202012' --19991231 --25122000
DECLARE #DateFormat varchar(10)
DECLARE #Date datetime
BEGIN TRY
SET #Date = CAST(#DateString AS DATETIME)
SET #DateFormat = 'Valid'
END TRY
BEGIN CATCH
BEGIN TRY
SET #DateFormat = 'ddMMyyyy'
SET #Date = CONVERT(DATETIME,STUFF(STUFF(#DateString,5,0,'/'),3,0,'/'))
END TRY
BEGIN CATCH
SET #DateFormat = 'MMddyyyy'
SET #Date = CONVERT(DATETIME,STUFF(STUFF(#DateString,1,2,''),3,0,
'/' + LEFT(#DateString,2) + '/'))
END CATCH
END CATCH
SELECT
#DateString InputDate,
#DateFormat InputDateFormat,
#Date OutputDate
Your data should be 19000101.So your input needs to be modified first then we need to use Convert to get your appropriate format.
declare #inp varchar(10) = '01011900'
select CONVERT(varchar, cast(right(#inp,4)+''+left(#inp,4) as datetime), 101)
--Output : 01/01/1900
Right now your question is absurd. There cannot be a generic format that can handle all the date formats, you need to provide that information to your query ( you would be much better of with a stored procedure in this scenario ) where you pass the date format string too. You could do something like this in your SELECT CASE
if the format is ddmmyyyy, do what JesuRaja suggested. But its already answered in SO
SELECT CONVERT (datetime, Stuff(Stuff('311012',5,0,'.'),3,0,'.'), 4)
if its mmddyyyy, see this answer
DECLARE #Date char(8)
SET #Date='12312009'
SELECT CONVERT(datetime,RIGHT(#Date,4)+LEFT(#Date,2)+SUBSTRING(#Date,3,2))
if its yyyymmdd, just do a CAST
SELECT CAST('20041223' AS datetime)
Bottomline is, you must specify the date format. For example, consider the string 20122012. Can you guess the date format?
Also, you cannot force the server to use / as your separator. The SQL Server will use either /, . or - depending on the Culture of the server.

Conversion failed when converting the nvarchar value '06/30/2012' to data type int

I'm having issues trying to set two variables, a From Date, and a To Date. Once I solve the issue for one, the other will be easy enough to figure out. I'm getting the error:
Conversion failed when converting the nvarchar value '06/30/2012' to data type int.
It's worth noting that I'm using a view to bring various tables together, and then executing the ones I want via sp_executesql. When I print my query I can see that it's recognizing the #fromdate as 0, perhaps that's the issue..
declare #fromdate nvarchar
declare #todate nvarchar
select #fromdate = '03/01/1999'
select #todate = ''
IF #fromdate <> ''
BEGIN
SELECT #sql = #sql + ' and convert (nvarchar,document_Date,101) > '+#fromdate+''
END
if #todate <> ''
BEGIN
SELECT #sql = #sql + ' and convert(nvarchar,document_date,101) > '+#todate+''
END
The column document_date is datetime. Any ideas? If so, could you explain why this is occurring so I can learn and avoid it happening in the future? I've included the print SQL below.
SELECT [system_status]
,[document_status_code]
,[rpt_category]
,[category]
,[user_status_cd]
,[user_status]
,[assigned_to_id]
,[assigned]
,[assigned_to_date]
,[owner_id]
,[owner]
,[rpt_acct_code]
,[acct_name]
,[rpt_title]
,[job_name]
,[logged_time]
,[rpt_format_type]
,[rpt_run_id]
,[rpt_doc_id]
,[rpt_id]
,[rpt_filename]
,[rpt_file_path]
,[rpt_run_name]
,[sla_start_date]
,[sla_due_date]
,[sla_completed_date]
,[sla_status]
,[SLA_Days]
,[Document_Date]
FROM VW_Document_Main
WHERE 1=1 and convert (nvarchar,document_Date,101) > 0
order by document_status_code ,owner_id
Part of the problem is that you do not have a length on your declaration of #fromdate
It is only returning the first character because you do not have a length. The declaration should say:
declare #fromdate nvarchar(10)
declare #todate nvarchar(10)
Since you do not have a length, it is returning 0 which is the first character.
Secondly, you are also comparing string values of the dates, you should be comparing the date values.
declare #fromdate datetime
declare #todate datetime
Then your code could be:
SELECT #sql = #sql + ' and document_Date > '''+convert(varchar(10), #fromdate, 101)+''''
The literal
'03/01/1999'
is a string literal. You are converting document_Date to a varchar, then doing an inequality comparison
and convert (nvarchar,document_Date,101) > '+#fromdate
Since the dates are not formatted YYYYMMDD, the comparison is unlikely to produce the comparison you expect.
If #fromdate for example is '04/01/1900', it will be greater than '03/01/1999' because '04' is greater than '03'.
Instead, convert #fromdate to the same type as document_Date, e.g.
AND document_Date > convert(datetime, #fromdate)
If the column document_date is already a datetime, why not declare declare #fromdate
and #todate as datetime as well, then your code will be simpler and you won't have to do any conversion. It seems to me the conversion is unnecessary for what you are trying to do.
Problem #1
declare #fromdate nvarchar
select #fromdate = '03/01/1999'
Why are you defining these as Unicode strings, never mind strings without a length? Why are you using an ambiguous, unreliable format for the literal? Is that March 1st or January 3rd? Are you sure your instance of SQL Server agrees with you?
Problem #2
SELECT #sql = #sql + ' and convert (nvarchar,document_Date,101) > '+#fromdate+''
Why are you converting your column to a Unicode string, never mind a string without a length? Why are you comparing it as a string? You know that '05/05/2010' is greater than '02/21/2015', when compared as a string, right?
Solution
Stop using ambiguous formats. Stop thinking that dates are strings and should be compared as such.
How about:
DECLARE #fromdate DATETIME = '19990301'; -- guessing you meant March 1st.
-- See why ambiguous formats are bad and you should never use them?
...
SELECT #sql += ' AND document_Date > #fromdate;';
EXEC sp_executesql #sql, N'#fromdate DATETIME', #fromdate;
Now you don't have to do any conversions at all.

The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value - Leap Year

I get this error in stored procedure code and I discovered one of the records is from a leap year date 2008-02-29. How do I get around this with the code I have. Here is the code:
set #ContractDate = cast(cast(#Year as nvarchar(4))
+ '/' + cast(datepart(mm,#ContractDate) as nvarchar(2))
+ '/' + cast(datepart(dd,#ContractDate) as nvarchar(2)) as datetime)
First off:
What values do you have for #Year and #ContractDate?
And what format/type is #ContractDate?
I ask because this works for me on us_english SQL Server 2012
SELECT cast('2008/02/29' as datetime)
However, if I change SET DATEFORMAT then I can break the above code
-- breaks
SET DATEFORMAT DMY;
SELECT cast('2008/02/29' as datetime)
Using ISO date format is OK no matter what I use for SET DATEFORMAT
SET DATEFORMAT DMY;
SELECT cast('20080229' as datetime);
SET DATEFORMAT MDY;
SELECT cast('20080229' as datetime);
SET DATEFORMAT YDM;
SELECT cast('20080229' as datetime);
Conclusion: you are using non ISO date formats and relying on implicit conversions
It is better to get the string in ISO format (yyyymmdd) before converting to datetime/date and it will work in any server regardless of culture settings
If #ContractDate is a datetime/date type and #year is like 2012/'2012' then following should work. Working Example
Set #ContractDate = convert(datetime,
convert(varchar(4),#year) + right(convert(varchar(8),#ContractDate,112),4))
ALTER PROCEDURE [dbo].[Sden_report1]
#fromdt nvarchar(13),
#todt nvarchar(13)
AS
BEGIN
select AD_PID,AD_Appointmentdate,AD_Patientname,AD_Patientphno,AD_Visitpurpose
from Appointment_Details1
where
--PL_CID = #CID and PL_Itemcode = #JCode AND
(#fromdt = '' OR (DATEDIFF(DAY,AD_Appointmentdate, #fromdt) <= 0))
AND (#todt = '' OR (DATEDIFF(DAY,AD_Appointmentdate, #todt) >= 0))
end
GO
When i Execute the procedure
i will get below error:
EXEC Sden_report1 '20-11-2012','20-05-2013'
Error
The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
Anyone Help...`enter code here`

Validate datetime inside a t-sql function

I need to validate a date inside a social security number checking function. The date format it should accept is ddmmyyyy, for example 01012000 (first of Jan, 2000).
I have tried converting this string into yyyy-mm-dd, and using IsDate() function, but the problem is that sometimes the datetimeformat of SqlServer might be something else like dmy, and I cannot use the "set DateFormat ymd" inside a function because it gives this error:
Invalid use of a side-effecting operator 'SET COMMAND' within a function.
Also tried a try .. catch block but with the same results.
So I need a way to validate datetime, regardless of the SqlServer dateformat, in a user function.
This snippet of code will try to convert the input. It first changes the string to a German time format dd.mm.yyyy with convert format 104. It uses begin try to suppress any error during the conversion.
If it succeeds, the date is in #output_dt. If it fails, #output_dt will be null.
declare #input_str varchar(25)
declare #output_dt date
set #input_str = '31122011'
if len(#input_str) >= 8
begin
declare #german_str varchar(25)
select #german_str = substring(#input_str, 1, 2) + '.' +
substring(#input_str, 3, 2) + '.' +
substring(#input_str, 5, 4)
begin try
select #output_dt = convert(date, #german_str, 104)
end try
begin catch
end catch
end
select #output_dt
If you can't use begin catch, you could create a table with valid dates. This example creates a table called ValidDates with dates from 1900 to 2100:
if object_id('ValidDates') is not null
drop table ValidDates
create table ValidDates (date_str varchar(8), dt date)
go
truncate table ValidDates
declare #start_dt date
declare #end_dt date
set #start_dt = '1900-01-01'
set #end_dt = '2100-01-01'
; with cte as
(
select #start_dt as dt
union all
select dateadd(day, 1, dt)
from cte
where dt < #end_dt
)
insert ValidDates
(date_str, dt)
select replace(convert(varchar(10), dt, 104),'.','')
, dt
from cte
option (maxrecursion 0);
You can then check for a valid date like:
select #output_dt = dt from ValidDates where date_str = #input_dt
Seems like
SELECT ISDATE('2005-05-22') is affected by SET DATEFORMAT dmy and returns zero
but
SELECT ISDATE('20050522') is not affected even when dateformat is dmy, so this one can be used independently from any dateformat used as default by database.

convert strings of type mm/dd/yyyy h to date time

I have a function which converts all of the strings to datetime.
ALTER FUNCTION formatit(
#fromtime VARCHAR(50) -- varchar
)
RETURNS DATETIME
AS
BEGIN
DECLARE #from datetime
IF (CHARINDEX('NOON',#fromtime,0)) = 0
SET #from = CONVERT(DATETIME, #fromtime)
ELSE
SET #from =CONVERT(DATETIME, '01/01/2000 12pm')
RETURN(#from)
END
SELECT dbo.formatit('04/12/2011 12 ')
So when u see the last select stmt it throws an error saying:
The conversion of a char data type to a datetime data type
resulted in an out-of-range datetime value.
It works fine if i give time 4 pm or 4:00. But it gives an error if i give just 4. Kindly let me know how i can handle this?
You could add a lot of code to look at the string and see if there is a ':' (like you have code to look for NOON). The problem is that if the string ends in 12PM the conversion will work too. So you would have to do something like
ALTER FUNCTION formatit(
#fromtime VARCHAR(50) -- varchar
)
RETURNS DATETIME
AS
BEGIN
DECLARE #from datetime
IF (CHARINDEX('NOON',#fromtime,0)) <> 0
BEGIN
SET #from =CONVERT(DATETIME, '01/01/2000 12pm')
END
ELSE IF (CHARINDEX('PM',#fromtime,0)) = 0 AND (CHARINDEX('AM',#fromtime,0)) = 0 AND (CHARINDEX(':',#fromtime,0)) = 0
BEGIN
SET #fromtime = #fromtime+':00'
SET #from =CAST(#fromtime AS datetime)
END
ELSE
BEGIN
SET #from =CAST(#fromtime AS datetime)
END
return(#from)
END
It looks like whitespace is ignored - I tried these and they all worked...
SELECT dbo.formatit('04/12/2011 12 ')
SELECT dbo.formatit('04/12/2011 12:00')
SELECT dbo.formatit('04/12/2011 12PM')
SELECT dbo.formatit('04/12/2011 12AM')
SELECT dbo.formatit('NOON')
Really you should look at the data you are using to feed this function with something other than TSQL so you have a better string parser.
Your call to dbo.formatit('04/12/2011 12 ') results in a call to convert(datetime, '04/12/2011 12 '). This string is not a valid input to convert to a date/time value.
See the list of formats in the CAST and CONVERT reference in MSDN. If you need to convert this string, you will need to change the time portion into "12:00PM" or just "12:00" (which is assumed to be in the 24-hour format).
First, I would find all the unique time occurrences in your table, something like:
select distinct rtrim(substring(#timeField,charindex(' ',#timeField)+1,99))
as TimePortion
This will give you a sense of what you are dealing with.
Then, in your function, break apart the date and time portions...
Now, based on what you found from the query, you need to spell out what to do with the times you find. For example, if the time portion is numeric, you might simply append :00 to it (i.e. 4 becomes 4:00). If you see NOON, you might replace it with 12:00pm, etc.
ALTER FUNCTION formatit( #fromtime VARCHAR(50) )
RETURNS DATETIME
AS
BEGIN
declare #dtPortion VARCHAR(12)
declare #tmPortion VARCHAR(32)
declare #x INT
SET #x = charindex(' ',#fromTime)
SET #dtPortion = left(#fromTime,#x-1)
SET #tmPortion = rtrim(substring(#fromTime,#x+1,99))
-- Figure out what to do
SELECT #FromTime =
CASE
WHEN IsNumeric(#tmPortion) = 1 THEN #dtPortion+' '+#tmPortion+':00'
WHEN #tmPortion = 'NOON' THEN #dtPortion+' 12:00pm'
ELSE
#dtPortion+' 12:00pm'
END
SET #from =CONVERT(DATETIME, '01/01/2000 12pm')
RETURN(#from)
END
Go
Hope this gets you started