HOW to create SQLSERVER functions? - sql-server

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

Related

T-SQL : CREATE FUNCTION must be the only statement in batch [duplicate]

I'm getting this error from the function:
CREATE FUNCTION getLavel(#id int ,#lavel char)
RETURNS date
BEGIN
DECLARE #date date
select #date = (select authorization_date from Authorized WHERE diver_number = #id and #lavel =level_name)
return #date
END
GO
What can be the reason?
Ty very much.
The function needs to be either the only function in the query window OR the only statement in the batch. If there are more statements in the query window, you can make it the only one "in the batch" by surrounding it with GO's.
e.g.
GO
CREATE FUNCTION getLavel(#id int ,#lavel char)
RETURNS date
BEGIN
DECLARE #date date
select #date = (select authorization_date from Authorized WHERE diver_number = #id and #lavel =level_name)
return #date
END
GO
Turn this into an inline table valued function. This will perform better than the scalar function. Also, you should NOT use the default sizes for character datatypes. Do you know what the default length for a char is? Did you know that it can vary based on usage?
CREATE FUNCTION getLavel
(
#id int
, #lavel char --You need to define the length instead of the default length
)
RETURNS table
return
select authorization_date
from Authorized
WHERE diver_number = #id
and #lavel = level_name
GO
You need to add RETURN before the END statement
That should fix your issue, that's what fixed mine. :D
Make sure that this statement is the only the only sql in your query window before you execute it.
Or you can highlight the function declaration and execute
What solved it for me, was that I was trying to create the function inside of a transaction context - that doesn't make sense from a SQL Server point of view. Transactions are for data, not functions.
Take the CREATE FUNCTION statement out of the transaction, then wrap it in GO's
CREATE FUNCTION CalculateAge(#DOB DATE)
RETURNS INT
AS
BEGIN
DECLARE #Age INT
SET #DOB='08/12/1990'
SET #Age =DATEDIFF(YEAR,#DOB,GETDATE()) -
CASE
WHEN (MONTH (#DOB)> MONTH (GETDATE ())) OR
(MONTH (#DOB)= MONTH (GETDATE ()) AND DAY (#DOB) >DAY (GETDATE ()))
THEN 1
ELSE 0
END
SELECT #Age
END
The Error is given to you in only query Page But if you execute the query then it will successfully execute.
CREATE FUNCTION getLavel(#id int ,#lavel char)
RETURNS date
BEGIN
DECLARE #date date
select #date = (select authorization_date from Authorized WHERE diver_number = #id and #lavel = level_name)
return #date
END
GO

SQL server Function - Take column name as input parameter

I need to write a SQL function to return column specific values, so I am passing the column name as a parameter to SQL-function to return its corresponding value. Here is the sample function
CREATE FUNCTION GETDATETIME(#columnName VARCHAR(100))
RETURNS DATETIME
AS
BEGIN
RETURN (SELECT TOP 1.#columnName FROM TEST_TABLE )
END
GO
The above function seems to be straight forward, but it not working as expected.
And when I execute the function
SELECT dbo.GETDATETIME('DATETIMECOLUMNNAME')
I am getting this error:
Conversion failed when converting date and/or time from character string.
Can someone help me to identify the issue?
For that you need to write dynamic sql. But Functions won't support execute statement.
So you need to write multiple If conditions for each column.
CREATE FUNCTION GETDATETIME(#columnName VARCHAR(100))
RETURNS DATETIME
AS
BEGIN
DECLARE #RESULT DATETIME;
IF (#columnName = 'ABC')
Begin
SELECT TOP 1 #RESULT = [ABC] FROM TEST_TABLE
END
ELSE IF (#columnName = 'DEF')
Begin
SELECT TOP 1 #RESULT = [DEF] FROM TEST_TABLE
END
ELSE IF (#columnName = 'GHI')
Begin
SELECT TOP 1 #RESULT = [GHI] FROM TEST_TABLE
END
RETURN #RESULT
END
GO
Edit 2:
If your column always return Datetime, then you can do like below.
CREATE TABLE A_DUM (ID INT, STARTDATE DATETIME, ENDDATE DATETIME, MIDDLEDATE DATETIME)
INSERT INTO A_DUM
SELECT 1, '2019-07-24 11:35:58.910', '2019-07-28 11:35:58.910', '2019-07-26 11:35:58.910'
UNION ALL
SELECT 2, '2019-07-29 11:35:58.910', '2019-08-01 11:35:58.910', '2019-07-24 11:35:58.910'
And your function like below
CREATE FUNCTION GETDATETIME(#columnName VARCHAR(100))
RETURNS DATETIME
AS
BEGIN
DECLARE #RESULT DATETIME;
SELECT TOP 1 #RESULT = CAST(PROP AS DATETIME)
FROM A_DUM
UNPIVOT
(
PROP FOR VAL IN (STARTDATE, ENDDATE,MIDDLEDATE)
)UP
WHERE VAL = #columnName
RETURN #RESULT
END
GO
There's a workaround to this, similar to #Shakeer's answer - if you are attempting to GROUP BY or perform a WHERE on a column name, then you can just use a CASE statement to create a clause to match on specific column names (if you know them).
Obviously this doesn't work very well if you have many columns to hard-code, but at least it's a way to achieve the general idea.
E.g. with WHERE clause:
WHERE
(CASE
WHEN #columnname = 'FirstColumn' THEN FirstColumnCondition
WHEN #columnname = 'SecondColumn' THEN SecondColumnCondition
ELSE SomeOtherColumnCondition
END)
Or with GROUP BY:
GROUP BY
(CASE
WHEN #columnname = 'FirstColumn' THEN FirstColumnGroup
WHEN #columnname = 'SecondColumn' THEN SecondColumnGroup
ELSE SomeOtherColumnGroup
END)
No you cannot use dynamic sql in functions in SQL. Please check this link for more info link.
So it is not possible to achieve this by any function, yes you may use stored procedures with output parameter for same.
You may find this link for reference link.

VARCHAR comparison in the FUNCTION

I have the following function:
CREATE FUNCTION ISRELKDVG(#WUNSCH_LIEFERTERMIN VARCHAR) RETURNS int AS
BEGIN
DECLARE #sTerminNone VARCHAR(8)
DECLARE #sTerminFrom VARCHAR(8)
SET #sTerminNone = '00000000'
SET #sTerminFrom = CONVERT(VARCHAR(8), GETDATE() - 100, 112) -- 100 days in the past
IF (#WUNSCH_LIEFERTERMIN <> #sTerminNone AND #WUNSCH_LIEFERTERMIN >= #sTerminFrom)
RETURN 1
RETURN 0
END
The variable given as parameter to the function is a date and has a form "YYYYMMDD". The problem is that the function never returns 1.
I have found the link which says that comparing varchar's with unspecified length may lead to errors. Does it also refer to varchar's passed to the functions?
Do not rely on implicit conversions, using unknown dateformats. Convert to dates or datetimes, specifying a dateformat, and compare those values.
Specify the size of function parameter, e.g. varchar(8). Otherwise it is 1 character long by default:
declare #c as varchar
set #c = '20130101'
select #c -- returns 2
Try this out:
CREATE FUNCTION ISRELKDVG(#WUNSCH_LIEFERTERMIN VARCHAR(8)) RETURNS int AS
BEGIN
DECLARE #sTerminNone VARCHAR(8)
DECLARE #sTerminFrom DATE
SET #sTerminNone = '00000000'
IF (#WUNSCH_LIEFERTERMIN = #sTerminNone)
RETURN 0
SET #sTerminFrom = DATEADD(day,-100,GETDATE()) -- 100 days in the past
IF (CAST(#WUNSCH_LIEFERTERMIN AS DATE) >= #sTerminFrom)
RETURN 1
RETURN 0
END
select dbo.ISRELKDVG('00000000') --0
select dbo.ISRELKDVG('20030901') --0
select dbo.ISRELKDVG('20130901') --1
select dbo.ISRELKDVG('20130730') --1
Yes that is the main problem.
MSDN - Remarks
When n is not specified in a data definition or variable declaration
statement, the default length is 1. When n is not specified when using
the CAST and CONVERT functions, the default length is 30.
But (even in case of Cast/Convert), you should always define the length to avoid such troubles.
Change
#WUNSCH_LIEFERTERMIN VARCHAR --<--Length is 1 by default
To
#WUNSCH_LIEFERTERMIN VARCHAR(8) --Or length as appropriate
Secondly, you should be comparing Dates not Strings.
DECLARE #sTerminNone DATE = CONVERT(DATETIME, 0) --<--DATE (Assign correct date)
DECLARE #sTerminFrom DATE = GETDATE() - 100
Finally,
IF (CONVERT(DATE, #WUNSCH_LIEFERTERMIN, 112) <> #sTerminNone AND --Not sure if you need this
CONVERT(DATE, #WUNSCH_LIEFERTERMIN, 112) >= #sTerminFrom)
RETURN 1
ELSE
RETURN 0
Ideally, you should pass/define a DateType parameter to the function.

stored function returnin NULL instead than DATETIME

I created the following sfunction
CREATE FUNCTION sf_GetTrainingDate (#ID_ITEM int,#EMPLOYEE VARCHAR)
RETURNS DATETIME AS
BEGIN
--(1)
DECLARE #RESULT DATETIME
DECLARE #DATE DATETIME
DECLARE #REPEAT_INTERVAL INT
SET #DATE = (/*subquery returning a date in datetime format*/)
SET #REPEAT_INTERVAL = (/*subquery returning a datetime */)
WHILE #DATE <= getdate()
BEGIN
SET #DATE=dateadd(month,#REPEAT_INTERVAL,#DATE)
IF #DATE > GETDATE()
BREAK
ELSE
CONTINUE
END
SET #RESULT = #DATE
RETURN #RESULT
--(2)
END
The code works correctly, I mean if I run only the part from (1) to (2) using some PRINT commands to read the value of #DATE all is fine, but as i use the stored function it returns NULL instead of a date.
Could you give me an hand?

TSQL UDF To Split String Every 8 Characters

Someone decided to stuff a bunch of times together into a single column, so the column value might look like this:
08:00 AM01:00 PM
And another column contains the date in the following format;
20070906
I want to write a UDF to normalize this data in a single SQL query, so I can get back 2 rows of datetime type for the above example
2007-09-06 08:00:00.000
2007-09-06 13:00:00.000
The conversion to datetime type is simple...but I need to split the time part every 8 characters to get the individual time out.
Anyone know of an existing UDF to do this?
Try this, it'll split your string into chunks of the specified lenth:
create function SplitString
(
#str varchar(max),
#length int
)
returns #Results table( Result varchar(50) )
AS
begin
declare #s varchar(50)
while len(#str) > 0
begin
set #s = left(#str, #length)
set #str = right(#str, len(#str) - #length)
insert #Results values (#s)
end
return
end
For example:
select * from dbo.SplitString('08:00 AM01:00 PM', 8)
Will give this result:
Result
08:00 AM
01:00 PM
There is a bug in the query above, the below query fixes this.
Also, I have made the returned table contain a sequence column so that it is possible to determine what sequence the split is in:
CREATE function SplitString
(
#str varchar(max),
#length int
)
RETURNS #Results TABLE( Result varchar(50),Sequence INT )
AS
BEGIN
DECLARE #Sequence INT
SET #Sequence = 1
DECLARE #s varchar(50)
WHILE len(#str) > 0
BEGIN
SET #s = left(#str, #length)
INSERT #Results VALUES (#s,#Sequence)
IF(len(#str)<#length)
BREAK
SET #str = right(#str, len(#str) - #length)
SET #Sequence = #Sequence + 1
END
RETURN
END

Resources