stored procedure returns varchar - sql-server

I would like to know if in SQL is it possible to return a varchar value from a stored procedure, most of the examples I have seen the return value is an int.
Example within a procedure:
declare #ErrorMessage varchar(255)
if #TestFlag = 0
set #ErrorMessage = 'Test'
return #ErrorMessage

You can use out parameter or the resulset to return any data type.
Return values should always be integer
CREATE PROCEDURE GetImmediateManager
#employeeID INT,
#managerName VARCHAR OUTPUT
AS
BEGIN
SELECT #managerName = ManagerName
FROM HumanResources.Employee
WHERE EmployeeID = #employeeID
END
Taken from here

You will need to create a stored function for that:
create function dbo.GetLookupValue(#value INT)
returns varchar(100)
as begin
declare #result varchar(100)
select
#result = somefield
from
yourtable
where
ID = #value;
return #result
end
You can then use this stored function like this:
select dbo.GetLookupValue(4)
Marc

A stored procedure's return code is always integer, but you can have OUTPUT parameters that are any desired type -- see http://msdn.microsoft.com/en-us/library/aa174792.aspx .

Related

SQL Server - Hasbytes in function gives different result then in select

I created a function like this:
CREATE FUNCTION dbo.HashCheeseName (#CheeseName NVARCHAR(40))
RETURNS VARCHAR(40)
AS BEGIN
DECLARE #Salt VARCHAR(25)
DECLARE #CheeseName NVARCHAR(40)
DECLARE #output VARCHAR(40)
SET #Salt = '123abc11aa'
SET #output = HASHBYTES('SHA2_256', CAST(#CheeseName as VARCHAR(40)) + #Salt)
RETURN #output
END
;
When I just run
SELECT HASHBYTES('SHA2_256', CAST('SwissCheese' as VARCHAR(40)) + #Salt)
I get an expected result like 0xF456D41144584064AC5456B7E3...
However, when I run the function in a query
SELECT dbo.HashCheeseName('SwissCheese')
I get a result like this: h:Mó!yýŠù’p» ªu_aøP¾æhw
Any ideas on why it would result in something like this? At first sight it looks like a conversion issue, but I don't see the problem
What you are doing there isn't the same. HASHBYTES returns a varbinary (Hashbytes (Transact-SQL) - Return Values) where as your function is returning a varchar. Those are different datatypes. As a result, the last line of your function is effectively:
SET #output = CONVERT(varchar(40),HASHBYTES('SHA2_256', CAST(#CheeseName as VARCHAR(40)) + #Salt));
The varchar representation of a varbinary will not be the same. Either return a varbinary in your function, or your test SELECT with a CONVERT to a varchar(40).
Edit: To confirm, the solution is to simply change the return type of your function and variable:
CREATE FUNCTION dbo.HashCheeseName (#CheeseName NVARCHAR(40))
RETURNS varbinary(8000)
AS BEGIN
DECLARE #Salt VARCHAR(25);
DECLARE #CheeseName NVARCHAR(40);
DECLARE #output varbinary(8000) ;
SET #Salt = '123abc11aa';
SET #output = HASHBYTES('SHA2_256', CAST(#CheeseName as VARCHAR(40)) + #Salt);
RETURN #output;
END

Use a stored procedure to get a list of nvarchar(20) values as a parameter

I'm developing a SQL Server 2012 stored procedure.
I need to return a list of nvarchar(20) values, and I don't know how can I do it. I have tried this:
Using a Table-Valued Parameters but it must be READONLY.
Doing a select to return that list. But stored procedures only
returns INT values.
Any idea?
UPDATE:
This is what I have done:
CREATE PROCEDURE [dbo].[GetAggregationChildren]
#parentCode nvarchar(20),
#codeLevel tinyint output,
#returnValue int output
AS
declare #childsLevelCount tinyint
, #invalidChildCodesCount int;
set nocount on;
-- ======== VALIDATION ==========
if NULLIF(#parentCode, '') IS NULL
begin
set #returnValue = -19;
return NULL; -- Parameter null or empty.
end
-- Check if parent exists in AGGREGATIONS table.
if not exists (Select top 1 CODE from AGGREGATIONS where CODE = #parentCode)
begin
set #returnValue = -11;
return NULL;
end
set #childsLevelCount = (select count(c.CODE_LEVEL) from CODES c where c.CODE in (Select CODE from AGGREGATION_CHILDS where PARENT_CODE = #parentCode) group by c.CODE_LEVEL);
-- If this aggregation has children codes with different values, it is an error.
if (#childsLevelCount > 1)
begin
set #returnValue = -201;
return NULL;
end
-- =========== CODE =============
set #returnValue = 0;
set #codeLevel = (select c.CODE_LEVEL from CODES c where c.CODE in (Select CODE from AGGREGATION_CHILDS where PARENT_CODE = #parentCode) group by c.CODE_LEVEL);
select CODE from AGGREGATION_CHILDS where PARENT_CODE = #parentCode;
But, I have no idea about how to return the result of this select:
select CODE from AGGREGATION_CHILDS where PARENT_CODE = #parentCode;
This stored procedure returns this on SQL Server Management Studio:
It is also returning a 0. I thought that the stored procedure is going to return the select result only.
I need the result in a parameter because I going to use in a SQLCommand like this one:
SqlParameter childsParam = new SqlParameter();
childsParam.ParameterName = "#childs";
childsParam.SqlDbType = System.Data.SqlDbType.Structured;
childsParam.Direction = System.Data.ParameterDirection.Input;
childsParam.Value = tvp;
parameters = new List<SqlParameter>();
parameters.Add(childsParam);
SqlConnection connection =
_context.Database.Connection as SqlConnection;
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = storedProcedureName;
cmd.CommandType = CommandType.StoredProcedure;
if (parameters != null)
cmd.Parameters.AddRange(parameters.ToArray());
cmd.Connection = connection;
cmd.ExecuteNonQuery();
connection.Close();
Stored procedure returns only Integer?
No this is not 100% true. If you are using RETURN to return the values from your stored procedure then your statement is true else it is false.
If you want to return string from your stored procedure then you can use SELECT like this:
CREATE PROCEDURE myProc
AS
BEGIN
SELECT 'test'
END
And to return multiple values you can use it like
CREATE PROCEDURE myProc
#Value1 varchar(20) OUTPUT,
#Value2 varchar(20) OUTPUT
AS
SELECT #Value1 = 'test1', #Value2 = 'test2'
and call it like
DECLARE #Value1 varchar(20), #Value2 varchar(20)
exec myProc #Value1 OUTPUT, #Value2 OUTPUT
SELECT #Value1, #Value1
Stored procedures return the type of the field in the SELECT statement. You can use CAST and CONVERT to change the types. For example:
SELECT CAST(field AS NVARCHAR(20))
With table value parameters you can set the field type on creation:
CREATE TYPE JobSpecifications AS TABLE
(JobName VARCHAR(50), AvailableDate Date );
you can use a temporary table to recuperate your list from the stored procedure, like the example below :
create proc Test
AS BEGIN
SELECT CAST('jkj' AS NVARCHAR(20)) value
END
DECLARE #tmp TABLE(value nvarchar(20))
INSERT INTO #tmp EXEC GhaziTest
SELECT * from #tmp

Run A Loop in SQL Server

I want to run a stored procedure on each ID return by a SELECT query. Is there a simple way to do something like:
FOREACH (SELECT ID FROM myTABLE WHERE myName='bob') AS id
BEGIN
EXEC #return_value = [dbo].[spMYPROC]
#PARAM1 = id
#PARAM2 = 0
END
Since I just happened to answer a very similar question yesterday, I have this code handy. As others have stated, it may not be the best approach, but still it's nice to learn how to use a while loop anyway.
Assuming a table named "Customer"
declare #Id int
select #Id = MIN(Id)
from Customer c
while(select COUNT(1)
from Customer c
where c.Id >= #Id) > 0
begin
--run your sproc right here
select #Id = MIN(Id)
from Customer c
where c.Id > #Id
end
DECLARE #ID INT, #return_value INT
DECLARE c CURSOR FOR
SELECT
ID
FROM myTABLE
WHERE myName = 'bob'
OPEN c; FETCH NEXT FROM c INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC #return_value = [dbo].[spMYPROC]
#PARAM1 = #ID,
#PARAM2 = 0
FETCH NEXT FROM c INTO #ID
END
CLOSE c; DEALLOCATE c;
You have two option here
Option 1 Using Split Function
Pass a comma deliminated list of IDs and use a Split function Inside your Procedure to make split these values and do whatever you want to do with it.
To
Make it work you will need two thing
1) Create a Function which
accepts a Comma Deliminated string and split them.
2) Modify you
Store Procedure and add this function in there in a way that passed
parameter is passed to the function inside that store procedure and
that function split the values before passing it onto your store
Procedure .
Create this function 1st
Function Definition
CREATE FUNCTION [dbo].[FnSplit]
(
#List nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table (Id int identity(1,1), Value nvarchar(100))
AS
BEGIN
WHILE(Charindex(#SplitOn,#List)>0)
BEGIN
INSERT INTO #RtnValue (value)
SELECT VALUE = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
SET #List = SUBSTRING(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
END
INSERT INTO #RtnValue (Value)
SELECT VALUE = ltrim(rtrim(#List))
RETURN
END
Modify you strored Procedure something like this
Stored Procedure
ALTER Procedure [dbo].[spMYPROC] (#Param1 VARCHAR(1000)= NULL)
AS
BEGIN
SELECT * FROM TableName
where ColumnNAME IN (SELECT Value FROM dbo.FnSplit(#Param1,','))
END
GO
Option 2 Table Type Parameter
Create a Table Type and alter your proc to accept a Table Type Parameter and do whatever you want to do with them values inside your proc.
TABLE TYPE
CREATE TYPE dbo.TYPENAME AS TABLE
(
Value int
)
GO
Stored Procedure to Accept That Type Param
ALTER PROCEDURE [dbo].[spMYPROC]
#TableParam TYPENAME READONLY
AS
BEGIN
SET NOCOUNT ON;
--Temp table to store passed Id values
declare #tmp_values table (value INT );
--Insert passed values to a table variable inside the proc
INSERT INTO #tmp_values (value)
SELECT Value FROM #TableParam
/* Do your stuff here whatever you want to do with Ids */
END
EXECUTE PROC
Declare a variable of that type and populate it with your values.
DECLARE #Table TYPENAME --<-- Variable of this TYPE
INSERT INTO #Table --<-- Populating the variable
SELECT ID FROM myTABLE WHERE myName='bob'
EXECUTE [dbo].[spMYPROC] #Table --<-- Stored Procedure Executed

Why does the output of this simple proc change datatypes?

In testing output values from procs, why does the final select #TestValOut return 0 instead of null or an empty string?
I understand the correct way to do this is by using OUTPUT parameters, so the question really becomes: Why is the datatype of the set value of #TestValOut, at execution, an integer?
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'Custom.test') AND type in (N'P', N'PC'))
DROP PROCEDURE Custom.test
GO
CREATE PROCEDURE Custom.test (
#CurrentUserID INT = 1
)
As
Declare #TestValIn varchar(max)
select #TestValIn='asdf'
GO
BEGIN TRAN
Declare #TestValOut varchar(max)
set #TestValOut='ffff'
Exec #TestValOut=Custom.test #CurrentUserID=1
select #TestValOut
ROLLBACK
A return value in a stored procedure is always an integer, as a matter of fact you can only use an integer with a return value. The fact that you see 0 means the proc executed correctly, this is the return value that SQL Server returns telling you what the result of the proc execution is
For fun do a select 1/0 in the proc and you will see it won't be 0 anymore
See here
Is a return value of 0 always a success in stored procedures?
here are the examples from that answer
CREATE PROC pr_test AS
SELECT 1/0
RETURN 0
GO
Now run it
DECLARE #i INT
exec #i = pr_test
SELECT #i -- will be 0
DROP PROC pr_test
Now let's do it again without the return statement
CREATE PROC pr_test2 AS
SELECT 1/0
GO
DECLARE #i INT
exec #i = pr_test2
SELECT #i -- will be - 6
Better to use an output parameter to pass back statuses and or messages
I think what you're trying to do is use an output parameter, which should be done like this.
CREATE PROCEDURE Custom.test (
#CurrentUserID INT = 1,
#TestValOut varchar(max) OUTPUT
)
As
select #TestValOut='asdf'
GO
BEGIN TRAN
Declare #TestValOut varchar(max)
Exec Custom.test #CurrentUserID=1, #TestValOut OUTPUT
select #TestValOut
ROLLBACK
#TestValOut is assigned the value that would be returned by an "RETURN" like this:
CREATE PROCEDURE Custom.test (
#CurrentUserID INT = 1
)
As
Declare #TestValIn varchar(max)
select #TestValIn='asdf'
RETURN --defaults to zero, this is the value
GO
or
CREATE PROCEDURE Custom.test (
#CurrentUserID INT = 1
)
As
Declare #TestValIn varchar(max)
select #TestValIn='asdf'
RETURN 0 --this is the value
GO
Your stored procedure doesn't actually do anything at all: there is no resultset. To see the difference...
CREATE PROCEDURE Custom.test (
#CurrentUserID INT = 1
)
As
select * from sys.objects
RETURN 42 --random value
GO
DECLARE #rtn int
EXEC #rtn = Custom.test
--you have the output of sys.objects now
--and the scalar RETURN value
SELECT #rtn
You need to explicity say what value to return. Default is 0
CREATE PROCEDURE Custom.test (
#CurrentUserID INT = 1
)
As
Declare #TestValIn varchar(max)
select #TestValIn='asdf'
RETURN 0
GO

can we return a null from stored procedure

Can we return null value from stored procedure. i dont want to use collase or isnull. I want to capture NULL at the frontend. Is it possible ?
Edit:
I am using Sql Server 2005
eg. where i want to use
CREATE PROCEDURE [Authentication].[spOnlineTest_CheckLogin]
#UserName NVARCHAR(50)
AS
BEGIN TRY
BEGIN TRAN
COMMIT TRAN
RETURN NULL
END TRY
Error
The 'spOnlineTest_CheckLogin' procedure attempted to return a status of NULL, which is not allowed. A status of 0 will be returned instead.
Msg 0, Level 11, State 0, Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
No, the return type of a stored procedure is INT and it cannot be null.
use an output parameter, example
CREATE PROCEDURE Test
#UserName NVARCHAR(50), #Status int output
AS
BEGIN TRY
BEGIN TRAN
COMMIT TRAN
set #Status = null
END TRY
begin catch
end catch
go
then call it like this
declare #s int
set #s =5
exec Test'bla',#s output
select #s --will be null
You can think of a proc like follows. Let me first set the context. We might have a table Table1(id int, name varchar(2), Address varchar(2)) and want to get the id and if not found, it will be null. So we might write a proc like the following:
CREATE PROCEDURE GetId
#Name VARCHAR(50), #Status int output
AS
BEGIN TRY
set #Status = null
select #Status = id from Table1 where name=#name
This will work for you.

Resources