user defined function call vs calling UDF in a Store procedure - sql

I have a user defined function that is called inside a stored procedure. All that stored procedure does is return the value that is obtained from the UDF scalar function.
However,
Select * UDF_FunctionName(param1,param2)
udf call is here-
SELECT dbo.udfFunction('1234',10) as result
and
Exec StoreProcName(param1,param2)
are returning different results.
StoreProcName calls the `UDF_FunctionName(param1,param2)
sproc code is here-
BEGIN
SET NOCOUNT ON;
Return SELECT [DbName].[dbo].[udfFunction](#param1, #param2)
END
What could be the reason for different results?.

You are trying to use RETURN and SELECT together:
Return SELECT [DbName].[dbo].[udfFunction](#param1, #param2)
You cannot do that, you either want to return the result, or select it. Depending on which you choose, retrieving the value will differ.
If you do this:
SELECT [DbName].[dbo].[udfFunction](#param1, #param2)
Then the resultset will have a single row and column containing your value. Access this exactly as you would any other resultset.
If you do this:
RETURN [DbName].[dbo].[udfFunction](#param1, #param2)
Your stored procedure will have a return value which is the result of your function call. Access this by defining a scalar variable and assigning it to the result of the SP call - assuming the result is INT that might look like
DECLARE #result INT
EXEC #Result = StoredProcName(#param1, #param2)

You should not use RETURN in this way in a stored procedure. If you want to return a scalar value to the calling code use an OUTPUT parameter. RETURN is generally used for status codes.
You might have something like
-- SAMPLE UDF
CREATE FUNCTION dbo.YourUDF (#Username VARCHAR(30), #EntityID INT)
RETURNS INT
AS
BEGIN
RETURN #EntityID;
END
GO
-- SAMPLE PROCEDURE
CREATE PROCEDURE dbo.YourProc #Username VARCHAR(30), #EntityID INT, #Output INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #Output = dbo.YourUDF(#Username, #EntityID);
IF #Output IS NULL -- AN ERROR
BEGIN
RETURN 1; -- RETURN A STATUS OF -1 TO INDICATE ERROR
END
END
Then you could call this as:
DECLARE #Output INT, #ReturnValue INT;
EXECUTE #ReturnValue = dbo.YourProc
#Username = '1234',
#EntityID = 1,
#Output = #Output OUTPUT;
SELECT ValueFromUDF = #Output,
ReturnValue = #ReturnValue;
This returns:
ValueFromUDF ReturnValue
------------------------------
1 0
If we pass NULL as #EntityID, to trigger the artificial error, then we get a return status of -1:
DECLARE #Output INT, #ReturnValue INT;
EXECUTE #ReturnValue = dbo.YourProc
#Username = '1234',
#EntityID = NULL,
#Output = #Output OUTPUT;
SELECT ValueFromUDF = #Output,
ReturnValue = #ReturnValue;
ValueFromUDF ReturnValue
------------------------------
NULL 1

Related

Stored procedure returns 0 instead of value

There is a stored procedure that can return top 1 result as
USE [DB]
GO
.....
CREATE PROCEDURE [dbo].[GET]
(#in VARCHAR(10), #Out VARCHAR(10) OUTPUT)
AS
SELECT top 1 #Out = tab.Col
FROM table tab
RETURN
GO
When I call it in main query
DECLARE #output VARCHAR(10)
DECLARE #in VARCHAR(10)
DECLARE #Out VARCHAR(10)
EXECUTE dbo.GET #in = 'table', #Out = #output
It prints #output as 0;
but if I do
EXECUTE dbo.GET #in = 'table', #Out = #Out
And print #out, I get the correct value.
Why could this happen?
I did pass output #Out to pre-defined variable #output
Assuming SQLS due to presence of 'dbo' and sqlserver tag
Your query in the procedure doesn't assign a value to the out parameter (called #out) it assigns to some other variable called #outpk. Resolve the naming mismatch and make them the same
Sqlserver does not support LIMIT. To limit result set size use SELECT TOP 1 *. Using TOP (or any similar result set restrictor) without ORDER BY is illogical. Specify an ORDER BY
In sqlserver, output parameters must be passed with the OUTPUT keyword when calling the procedure:
EXEC sprocname #inputparameter ='value', #outputparameter = #variableToSet OUTPUT;
Use semicolons; omitting them is deprecated
Example
USE [DB]
GO
CREATE PROCEDURE [dbo].[GET]
(#in VARCHAR(10), #OutPk VARCHAR(10) OUTPUT)
AS
SELECT #OutPK = tab.Col
FROM table tab
ORDER BY tab.Col;
GO
DECLARE #output VARCHAR(10);
EXECUTE dbo.GET #in = 'table', #OutPK = #output OUTPUT
SELECT #output;
If its MySql (Limit is in mySql), you can simply call:
Call dbo.GET('table', #out);
No need to have separate variable #output.

Calling scalar function through Exec

I have created a scalar function
CREATE FUNCTION dbo.Dumm()
returns INT
AS
BEGIN
DECLARE #a INT
SELECT #a = 1
RETURN #a
END
Now I am calling the scalar function through Exec not through select
EXEC dbo.Dumm
It did not return 1. It just says
Command(s) completed successfully.
Whats happening internally. Is there any meaning for it ?
Try this:
DECLARE #ret int;
EXEC #ret = dbo.Dumm
and then show the result querying your variable #ret as follow:
SELECT #ret
Tell me if it's OK

IF / ELSE depending on result of stored procedure

I've the following stored procedure:
ALTER PROCEDURE [dbo].[CheckAdminExists]
#SID NVARCHAR(50),
#AdminName NVARCHAR(MAX)
AS
SELECT
Administrator.ID
FROM
Administrator
WHERE
Administrator.SID = #SID
AND Administrator.Name = #AdminName
GO
Now I would like to create another SP with a code like that:
IF NOT NULL (EXECUTE CheckAdminExists 'S-1','Admin')
--do something
ELSE
--do something else
What's the right syntax for doing it?
You should not use a stored procedure for this and use a function instead to check if the Admin Exists.
Then in your new stored procedure call the CheckAdminExists function:
CREATE FUNCTION [dbo].[CheckAdminExists] (#SID NVARCHAR(50), #AdminName NVARCHAR(MAX))
RETURNS BIT
AS
BEGIN
DECLARE #RetVal INT
SELECT #RetVal = COUNT(Administrator.ID)
FROM
Administrator
WHERE
Administrator.SID = #SID
AND Administrator.Name = #AdminName
IF #RetVal > 0
BEGIN
RETURN 1
END
RETURN 0
END
Then in your stored procedure call the function:
DECLARE #AdminExists BIT
SELECT #AdminExists = [dbo].[CheckAdminExists]
IF #AdminExists
BEGIN
-- your code
END
ELSE
BEGIN
-- your code
END
Indeed, use FUNCTION.
But if you need to return more than 1, use OUTPUT parameters.

Stored procedure and function returning unexpected results

Using stored procedure output for a parameter of a function
DECLARE #SeqNo int;
DECLARE #CharNumber varchar(10);
EXEC dbo.sp_GetNextCounter 'ITEMTYPE', #SeqNo OUTPUT;
EXEC #CharNumber=dbo.rf_f_CIntToChar #SeqNo, 6;
SELECT #CharNumber;
The stored procedure sp_GetNextCounter has an integer output called SeqNo.
The stored procedure:
#param0 varchar(12),
#SeqNo INT OUTPUT
AS
BEGIN
IF (#param0 IS NOT NULL)
BEGIN
set nocount on
DECLARE #reqseqno INT
SELECT #reqseqno = CounterValue FROM Counters WHERE CounterName = #param0
UPDATE Counters SET CounterValue = #reqseqno + 1 WHERE CounterName = #param0
SELECT #reqseqno AS 'SeqNo'
END
END
GO
The function dbo.rf_f_CIntToChar takes two parameters (integer to convert, number of characters to return) returns a varchar version of the integer with leading zeros.
The function:
(#intVal int, #intLen int)
RETURNS varchar(10)
WITH EXEC AS CALLER
AS
BEGIN
IF #intlen > 20 SET #intlen = 20
IF #intlen < LEN(#intVal) RETURN RIGHT(CONVERT(varchar(10), #intVal), #intlen)
RETURN REPLICATE('0', #intLen - LEN(#intVal)) + CONVERT(varchar(10), #intVal)
END
GO
Both the stored procedure and the function operate as they should when used separately.
Why does the above query return SeqNo rather than CharNumber?
Your stored procedure never assigns a value to the output parameter #SeqNo

can we have a stored procedure with output parameters and return statement?

Can a stored procedure have output parameters and return statement? If so can anybody give me a simple example.thank you all.
Stored procedure can return integer type only in a return statement and can have any number of out parameters. See this for references supporting this.
Simplest eg of stored procedure
Return integer value from SP
CREATE procedure [sys].[sp_name]
(
#var1 bit = 0,
#publisher smallint
)
AS
BEGIN
IF #var1<> 0
RETURN (#publisher )
END
Using Out Parameter
CREATE PROCEDURE GetImmediateManager
#employeeID INT,
#managerID INT OUTPUT
AS
BEGIN
SELECT #managerID = ManagerID
FROM HumanResources.Employee
WHERE EmployeeID = #employeeID
END
You can use Transactions, Exception handling(try Catch), DDL and DML Queries, calling another stored procedure within one stored procedures and many more operations.
Please comments for more functionalities supported in stored procedure
If you mean the standard RETURN statement that gives an integer then yes
If you mean a UDF RETURN , then no. But a stored proc can have a normal SELECT
You are free to use both OUTPUT params and a single RETURN value:
CREATE PROCEDURE RaiseToPower (
#IN INT,
#OUT INT OUTPUT
)
AS
DECLARE #POWER INT
SET #POWER = 3
SET #OUT = POWER(#IN, #POWER)
RETURN #POWER
GO
/**/
DECLARE #POW INT, #RESULT INT
EXEC #POW = dbo.RaiseToPower 2, #RESULT OUTPUT
SELECT 2, 'raised to', #POW, 'is', #RESULT
>> 2 raised to 3 is 8
No. It is either a stored procedure or a scalar function.
A scalar function returns a value and takes 0 to n in parameters.
A stored procedure can take from 0 to n input parameters and can have 0 to n output parameters.