SQL syntax for a function - sql

I have the following code, syntax somewhere is not correct,
CREATE FUNCTION [dbo].[Greeting](#Name [varchar])
RETURNS [int] AS
BEGIN
Declare #Gender varchar
Declare #Greeting varchar
select #Gender = Gender from [NameData].[dbo].[Names] where Name = #Name
select #Greeting = (case when #Gender = 'Female' then 'Ms.' else 'Mr.');
RETURN #Greeting
END
GO
The error I'm getting is:
Incorrect syntax near ')'.
Anyone can help?
Thanks

You are missing the end to your case statement. Probably more importantly, you are not using length specifications for varchar. In SQL Server always use length specifications. The default value depends on the context -- and in this context, the value is 1, which will produce incorrect results.
You should also end your statements with semicolons. And, fix the return value, because you do not seem to be returning an integer. So:
CREATE FUNCTION [dbo].[Greeting](
#Name varchar(255)
)
RETURNS varchar(255) AS
BEGIN
Declare #Gender varchar(255);
Declare #Greeting varchar(255);
select #Gender = Gender from [NameData].[dbo].[Names] where Name = #Name ;
select #Greeting = (case when #Gender = 'Female' then 'Ms.' else 'Mr.' end);
RETURN #Greeting;
END;
You do realize that all unrecognized names will be given a "greeting" of "Mr.". I assume that is intentional. Also, the function can be simplified, but I'm following your original logic as much as possible.

You have
RETURNS [int]
but are trying to return #Greeting which is declared a varchar
And also missing end for case statement.

You missed END in your case statement:
CREATE FUNCTION [dbo].[Greeting] (#Name [varchar(255)])
RETURNS [int] --also this will need to be changed to varchar()
AS
BEGIN
DECLARE #Gender VARCHAR(255) --added varchar length
DECLARE #Greeting VARCHAR(255) --added varchar length
SELECT #Gender = Gender
FROM [NameData].[dbo].[Names]
WHERE NAME = #Name
SELECT #Greeting = (
CASE
WHEN #Gender = 'Female'
THEN 'Ms.'
ELSE 'Mr.'
END --added this
);
RETURN #Greeting
END
GO

Related

What's better to optimize a database: use a bunch of stored procedures with different filters or use a single one with if conditions?

I'm trying to optimize my database so, I decided to change a stored procedure which has a lot of "IF CONDITIONS" to filter with different parameters.
So, I was thinking on change it and make a bunch of stored procedures with different filters and stop using the one with a lot of "IF CONDITIONS"
And just validate on my backend which stored procedure use, instead of do it in SQL Server.
This is the best way to do it or there are better ways to do this?
Example of my actual stored procedure:
CREATE PROCEDURE [dbo].[sp_GetFilters]
#Id INT,
#Name VARCHAR(50),
#LastName VARCHAR(50),
#Age INT,
#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF #ID IS NOT NULL AND
#NAME IS NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE
WHERE ID = #ID
END
ELSE IF #ID IS NULL AND
#NAME IS NOT NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE WHERE
NAME = #NAME
END
...
and so on..
I want to change that one to a bunch of different stored procedures, each one of them with a unique filter
It is a good idea? There are better ways to optimize this stored procedure?
Thanks, for the help!
You could try one query, with parameter evaluation in the WHERE clause. I've used this approach widely with great success.
CREATE PROCEDURE dbo.sp_GetFilters
#Id INT = NULL
,#Name VARCHAR(50) = NULL
,#LastName VARCHAR(50) = NULL
,#Age INT = NULL
,#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM EXAMPLE_TABLE
WHERE 1 = 1
AND CASE WHEN #Id IS NULL THEN 1 ELSE ID END = CASE WHEN #Id IS NULL THEN 1 ELSE #Id END
AND CASE WHEN #Name IS NULL THEN '1' ELSE NAME END = CASE WHEN #Name IS NULL THEN '1' ELSE #Name END
AND CASE WHEN #Age IS NULL THEN 1 ELSE AGE END = CASE WHEN #Age IS NULL THEN 1 ELSE #Age END;
/* and so on....*/
END;

SQL - Why can't I compare varchar to varchar(15)?

Can anyone explain to me why the following returns 'Not equal'?
DECLARE #X15 varchar(15) = 'ABC'
DECLARE #X varchar = #X15
SELECT CASE WHEN #X = #X15 THEN 'Equal' ELSE 'Not equal' END
I must be missing something obvious.
If you print out #X you'll see the problem:
DECLARE #X15 varchar(15) = 'ABC'
DECLARE #X varchar = #X15
SELECT LEN(#X), #X, CASE WHEN #X = #X15 THEN 'Equal' ELSE 'Not equal' END
If you don't specify a length for varchar it defaults to 1 character so your #X variable can only hold the first character of #X15.
The default value of n is 1 for the char and varchar data types when they are used in variable declaration.
Ex:-
DECLARE #myVariable AS varchar = 'abc';
DECLARE #myNextVariable AS char = 'abc';
DECLARE #myVariableWithLength AS varchar(15) = 'abc';
--The following returns 1
SELECT DATALENGTH(#myVariable), DATALENGTH(#myNextVariable),DATALENGTH(#myVariableWithLength);
GO

SQL Server function to get output zero or not

I am stuck to get output from function that takes an input parameter and should return zero or not:
alter function dbo.ZERONOT(#input int)
returns varchar(30)
as
begin
declare #result varchar(30)
declare #result1 varchar(30)
select #input = P_PRICE
from Product_ID
if (#input > 0)
set #result = 'YES'
return #result
else
set #result1 = 'NO'
return #result1
end
I think you want this:
ALTER FUNCTION dbo.ZERONOT(#Input INT) --The input value stored here
-- The variable used to pass the value to the function and make some
-- operations based on it, do not change his value.
RETURNS VARCHAR(3)
AS
BEGIN
DECLARE #Result VARCHAR(3);
IF EXISTS (SELECT 1 FROM Products WHERE Product_ID = #Input)
--Or maybe the price because I don't think you have a table named Product_ID
SET #Result = 'Yes'
ELSE
SET #Result = 'No';
RETURN #Result
END
Don't forget to visit the documentation

Passing Parameters to a stored Procedure

I am working on a project that accepts 3 different parameters, the date is required and the First and Last name are optional. We setup the query below, but even if I change the parameters on the report (SSRS) it still looks at #LetterCreated as being '1/1/1950', any ideas on how I can get this to just accept the parameters? We set the date this way because we want the report to show with all of the reports when it is initially opened.
Alter Proc
AS
BEGIN
SET NOCOUNT ON;
DECLARE #LetterCreated DATETIME,
#FirstName VARCHAR(20),
#LastName VARCHAR(20)
SELECT #LetterCreated = '1/1/1950'
SELECT #FirstName = ''
SELECT #LastName = ''
SELECT
LETTERCREATETIME,
Firstname,
LastName,
From RedFlagAddress
WHERE
CASE WHEN #LetterCreated='1/1/1950'
THEN '1/1/1950'
ELSE ISNULL(LETTERCREATETIME, '07/05/81')
END = #LetterCreated
AND (LastName LIKE #LASTNAME + '%' AND FirstName LIKE #FirstNAME + '%')
END
Any suggestions would be greatly appreciated.
You are setting the #lettercreated date in the procedure. Variables defined within the procedure are not visible outside it.
You should declare the parameters as parameters, and set the default in the declaration
ALTER PROC yourproc
(
#LetterCreated DATETIME = '1950-1-1',
#FirstName VARCHAR(20) = '',
#LastName VARCHAR(20) = ''
)
as
begin
select
LETTERCREATETIME,
Firstname,
LastName,
From
RedFlagAddress
where
(
ISNULL(LETTERCREATETIME, '07/05/81') = #LetterCreated
or
#LetterCreated = '1950-1-1'
)
AND LastName LIKE #LASTNAME + '%'
AND FirstName LIKE #FirstNAME + '%'
end
I'm guessing here but what you may want is
IF parameter #LetterCreated is null then it should not be used as a filter at all
IF the data in RedFlagData.LETTERCREATETIME is Null then it should be matched to a filter date of '07/05/81' FWR
Assuming that you have the 'allow nulls' check on the RDL/RDLC set for the #LetterCreated parameter, the where needs to be changed, the optional filter can be set like so:
ISNULL(#LetterCreated, LETTERCREATETIME) = ISNULL(LETTERCREATETIME, '07/05/81')
If you get rid of the magic date, then you can guarantee no date filter applied even if LETTERCREATETIME is null, by the filter:
ISNULL(#LetterCreated, LETTERCREATETIME) = ISNULL(LETTERCREATETIME)
OR
(#LetterCreated IS NULL AND LETTERCREATETIME IS NULL)
Thus:
ALTER PROC XYZ
(
#LetterCreated DATETIME,
#FirstName VARCHAR(20) = NULL,
#LastName VARCHAR(20) = NULL
)
as
begin
select
LETTERCREATETIME,
Firstname,
LastName,
From
RedFlagAddress
where
(
ISNULL(#LetterCreated, LETTERCREATETIME) = LETTERCREATETIME
OR
(#LetterCreated IS NULL AND LETTERCREATETIME IS NULL)
)
AND LastName LIKE ISNULL(#LastName, '') + '%'
AND FirstName LIKE ISNULL(#FirstName, '') + '%'
end
One caveat : The performance of this query will be terrible, given the amount of functional manipulation in the where clause, and the LIKEs and ORs - Hopefully RedFlagAddress is a relatively small table? If not, you may need to rethink your approach
Similar to podiluska's answer, you should set the parameters as part of the SP, as podiluska indicates, but then you should set the default values in SSRS, in the Parameters there.
This will let the users see the defaults and use those for subscriptions, or override them as needed.
Alter Proc Proc_Name
(
#LetterCreated DATETIME,
#FirstName VARCHAR(20) = null,
#LastName VARCHAR(20) = null
)
AS
BEGIN
SET NOCOUNT ON;
This will pass null values as Default values to you Proc now you code should be able to handle null values if no values are provided for FirstName and LastName

Passing parameters after calling stored procedure

I have the following UDF:
create function fn_name
(#first varchar(50),
#middle varchar(50),
#last Varchar(50))
returns varchar(100)
as
begin
return
case
when #middle is null then #first+' '+#Last
when Len(#middle)=0 then #first+' '+#Last
else #first+' '+#middle+' '+#Last
end
end
I am thinking of creating a stored procedure for the above function but in such a way that I am passing in the parameters one by one after calling the stored procedure. Is it possible in SQL Server? If yes, how?
You don't really want to call the stored procedure multiple times for each parameter. That is a nightmare, because you have to save state between the calls. Instead, use optional parameters:
create procedure usp_name (
#first varchar(50) = '',
#middle varchar(50) = '',
#last varchar(50) = '',
#name varchar(100) output
)
as
begin
select #name = (case when #middle is null then #first+' '+#Last
when Len(#middle)=0 then #first+' '+#Last
else #first+' '+#middle+' '+#Last
end);
end; -- usp_name
Now, all three parameters are optional. If you invoke it thus:
declare #name varchar(100);
exec #name = #name output;
Then it will return ''. If you call:
declare #name varchar(100);
exec #first = 'Gordon', #last = 'Linoff', #name = #name output;
Then you will get 'Gordon Linoff'.
Not all parameters need be optional as in this example. They become optional when you specify a default value.