SQL Server function to get output zero or not - sql

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

Related

Select and Set not working together in TSQL FUNCTION

I am using a function in SQL SERVER and setting a user variable using select and after that set . But seems set is not working .
--#id is input
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= +''+'DOMAIN\'+#id+''
IF #result IS NULL
SET #result = 'DOMAIN\'+#id+''
return (#result)
If user is not found I want to select id not the null values. Buts seems it coming null always
Set is not working in conditional statement.
What I am doing wrong?
Below is the update:
yes Slippery, I checked its coming null. If I set
SET #result ='MY ID'
it works but #result = 'DOMAIN\'+#id did not work
The whole function
FUNCTION [dbo].[USER_INFO]
(
-- Add the parameters for the function here
#id varchar(300)
)
RETURNS varchar(MAX)
AS
BEGIN
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= +''+'DOMAIN\'+#id+''
IF #result IS NULL
SET #result = 'DOMAIN\'+#id+''
return (#result)
END
Just in case that really is the entire function, you'll need that first line to be "CREATE FUNCTION" (or "ALTER FUNCTION" if it already exists), instead of just "FUNCTION"...
This will eliminate NULL's from being returned by your function:
DECLARE #result VARCHAR(MAX)
-- Eliminate NULL being passed in so string concatenation doesn't return NULL
IF #id IS NULL
SET #id = ''
-- Set the output value...if nothing exists, set it to 'x'
SET #result = (SELECT TOP 1 ISNULL(INFO,'x') FROM USER_INFO WHERE ID = 'DOMAIN\' + #id);
-- Now, neither #result OR #id will be NULL so the following should always return something other than NULL
IF #result = 'x'
SET #result = 'DOMAIN\' + #id
RETURN (#result)
Based on the other comments, try this:
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= 'DOMAIN\'+#id
IF #result IS NULL
SET #result = 'DOMAIN\'+ ISNULL(#id, '')
return (#result)
I don't think you need all that handing with the quotes and pluses
You should try like this. No need of those extra '' single quotes at end
Declare #result varchar(MAX)
SELECT #result = INFO FROM USER_INFO WHERE ID= 'DOMAIN\' + #id
IF #result IS NULL
SET #result = 'DOMAIN\' + #id
return (#result)
Few points to mention: your function name and the table name both are same user_info. Try naming them differently like
FUNCTION [dbo].[Get_USER_INFO]
(
-- Add the parameters for the function here
#id varchar(300)
)
SELECT #result = INFO FROM USER_INFO
Also, you should call your function like
select dbo.Get_USER_INFO('my-user_id')
The difference between select and set is that if set didn't found any value then it will return null but if select didn't found any value then it will show the previous value of the variable, the same case is happening for you when the #result value is null select don't assign any value and return the same previous value instead of assigning null and that is the reason the if statement is false and its not moving to the Set statement.
koppinjo, if the #result variable never set to anything then it should hit the block, but i guess the first time the #result variable value is not null so it's not hitting the block.
please view this for post more clarification.
http://www.mssqltips.com/sqlservertip/1888/when-to-use-set-vs-select-when-assigning-values-to-variables-in-sql-server/

Incompatible object type when create and alter a table value function in SQL

I'm getting the below error for the given function.
Msg 2010, Level 16, State 1, Procedure GetTableFromDelimitedValues, Line 2
Cannot perform alter on 'dbo.GetTableFromDelimitedValues' because it is an incompatible object type.
IF NOT EXISTS(SELECT 1 FROM sys.objects
WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
EXECUTE('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues](#input varchar(max),
#delimiter char(1) = ",")) RETURNS #Result TABLE (
Value nvarchar(4000)) AS BEGIN RETURN END')
END
GO
ALTER FUNCTION [dbo].[GetTableFromDelimitedValues](
#input varchar(max),
#delimiter char(1) = ',')
RETURNS #Result TABLE
(
Value nvarchar(4000)
)
AS
BEGIN
DECLARE #position int;
DECLARE #column nvarchar(4000);
WHILE LEN(#input) > 0
BEGIN
SET #position = CHARINDEX(#delimiter, #input);
IF (#position < 0) OR (#position IS NULL)
BEGIN
SET #position = 0;
END
IF #position > 0
BEGIN
SET #column = SUBSTRING(#input, 1, #position - 1);
SET #input = SUBSTRING(#input, #position + 1, LEN(#input) - #position)
END
ELSE
BEGIN
SET #column = #input;
SET #input = '';
END
INSERT #Result (Value)
SELECT #column;
END;
RETURN;
END
GO
Can someone please help me to get the compatible type by fixing the function?
You need to DROP and CREATE the function in this particular context
Since there is change in function return type, we must drop then recreate the function.
There are three types of functions,
Scalar
Inline table valued and
Multi Statement
ALTER cannot be used to change the function type.
IF EXISTS (SELECT [name] FROM sys.objects
WHERE object_id = OBJECT_ID('GetTableFromDelimitedValues'))
BEGIN
DROP FUNCTION [GetTableFromDelimitedValues];
END
GO
/* Now create function */
CREATE FUNCTION [dbo].[GetTableFromDelimitedValues](
#input varchar(max),
#delimiter char(1) = ',')
RETURNS #Result TABLE (
Value nvarchar(4000)
)
AS
BEGIN
..
..
..
RETURN;
END
in OBJECT_ID function you need to pass only function name not the schema. and why would create it 1st and then Alter it . Just check for existence 1st if it exists then drop function and create your function as I have shown above.
Also do not add Type in where clause when checking for existence, if there is another object not a function but any other object with the same name, it will not pick it up in your select statement and you will end up creating a function with a name an object already exists (this will throw an error).
IF you want to do it your way this is how you would go about it
IF NOT EXISTS(SELECT 1 FROM sys.objects
WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
EXECUTE('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues]() RETURNS #Result TABLE (
Value nvarchar(4000)) AS BEGIN RETURN END')
END
GO
In my case, this happened when I have a table name exactly as proc name. so making a change to proc name or a table referred in the proc should also fix this error message.
I have something to notify on your error related to your code:
The error says Cannot perform alter on 'dbo.GetTableFromDelimitedValues' because it is an incompatible object type
Which means that you have to look on your lines after the ALTER....
And yes there t is:
#input varchar(max)
The SQL server 2008 r2 not accept objects varchar(MAX), but that is only if you run a stored procedure
Because if you create a table by hand then it is fully accept it.
If you want a large cell then type varchar(1024) or varchar(2048) both of them are accepted. I face this issue few days ago...
That is my humble opinion
ADDITIONAL CHANGES
Use this
IF NOT EXISTS(SELECT 1 FROM sys.objects
WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
execute('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues]( #input varchar(max), #delimiter char(1)= ",") RETURNS #Result TABLE ( Value nvarchar(4000)) AS BEGIN RETURN END')
END GO
.... Pay attention to the change from ' to the "
** ADDITIONAL CHANGES **
I use the following which also works fine... with no any issue...
IF EXISTS (SELECT [name] FROM sys.objects
WHERE object_id = OBJECT_ID('GetTableFromDelimitedValues'))
BEGIN
DROP FUNCTION [GetTableFromDelimitedValues];
END
BEGIN
execute('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues]()
RETURNS
#Result TABLE (
Value nvarchar(4000))
AS
BEGIN
RETURN
END')
execute('ALTER FUNCTION [dbo].[GetTableFromDelimitedValues](
#input varchar(max),
#delimiter char(1) = ",")
RETURNS #Result TABLE (
Value nvarchar(4000))
AS
BEGIN
RETURN
END')
END
GO
I confirm the below code works. Seems the issue was somehow a scalar value function created with the same name during my development and got error as script's multi part table value alter statement function is compatible with it.
IF NOT EXISTS(SELECT 1 FROM sys.objects
WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
EXEC sp_executesql
#statement = N'CREATE FUNCTION dbo.[GetTableFromDelimitedValues] () RETURNS #Result
TABLE(Value nvarchar(4000))
AS
BEGIN
RETURN
END' ;
END
GO
ALTER FUNCTION [dbo].[GetTableFromDelimitedValues](
#input varchar(max),
#delimiter char(1) = ',')
RETURNS #Result TABLE
(
Value nvarchar(4000)
)
AS
BEGIN
DECLARE #position int;
DECLARE #column nvarchar(4000);
WHILE LEN(#input) > 0
BEGIN
SET #position = CHARINDEX(#delimiter, #input);
IF (#position < 0) OR (#position IS NULL)
BEGIN
SET #position = 0;
END
IF #position > 0
BEGIN
SET #column = SUBSTRING(#input, 1, #position - 1);
SET #input = SUBSTRING(#input, #position + 1, LEN(#input) - #position)
END
ELSE
BEGIN
SET #column = #input;
SET #input = '';
END
INSERT #Result (Value)
SELECT #column;
END;
RETURN;
END
GO
bug does function created and data return is not field define, just change after the table(add field) returns.
solution fix bug:
deleted function just
edit key word "Alter" => "Create"
F5 is created function is success

How to return the output of stored procedure into a variable in sql server

I want to execute a stored procedure in SQL Server and assign the output to a variable (it returns a single value) ?
That depends on the nature of the information you want to return.
If it is a single integer value, you can use the return statement
create proc myproc
as
begin
return 1
end
go
declare #i int
exec #i = myproc
If you have a non integer value, or a number of scalar values, you can use output parameters
create proc myproc
#a int output,
#b varchar(50) output
as
begin
select #a = 1, #b='hello'
end
go
declare #i int, #j varchar(50)
exec myproc #i output, #j output
If you want to return a dataset, you can use insert exec
create proc myproc
as
begin
select name from sysobjects
end
go
declare #t table (name varchar(100))
insert #t (name)
exec myproc
You can even return a cursor but that's just horrid so I shan't give an example :)
You can use the return statement inside a stored procedure to return an integer status code (and only of integer type). By convention a return value of zero is used for success.
If no return is explicitly set, then the stored procedure returns zero.
CREATE PROCEDURE GetImmediateManager
#employeeID INT,
#managerID INT OUTPUT
AS
BEGIN
SELECT #managerID = ManagerID
FROM HumanResources.Employee
WHERE EmployeeID = #employeeID
if ##rowcount = 0 -- manager not found?
return 1;
END
And you call it this way:
DECLARE #return_status int;
DECLARE #managerID int;
EXEC #return_status = GetImmediateManager 2, #managerID output;
if #return_status = 1
print N'Immediate manager not found!';
else
print N'ManagerID is ' + #managerID;
go
You should use the return value for status codes only. To return data, you should use output parameters.
If you want to return a dataset, then use an output parameter of type cursor.
more on RETURN statement
Use this code, Working properly
CREATE PROCEDURE [dbo].[sp_delete_item]
#ItemId int = 0
#status bit OUT
AS
Begin
DECLARE #cnt int;
DECLARE #status int =0;
SET NOCOUNT OFF
SELECT #cnt =COUNT(Id) from ItemTransaction where ItemId = #ItemId
if(#cnt = 1)
Begin
return #status;
End
else
Begin
SET #status =1;
return #status;
End
END
Execute SP
DECLARE #statuss bit;
EXECUTE [dbo].[sp_delete_item] 6, #statuss output;
PRINT #statuss;
With the Return statement from the proc, I needed to assign the temp variable and pass it to another stored procedure. The value was getting assigned fine but when passing it as a parameter, it lost the value. I had to create a temp table and set the variable from the table (SQL 2008)
From this:
declare #anID int
exec #anID = dbo.StoredProc_Fetch #ID, #anotherID, #finalID
exec dbo.ADifferentStoredProc #anID (no value here)
To this:
declare #t table(id int)
declare #anID int
insert into #t exec dbo.StoredProc_Fetch #ID, #anotherID, #finalID
set #anID= (select Top 1 * from #t)

Replacing frequently used complicated test in SQL Server Query with Function

I have a test I have to use regularly in queries to see if a CPT billing code is a billable encounter. In the SQL query, the test looks like this:
where (pvp.code between '99201' and '99215'
or pvp.code between '99221' and '99239')
plus a whole bunch more ranges.
I tried to create a function by just plugging this in to the function, but I got an "incorrect syntax" error -- not a huge surprise, really.
CREATE FUNCTION IsEncounter
(
#code varchar(20)
)
RETURNS bit
AS
BEGIN
DECLARE #Result bit;
SELECT #Result = #code between '99201' and '99215'
or #code between '99221' and '99239';
-- Return the result of the function
RETURN #Result;
END
I suppose I can do something like
if (#code >= '99201' and #code <= '99215')
or (#code >= '99221' and #code <= '99239')
select #Result = 1
else
select #Result = 0;
but I'd like to know the cleanest way to do this. Thanks.
Something like this should work:
CREATE FUNCTION IsEncounter
(
#code varchar(20)
)
RETURNS bit
AS
BEGIN
DECLARE #Result bit
SET #Result = CASE WHEN (#code between '99201' and '99215') or (#code between '99221' and '99239') THEN 1 ELSE 0 END
RETURN #Result
END
I think you are almost right with your UDF. I think there is just a few syntax issues. Try the following:
CREATE FUNCTION IsEncounter
(
#code varchar(20)
)
RETURNS bit
AS
BEGIN
DECLARE #Result bit = 0
IF #code between '99201' and '99215' or #code between '99221' and '99239'
BEGIN
SET #Result = 1
END
RETURN #Result
END
Then your WHERE clause would simply be:
where dbo.IsEncounter(p.Code)=1
I'd move my ranges into a table and then do this:
CREATE FUNCTION IsEncounter ( #code VARCHAR(20) )
RETURNS BIT
AS
BEGIN
DECLARE #MatchedRanges SMALLINT ;
DECLARE #Result BIT ;
SELECT #MatchedRanges = COUNT(*)
FROM tblRangeWhiteList
WHERE #code BETWEEN RangeStart AND RangeEnd
IF #MatchedRanges > 0
SET #Result = 1
ELSE
SET #Result = 0
RETURN #Result
END

SQL 2005 - Variant Parameter Question

I am working on a function that will be used by no less than 10 SProc's, and will probably grow once it is ironed out.
Problem i am running into is that i do not want to develop a function for each Data Type, which is why the SQL_VARIANT data type is looking pretty convenient for the action. I know is can do the ISNULL check on the data type but i also want to check to see if the Value being passed is a valid Number but the ISNUMERIC function does not work with SQL_VARIANT and I'm not too sure about the SQL_VARIANT_PROPERTY function.
Code so far:
CREATE FUNCTION dbo.mpt_Format_Number
(
#value SQL_VARIANT
, #money BIT
)
RETURNS VARCHAR
AS
BEGIN
--Check for NULL value
IF ISNULL(#value) BEGIN
-- Value IS NULL, return NULL
RETURN NULL
END ELSE BEGIN
-- Value is NOT NULL
DECLARE #TMP VARCHAR
END
END
CREATE FUNCTION dbo.mpt_Format_Number
(
#value SQL_VARIANT
, #money BIT
)
RETURNS VARCHAR
AS
BEGIN
--Check for NULL value
IF #value is null
-- Value IS NULL, return NULL
RETURN NULL
ELSE
BEGIN
-- Value is NOT NULL
if isnumeric(convert(varchar(max), #value)) = 1 RETURN 'Y' -- is valid number
--DECLARE #TMP VARCHAR
END
return 'N' --is not valid number
END
You can always test the property type with this syntax. Should be easy to incooperate in your function.
declare #t SQL_VARIANT
set #t = '3'
select SQL_VARIANT_PROPERTY(#t, 'basetype')
Result:
varchar
As a final implementation here is the full function as it was used.
ALTER FUNCTION [dbo].[_mpt_Format_Number]
(
#value SQL_VARIANT
, #money BIT = 0
)
RETURNS VARCHAR(max)
AS
BEGIN
DECLARE #ret VARCHAR(MAX)
--Check for NULL value
IF #value IS NULL BEGIN
-- Value IS NULL, return NULL
SET #ret = 'NULL'
END ELSE BEGIN
-- Value is NOT NULL
--Check for Numeric Value
IF ISNUMERIC(CONVERT(VARCHAR, #value)) = 0 BEGIN
--Value is NOT a Number, return NULL
SET #ret = 'NULL'
END ELSE BEGIN
--Value IS a Number
declare #isNeg BIT
declare #tmp varchar(max)
set #tmp = convert(varchar(max), round(cast(#value as money), 0), 1)
--Check if value is negative
if #value < 0 begin
--Value is Negative
set #isNeg = 1
--Remove the negative sign
set #tmp = replace(#tmp, '-', '')
end
--Remove the decimal plus any digits to the right of the decimal
set #tmp = left(#tmp ,len(#tmp) - 3)
--Is money set to True
if #money = 1 begin
--Pre-pend the dollar sign to value
set #tmp = '$' + #tmp
end
--Is isNeg set to True
if #isNeg = 1 begin
--Encapsulate the value with parenthesis
set #tmp = '(' + #tmp + ')'
end
SET #ret = #tmp
END
END
RETURN #ret
END