How to convert '01/01/0001' to datetime2 - sql

I was trying to display a '01/01/0001' from sql if the value is null. But when I convert the value into datetime2, it says:
Msg 517, Level 16, State 3, Line 18
Adding a value to a 'datetime2' column caused an overflow.
this is what I tried:
Declare #NewDate as DateTime2
SELECT #Tem = Ab.Date_out
FROM Timesheet_header Ab
WHERE (Ab.Employee_id = 3424)
AND (Ab.Work_date BETWEEN ('2017-08-31') AND ('2017-08-31'))
print #Tem
if(#Tem IS NULL)
Begin
set #NewDate = CONVERT(VARCHAR, DATEADD(DAY,-5,CAST('0001-01-01' AS DATETIME2)),100)
--some select clause here
End
else
Begin
--some select clause here
End
print #Tem
print #NewDate

Here is your problem:
DATEADD(DAY,-5,CAST('0001-01-01' AS DATETIME2))
Datetime2 min value is 0001-01-01, but you try to create a value that's 5 days before.
From MSDN:
Date range 0001-01-01 through 9999-12-31
Also, your #NewDate variable is of type datetime2, but you try to populate it with varchar(100) -
set #NewDate = CONVERT(VARCHAR, DATEADD(DAY,-5,CAST('0001-01-01' AS DATETIME2)),100)
That makes no sense. If anything, you should be doing something simple like this:
SET #NewDate = '0001-01-01';

Related

Passing Variable from stored procedure to another

I have a stored procedure that I need pass the parameter from one to the other procedure and have it display as an output. I am declaring the following in the header of my procedure [xxx].[zzzz_ERP_Cyyyyy]
DECLARE #ProcedureLogRowKey INT
DECLARE #ProcedureRecordCount INT
DECLARE #ProcedureStartDateTime DATETIME
DECLARE #ProcedureLog_Note NVARCHAR(100)
EXEC [XXX].[spciProcedurePerformanceStartRecord_help]
'.[xxx].[zzzz_ERP_Cyyyyy]',
1,
#ProcedureStartDateTime,
'Contract Check',
#ProcedureLogRowKey OUTPUT
I am getting the following error:
Msg 515, Level 16, State 2, Procedure spciProcedurePerformanceStartRecord_help, Line 33 [Batch Start Line 17]
Cannot insert the value NULL into column 'YSTRTDTT_0', table '000.xxx.YPERLOG'; column does not allow nulls. INSERT fails.
Here is the procedure that I am getting the variable from to pass into my procedure [xxx].[zzzz_ERP_Cyyyyy]
CREATE PROCEDURE [xxx].[spciProcedurePerformanceStartRecord_help]
(#ProcedureName VARCHAR(200),
#ProcedureRecordCount INT = 1,
#ProcedureStartDateTime DATETIME = GETDATE,
#ProcedureLog_Note NVARCHAR(100),
#ProcedureLogRowKey INT OUTPUT --- I am passing this into my proc and
displaying it as output
)
AS
BEGIN
-- Set Default return for #ProcedureLogRowKey, used if logging is not turned on.
SET #ProcedureLogRowKey = -1;
-- Check to see if performance logging is enabled
IF EXISTS(SELECT ROWID FROM LIVE.YPERCON
WHERE YPROCNM_0 = #ProcedureName AND YLOGENA_0 = 2)
BEGIN
INSERT INTO xxx.YPERLOG (YROWKEY_0, YPROCNM_0, YRECCNT_0, YSTRTDTT_0, YENDDTT_0, YLOGNOTE_0,
YDURMS_0, CREDATTIM_0, UPDDATTIM_0, AUUID_0, CREUSR_0, UPDUSR_0)
SELECT
ISNULL(MAX(YROWKEY_0), 0) + 1,
#ProcedureName, #ProcedureRecordCount, #ProcedureStartDateTime,
'1753-01-01',
#ProcedureLog_Note, 0,
GETDATE(), GETDATE(), NEWID(), 'admin', 'admin'
FROM
xxx.YPERLOG
SELECT #ProcedureLogRowKey = ISNULL(MAX(YROWKEY_0), 0)
FROM xxx.YPERLOG
END
ELSE
BEGIN
DECLARE #Count integer
SELECT #Count = COUNT(0)
FROM LIVE.YPERERR
WHERE YPROCNM_0 = #ProcedureName
IS ISNULL(#Count, 0) = 0
INSERT INTO LIVE.YPERERR (YPROCNM_0, YREQDT_0, YLASTDT_0, YERRMSG_0,
CREDATTIM_0, UPDDATTIM_0, AUUID_0, CREUSR_0, UPDUSR_0)
VALUES (#ProcedureName, GETDATE(), '1753-01-01', 'Controller not defined or active',
GETDATE(), GETDATE(), NEWID(), 'admin', 'admin')
ELSE
UPDATE xxx.YPERERR
SET YLASTDT_0 = GETDATE()
WHERE YPROCNM_0 = #ProcedureName
END
END
Thanks in advance.
The issue is in procedure [xxx].[spciProcedurePerformanceStartRecord_help] with parameter #ProcedureStartDateTime DATETIME. You should set its default value this way:
In declaration set default value as NULL
#ProcedureStartDateTime DATETIME = NULL
It would look like tihs
CREATE PROCEDURE [xxx].[spciProcedurePerformanceStartRecord_help]
(
#ProcedureName VARCHAR(200)
,#ProcedureRecordCount INT = 1
,#ProcedureStartDateTime DATETIME = NULL
,#ProcedureLog_Note NVARCHAR(100)
,#ProcedureLogRowKey INT OUTPUT
)
AS
BEGIN
-- procedure's body
END
Inside procedure, at the beginning, check if #ProcedureStartDateTime parameter's value is NULL and if it is, set its value to GETDATE().
SET #ProcedureStartDateTime = ISNULL(#ProcedureStartDateTime, GETDATE())
You have declared DECLARE #ProcedureStartDateTime DATETIME and did not set any value to it. so, it is having NULL value and you are passing NULL value to the procedure execution
EXEC [XXX].[spciProcedurePerformanceStartRecord_help]
'.[xxx].[zzzz_ERP_Cyyyyy]',
1,
#ProcedureStartDateTime, -- NULL value passed here
'Contract Check',
#ProcedureLogRowKey OUTPUT
As the target column 'YSTRTDTT_0', table '000.xxx.YPERLOG', does not allow NULLs, you are getting error.

Using a CASE statement in a WHERE clause in SQL Server

I am trying to create query form on a website. First object is a dropdown list with operators. Default first value in the dropdown list is NULL(1), second value is LIKE(2), etc... Second object is a textbox where the user can enter a string like "A".
Therefore, I am trying to build the below SQL query to simulate the variables coming from the website. It runs and returns all values when the #op = 1. But I keep getting the following error when I change #op = 2:
Conversion failed when converting the nvarchar value 'Tom LIKE A%' to data type int."
DECLARE #StartDate DATETIME2(7) = '2017-11-08 00:00:00.0000000 +00:00'
DECLARE #EndDate DATETIME2(7) = '2017-11-08 00:00:00.0000000 +00:00'
DECLARE #Op INT = 2
DECLARE #name NVARCHAR(25) = 'A'
SELECT
name,
dttm
FROM
tableName
WHERE
dttm BETWEEN #StartDate AND #EndDate
AND CASE #Op
WHEN 1 THEN 1
WHEN 2 THEN name + ' LIKE ' + #name +'%'
END <> 0
Don't use case. Just use regular boolean logic:
WHERE dttm BETWEEN #StartDate AND #EndDate AND
( (#op = 1) OR
(#op = 2 AND name LIKE #name + '%')
)
Your specific issue involves constructing a LIKE comparison in a string. However, the above appears to be what you want to do.

Handle Julian and Real Times in one query

Hi Below is some sample data
DECLARE #Time TABLE (
[Time] VARCHAR(250),
[Count] VARCHAR(250)
)
INSERT INTO #Time ([Time],[Count])
VALUES
('13:52','2'),
('13:53','2'),
('13:54','5'),
('13:55','3'),
('13:56','3'),
('13:57','1'),
('13:58','4'),
('13:59','1'),
('130','72'),
('1300','61'),
('1301','40'),
('1302','51'),
('1303','53'),
('1304','59'),
('1305','62'),
('1306','36'),
('1307','56'),
('1308','52')
Select * from #Time
Is there a way to handle both data types so that it outputs as a real time
I use a function that partly works but am getting and error each time:
Msg 8116, Level 16, State 1, Line 1
Argument data type varchar is invalid for argument 2 of dateadd function.
The function I use is as follows and wondered if this can be adopted/changed to account for the poor data eg both types of Times (Julian/Regular).
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
-- Add the parameters for the function here
#JulianTime INT
)
RETURNS DATETIME
AS
BEGIN
-- Declare the return variable here
DECLARE #Result DATETIME
-- Add the T-SQL statements to compute the return value here
IF #JulianTime >= 0 AND #JulianTime < 1440 -- this ensures that the result will be in the range of a datetime data type
SET #Result = DATEADD(MINUTE, #JulianTime, CAST('00:00' AS TIME))
ELSE
SET #Result = CAST('00:00' AS TIME)
-- Return the result of the function
RETURN #Result
END
GO
ADDITION:
The COMPLETE datetime function is here:
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianDateTimeToSQLDateTime] (
-- Add the parameters for the function here
#JulianDate INT,
#JulianTime INT = 0
)
RETURNS DATETIME
AS
BEGIN
-- Declare the return variable here
DECLARE #Result DATETIME
-- Add the T-SQL statements to compute the return value here
IF #JulianDate > 640333 -- this ensures that the result will be in the range of a datetime data type
BEGIN
SET #Result = DATEADD(DAY, (#JulianDate-429), CAST('Jan 1 0001' AS DATETIME2))
IF #JulianTime < 1440 AND #JulianTime >= 0 -- this ensures that the time is between 00:00 and 23:59
SET #Result = DATEADD(MINUTE, #JulianTime, #Result)
END
ELSE
SET #Result = 'Jan 1 1753'
-- Return the result of the function
RETURN #Result
END
GO
I am not sure what exactly are you trying to do from your give information. But I tried to modify the function to return time when I pass it JulianTime as a varchar. Here is the code -- (try to make changes accordingly though)
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
-- Add the parameters for the function here
#JulianTime VARCHAR(255)
)
RETURNS TIME(0)
AS
BEGIN
-- Declare the return variable here
DECLARE #Result TIME(0), #HOUR VARCHAR(2), #MINUTES VARCHAR(2)
-- DECLARE #JulianTime VARCHAR(255)
-- SET #JulianTime = '13:02'
SET #HOUR = SUBSTRING(#JulianTime, 1, 2)
IF(LEN(#JulianTime) = 4)
SET #MINUTES = SUBSTRING(#JulianTime, 3, 2)
IF(LEN(#JulianTime) = 5)
SET #MINUTES = SUBSTRING(#JulianTime, 4, 2)
SET #Result = CONCAT(#HOUR, ':', #MINUTES)
-- PRINT #RESULT
-- Return the result of the function
RETURN #Result
END
GO
I've updated the FUNCTION.
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
#timeString varchar(250)
)
RETURNS TIME
AS
BEGIN
DECLARE #Result TIME ;
/* Ensure that we're working with a fixed date */
DECLARE #epoch datetime = '19000101' ;
/* Check the string for ':' */
IF CHARINDEX(':',#timeString) > 0
/* Can #timeString be parsed as a valid time? */
SET #Result = TRY_PARSE(#timeString AS time) ; /* Returns NULL if bad time string. */
ELSE
/* No ':' so check if valid julian time. */
IF TRY_CONVERT(int,#timeString) IS NOT NULL AND CONVERT(int,#timeString) BETWEEN 0 AND 1439
SET #Result = CAST( DATEADD(minute, CONVERT(int,#timeString), #epoch) AS time) ;
ELSE
SET #Result = NULL ;
RETURN #Result ;
END
http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=1ca82cd76b2932593262601b1742f602
This will only work if you're using something greater than SQL 2012+ because of TRY_PARSE and TRY_CONVERT. If you're lower than 2012, you can modify that bit to do what those functions essentially do.
Select
CASE WHEN CHARINDEX(':',[Time]) > 0 THEN CAST([Time] AS TIME) ELSE DATEADD(MINUTE, TRY_CAST([Time] AS INT), CAST('00:00' AS TIME)) END AS [RealTime],
*
from #Time
This appears to do the trick, thanks for the valuable input
For SQL 2008, use this function:
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
#timeString varchar(250)
)
RETURNS TIME
AS
BEGIN
DECLARE #Result time ;
/* Ensure that we're working with a fixed date */
DECLARE #epoch datetime = '19000101' ;
/* Check the string for ':' */
IF CHARINDEX(':',#timeString) > 0
IF ISDATE(#timeString) = 1
/* Is #timeString a valid time object? */
SET #Result = CAST(#timeString AS time) ;
ELSE
SET #Result = NULL ;
ELSE
/* No ':' so check if valid julian time. */
IF ISNUMERIC(#timeString) = 1 AND CONVERT(int,#timeString) BETWEEN 0 AND 1439
SET #Result = CAST( DATEADD(minute, CONVERT(int,#timeString), #epoch) AS time) ;
ELSE
SET #Result = NULL ;
RETURN #Result ;
END

How to extract date fields from string/text field in sql server 2005

There is a text filed in a table called as description. I would like to extract two date fields from this string when there is an occurrence of '~' character using sql server 2005 stored procedure. Help me out in this case.
Example: string: '长期租金;10/1/2012 ~ 10/31/2012'. At occurrence of ~ operator I would like to have from-date: 20121001 and to-date:20121031.
Here is a method which will give the start and end dates. I left most of the testing selects in place but commented out.
DECLARE #string AS NVARCHAR(255)
DECLARE #Seperator as char(1) = '~'
declare #CharStartDate as varchar(10)
declare #CharStopDate as varchar(10)
declare #StartDate as date
declare #StopDate as date
declare #I int
--SET #string = 'xvvvvvvcc;1/09/2012 ~ 1/10/2012xx'
--SET #string = 'xvvvvvvcc;12/31/2012 ~ 1/1/2012xx'
--SET #string = 'xvvvvvvcc;12/1/2012 ~ 10/0/2012xx'
SET #string = 'xvvvvvvcc;1/2/2012 ~ 1/3/2012xx'
--longest date 12/31/2011 = 10
--shortest date 1/1/2012 = 8
-- width of seperator = 3
SELECT
#CharStartDate = substring (#string, CHARINDEX(#Seperator,#string)-11,10)
,#CharStopDate = substring (#string, CHARINDEX(#Seperator,#string)+2,10)
--SELECT #CharStartDate,#CharStopDate
select #I = ascii(substring(#CharStartDate,1,1))
While #I > 57
BEGIN
set #CharStartDate = substring(#CharStartDate,2,10)
--select #CharStartDate
select #I = ascii(substring(#CharStartDate,1,1))
END
select #I = ascii(substring(REVERSE(#CharStopDate),1,1))
While #I > 57
BEGIN
set #CharStopDate = REVERSE(substring(REVERSE(#CharStopDate),2,10))
--select #CharStopDate
select #I = ascii(substring(REVERSE(#CharStopDate),1,1))
END
--select ascii(';'),ascii('9'),ascii('8'),ascii('7'),ascii('6'),ascii('6'),ascii('4'),ascii('3'),ascii('2'),ascii('1'),ascii('0')
SELECT #StartDate = #CharStartDate,#StopDate = #CharStopDate
--SELECT #I,#string,#Seperator,#CharStartDate,#CharStopDate,#StartDate,#StopDate
select datediff(dd,#StartDate,#StopDate) AS 'DateDiff',#StartDate as 'Start Date',#StopDate as 'Stop Date'
I will leave it to you to check for the seperator.
CREATE FUNCTION [dbo].[RemoveAlphaCharacters](#Temp nvarchar(max))
RETURNS nvarchar(max)
AS
BEGIN
WHILE PatIndex ('%[^0-9~/]%', #Temp) > 0
SET #Temp = Stuff(#Temp, PatIndex('%[^0-9~/]%', #Temp), 1, '')
RETURN #Temp
END
DECLARE #string nvarchar(max) = '长期租金;10/1/2012 ~ 10/31/2012'
SELECT CONVERT(date, SUBSTRING([dbo].[RemoveAlphaCharacters](#string), 0,
CHARINDEX('~', [dbo].[RemoveAlphaCharacters](#string))), 101) AS BDate,
CONVERT(date, SUBSTRING([dbo].[RemoveAlphaCharacters](#string),
CHARINDEX('~', [dbo].[RemoveAlphaCharacters](#string)) + 1,
CHARINDEX('~', REVERSE([dbo].[RemoveAlphaCharacters](#string)))), 101) AS EDate
In this instance you can use the following but really you need an exists clause or something like that to test the string for the tilde (~) and as everyone else has stated, this only works if the string always has a semicolon(;) and a tilde(~). You can convert to the strings into datetime fields if you need.
I have placed the string in a variable to make it easier to read...
DECLARE #string AS NVARCHAR(255)
SET #string = '长期租金;10/1/2012 ~ 10/31/2012'
SELECT StartDate = SUBSTRING(#string,CHARINDEX(';',#string)+1,LEN(#string)-CHARINDEX('~',#string)-1)
,EndDate = LTRIM(RIGHT(#string,LEN(#string)-CHARINDEX('~',#string)))
i have never used the older version of SQL cause i just graduated but doesnt it have the EXTRACT() function?.. The syntax goes like this below.
SELECT First_Name ,
EXTRACT ( CAST(Created_date AS DATE) FROM Created_date ) AS Date_only ;
You specify 'First_name' to let SQL know you want it as a column and 'created_date' is the field from which youre trying to separate the date. the cast function converts your field to DATE value before extractig it.
i hope this helps . thank you. if im wrong please let me know i would like to improve myself.

Try/Catch in UDF not possible? How to "TryCast" a varchar to datetime?

how can i convert a varchar parameter into datetime and if cast fails use GetDate() as default?
I've tried to put it in a Try/Catch but apparently that doesn't work in a UDF. It also does not work to simply check if the datetime is null, because it'll throw an exception('The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value'):
CREATE FUNCTION [dbo].[getRZUInfo]
(
#IMEI varchar(20),
#StrDeliveryDate varchar(20)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #Info VARCHAR(8000)
DECLARE #DeliveryDate datetime;
SET #DeliveryDate = Convert(datetime,#StrDeliveryDate,102);
IF #DeliveryDate IS NULL
SET #DeliveryDate=GetDate();
SELECT #Info = COALESCE(#Info + '|', '') + 'TAT_B2B: ' + Convert(varchar,tabData.TAT_B2B) + ', AC' + Convert(varchar,tabData.fimaxActionCode) + ', Diff: ' + Convert(varchar,DateDiff(day,tabData.Received_date,#DeliveryDate))
FROM tabData
WHERE (SSN_Number = #IMEI) AND (Received_Date >= DATEADD(month, -3, #DeliveryDate))
ORDER BY SSN_Number,Received_Date DESC
return #Info
END
SET #DeliveryDate = CASE
WHEN Isdate(#StrDeliveryDate) = 1 THEN
CONVERT(DATETIME, #StrDeliveryDate, 102)
ELSE Getdate()
END
A common flaw with IsDate is that it is unable to take in a date format specifier that CAST/CONVERT can.
See this:
set dateformat dmy
declare #StrDeliveryDate varchar(20) set #StrDeliveryDate = '2011.12.13'
select CASE
WHEN Isdate(#StrDeliveryDate) = 1 THEN
CONVERT(DATETIME, #StrDeliveryDate, 102)
ELSE Getdate()
END
output: 2011-03-21 22:19:54.683
This is a better function for testing 102-formatted dates specifically. Actually 102 is much easier, this is flexible enough to pick up yy/yyyy, m/mm, d/dd.
create function dbo.Is102Date(#any varchar(50))
-- 102 = yyyy.mm.dd
returns bit as begin
set #any = ltrim(rtrim(#any))
declare #theyear varchar(10)
set #TheYear = case
when #any like '%[^0-9.]%' then null
when #any like '[0-9][0-9].%[0-9].%[0-9]' then
case when LEFT(#any,2) >=50
then '19'+LEFT(#any,2)
else '20'+LEFT(#any,2)
end
when #any like '[0-9][0-9][0-9][0-9].%[0-9].%[0-9]' then
LEFT(#any,4)
end
declare #YYYYMMDDToTest varchar(50)
set #YYYYMMDDToTest = case
when #TheYear is not null then
#TheYear
+ -- month
SUBSTRING(#any, charindex('.',#any) +1,
charindex('.',#any,charindex('.',#any)+1)-
charindex('.',#any)-1)
+ -- day
right(#any,charindex('.',reverse(#any))-1)
end
return ISDate(#YYYYMMDDToTest)
end
GO
Use it instead of ISDATE to test for 102-formatted dates in varchar.
Just checking when Null
IF #StrDeliveryDate IS NULL
SET #DeliveryDate = GetDate();
ELSE
SET #DeliveryDate = Convert(datetime, #StrDeliveryDate, 102);