On a table I have a bigint column that stores a timestamp with a microsecond precision like:
636453251396217655
636453251398405201
636453251592389899
636453251668326820
I have to build a script that, if that date is older than a week, the row must moved to another table.
I tried to convert to date using:
CREATE FUNCTION [dbo].[UNIXToDateTime] (#timestamp bigint)
RETURNS datetime
AS
BEGIN
DECLARE #ret datetime
SELECT #ret = DATEADD(second, #timestamp, '1970/01/01 00:00:00')
RETURN #ret
END
and used like:
select dbo.UNIXToDateTime(636453251396217655)
but because of the bigint my script crash because:
Arithmetic overflow error during expression conversion in int data
type
I can lose precision, the important is the date part that is the main part of the sql filter.
Demo: http://sqlfiddle.com/#!6/24f05/1
There's an answer here for converting with epoch values:
CREATE FUNCTION [dbo].[fn_EpochToDatetime] (#Epoch BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #Days AS INT, #MilliSeconds AS INT
SET #Days = #Epoch / (1000*60*60*24)
SET #MilliSeconds = #Epoch % (1000*60*60*24)
RETURN (SELECT DATEADD(MILLISECOND, #MilliSeconds, DATEADD(DAY, #Days, '1/1/1970')))
END;
You can use that function but simply divide your epoch values. As you are fine with the loss of fidelity, this will suit your needs perfectly. For example:
DECLARE #epoch BIGINT = 636453251396217655
SELECT dbo.[fn_EpochToDatetime](#epoch/100000)
Function 1:
I need to create an sql server function named FirstDayInQtr to return the first day in the respective quarter of year when a date is input. This function should be defined with the following header.
CREATE FUNCTION FirstDayInQtr(#InputDate datetime) RETURNS datetime AS…
Should return the date of first day in the respective quarter. like 1/1/2016
Function 2:
A function to check if an input string consists of UPPERCASE characters.
This function should be defined with the following header.
CREATE FUNCTION CheckStringOfUpperAlphaOK(#String varchar(MAX)) RETURNS varchar(6) AS…
Should return "okay" if true and "not okay" if false
simply create function in this way
Function 1 for getting first day in quarter
CREATE FUNCTION FirstDayInQtr(#InputDate datetime)
RETURNS datetime
AS
BEGIN
DECLARE #day datetime
SELECT #day = DATEADD(qq, DATEDIFF(qq ,0, #InputDate),0)
Return #day
END
Function2 For checking capital character as
CREATE FUNCTION CheckStringOfUpperAlphaOK(#String varchar(MAX))
Returns VarChar(6)
AS
Begin
Declare #KeepValues as varchar(50)
Set #KeepValues = '%[^ ][A-Z]%'
While PatIndex(#KeepValues collate Latin1_General_Bin, #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex(#KeepValues collate Latin1_General_Bin, #Temp) + 1, 0, ' ')
Return #Temp
End
This will get you the First Day of the Current Quater. I think thats what you are after
CREATE FUNCTION FirstDayInQtr(#InputDate DATETIME)
RETURNS DATETIME
AS
BEGIN
DECLARE #firstDayOfCurrentQuater DATETIME
SELECT #firstDayOfCurrentQuater = DATEADD(qq, DATEDIFF(qq ,0, #InputDate),0)
RETURN #firstDayOfCurrentQuater;
END
I am trying to create dynamic code for date calculation in SQL stored procedures but am having problems executing string expressions and parameters as date expressions.
I want to hold generic string expressions in a table that will create the dates according to the value of the parameters.
for example this is a generic expression :
DATEADD(#TimeResolution, -#IterationN, #CurrentCalc)
as you can see these generic expressions are composed out of parameters to.
in the stored procedures I intend to declare the variables that are in the expression and assign values to them using a select statement from a different table.
the problem is that after deriving these string values and writing the expression it does not give me the date I want but fails.
so for example if I write the following code
declare #Today date
declare #LastYear date
set #Today = getdate()
set #LastYear = DATEADD(year, -1, #Today)
select #Lastyear
it works fine and I will get last year's date.
but when I try something like this :
declare #Today date
declare #LastYear date
declare #Timeresolution varchar(5)
select #Timeresolution = [Timeresolution] from dbo.mytable where rule_id=1//Timeresolution is a varchar column in my table holding the values 'year' or 'month'
declare Iteration int
select #Iteration = [Iteration] from dbo.mytable where rule_id=1 //Iteration is a int column in my table holding the values 1 or 2, or 3
set #Today = getdate()
set #LastYear = DATEADD(Timeresolution , -Iteration , #Today)
select #Lastyear
this gives me a conversion error.
Is there a way to create such dynamic date expressions?
It isn't possible to use a variable for the interval in DATEADD, but you can do something like this:
IF #Timeresolution = 'year'
BEGIN
SET #LastYear = DATEADD(year, -#Iteration , #Today)
END
IF #Timeresolution = 'month'
BEGIN
SET #LastYear = DATEADD(month, -#Iteration , #Today)
END
I need to convert VARCHAR values into DATETIME in multiple columns of a view for sorting and formatting (displaying in locale format) purposes in another application on SQL Server 2008.
There are currently two problems.
The input format of the VARCHAR values differ (but consistent at
column level)
Also there may be faulty values (e.g.: 20..05.2015)
Unfortunately the TRY_CONVERT function is available just for SQL Server 2012 and later.
ISDATE does not work because the view contains different date formats and I can neither set the language inside user defined functions nor in views, which would cause ISDATE to work with german date formats for example.
Is there any easier solution for my problem?
My first thought was to write a function like
FUNCTION TryConvertStringAsDatetime ( #value VARCHAR(MAX),
#format INT
)
that uses the format numbers of the CONVERT function, but checking for every possible format manually scares me a bit.
Example: TryConvertStringAsDatetime('20.05.2015', 104) (with some pseudocode)
SET #day = character 1 and 2
SET #month = character 4 and 5
SET #year = character 7, 8, 9 and 10
SET #dateODBCFormat = #year - #month - #day (concatenated with hyphen and not subtracted :)
IF ISDATE(#dateODBCFormat ) = 1
RETURN CONVERT(DATETIME, #dateODBCFormat, 120)
ELSE
RETURN CONVERT(DATETIME, 0) (does the job)
This is the function I now came up with:
CREATE
FUNCTION TryConvertStringAsDatetime ( #value VARCHAR(MAX),
#format INT
)
RETURNS DATETIME
AS
/*
Tries to convert a given VARCHAR value to DATETIME.
Returns NULL if no value was specified or the value is not in the correct format.
*/
BEGIN
DECLARE #length INT = LEN(#value)
IF #length IS NULL OR #length < 10 OR #length > 23
RETURN NULL
DECLARE #day VARCHAR(2),
#month VARCHAR(2),
#year VARCHAR(4),
#time VARCHAR(9)
IF #format = 104 --dd.mm.yyyy hh:mi:ss(24h)
BEGIN
SET #day = SUBSTRING(#value, 1, 2)
SET #month = SUBSTRING(#value, 4, 2)
SET #year = SUBSTRING(#value, 7, 4)
END
ELSE IF #format IN (120, 121) --yyyy-mm-dd hh:mi:ss(24h)
BEGIN
SET #year = SUBSTRING(#value, 1, 4)
SET #month = SUBSTRING(#value, 6, 2)
SET #day = SUBSTRING(#value, 9, 2)
END
ELSE
RETURN NULL -- currently only german and ODBC supported
IF #length > 11
SET #time = SUBSTRING(#value, 12, #length - 11)
SET #value = #year + '-' + #month + '-' + #day + ISNULL(' ' + #time, '')
IF ISDATE(#value) = 1
RETURN CONVERT(DATETIME, #value, 121)
RETURN NULL
END
I would probably go with something like this:
CREATE FUNCTION TryConvertToDate
(
#InputString varchar(20)
)
RETURNS Datetime
BEGIN
DECLARE #DateTime datetime = NULL
SET #DateTime =
CASE
WHEN LEN(#InputString) = 10 AND PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]', #InputString)=1 THEN
CONVERT(DateTime, #InputString, 104) -- German
WHEN LEN(#InputString) = 10 AND PATINDEX('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', #InputString)=1 THEN
CONVERT(DateTime, #InputString, 120) -- ODBC
ELSE
NULL -- unsuported format
END
RETURN #DateTime
END
Note: Testing for length and using patindex ensures only general format, so you need the call this function inside a try block in case the days and months are inverted and will cause a conversion error.
On the other hand, adding supported formats to this function is very easy - all you have to do is add a when clause with the correct patindex and length and the correct convert style.
Another option is to ensure the string can actually be converted to date.
This will make your function more complicated and thus harder to write, but will be easier to work with as it will reduce to minimum the chance of raising a conversion error:
CREATE FUNCTION TryConvertToDate
(
#InputString varchar(20)
)
RETURNS Datetime
BEGIN
DECLARE #DateValue date, #Days int, #Months int, #Years int
IF LEN(#DateString) = 10 AND PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9]', #InputString)=1 -- German format
BEGIN
SELECT #Days = CAST(LEFT(#InputString, 2) As int),
#Months = CAST(SUBSTRING(#InputString, 4, 2) as int),
#Years = CAST(RIGHT(#InputString, 4) as int)
-- NOTE: you will need to add a condition for leap years
IF (#Days < 31 AND #Months IN(4,6,9,12)) OR (#Days < 30 AND #Months = 2)
SET #DateValue = convert(date, #InputString, 104)
END
IF LEN(#InputString) = 10 AND PATINDEX('[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]', #InputString)=1 -- ODBC format
BEGIN
SELECT #Days = CAST(RIGHT(#InputString, 2) As int),
#Months = CAST(SUBSTRING(#InputString, 6, 2) as int),
#Years = CAST(LEFT(#InputString, 4) as int)
-- NOTE: you will need to add a condition for leap years
IF (#Days < 31 AND #Months IN(4,6,9,12)) OR (#Days < 30 AND #Months = 2)
SET #DateValue = convert(date, #InputString, 120)
END
RETURN #DateValue
END
You might have better luck in terms of both speed and functionality doing this in SQLCLR (as noted by #Tab and #Zohar in various comments).
.NET / C# code:
using System;
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TryConvertStuff
{
[SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlDateTime TryConvertDateTime([SqlFacet(MaxSize = 50)] SqlString
StringDate, [SqlFacet(MaxSize = 10)] SqlString Culture)
{
CultureInfo _Culture = CultureInfo.CurrentCulture;
if (!Culture.IsNull && Culture.Value.Trim() != String.Empty)
{
_Culture = CultureInfo.GetCultureInfo(Culture.Value);
}
DateTime _RealDate;
if (DateTime.TryParse(StringDate.Value, _Culture,
DateTimeStyles.None, out _RealDate))
{
return _RealDate;
};
return SqlDateTime.Null;
}
}
Tests:
SELECT dbo.TryConvertDateTime(N'2019-04-20', N'en'); -- 2019-04-20 00:00:00.000
SELECT dbo.TryConvertDateTime(N'2019-04-20f', N'en'); -- NULL
SELECT dbo.TryConvertDateTime(N'2019.04.20', N'en'); -- 2019-04-20 00:00:00.000
SELECT dbo.TryConvertDateTime(N'20.04.2019', N'en'); -- NULL
SELECT dbo.TryConvertDateTime(N'20.04.2019', N'de'); -- 2019-04-20 00:00:00.000
SELECT dbo.TryConvertDateTime(N'20.04.2019', NULL); -- NULL
I have a DateSurragate Key column and i need a end of week column for that DateSurragate Key ,,,
I created a user defined function
CREATE FUNCTION dbo.fn (#dt date)
RETURNS date
AS
BEGIN
DECLARE #result date
select #result = dateadd(week, datediff(week, 0, #dt), 4)
RETURN #result;
END;
GO
This function works with date but when values like -1 and -2 are passed it gives NULL
PLEASE let me know how i can change this function so that it can handle integer values I am new to tsql
If my understanding is not wrong(to determine whether input value is valid date or not?)
USE ISDATE(expression) function:
EX:
DECLARE #datestring varchar(8)
SET #datestring = '12/21/98'
SELECT ISDATE(#datestring)
Similarly check for your input parameter within Function in the beginning.
Raise error or change the flow in func if ISDATE() return 0 in your case.