SQL Server - Trouble passing variable to a stored procedure - sql-server

I know this is a basic question - but I can't figure the correct way to get this done.
I need to pass a variable to a SQL Server 2008 stored procedure and return the query.
Here's the stored procedure:
CREATE PROCEDURE pOrders
AS
DECLARE #enteredClientID varchar(20);
DECLARE #Results table (ClientID varchar(20), Num_orders int);
BEGIN
SET NOCOUNT ON;
-- Get all the order from the client
INSERT INTO #Results
SELECT ClientID, sum(Num_orders)
FROM Orders O
WHERE O.ClientID = #enteredClientID
GROUP BY O.ClientID);
-- Insert the orders into the results table --
SELECT *
FROM #Results;
END
GO;
Now, I would execute the stored procedure and get the result back:
exec pOrders
set #enteredClientID = 'ABC123456789'
I get this error message back:
Must declare the scalar variable "#enteredClientID".
But, I'm declaring the variable.... what am I missing?

You didn't declare a parameter, but a local variable. To declare it as you wanted to:
CREATE PROCEDURE pOrders (#enteredClientID varchar(20))
AS
DECLARE #Results table (ClientID varchar(20), Num_orders int);
SET NOCOUNT ON;
-- Get all the order from the client
INSERT INTO #Results
SELECT ClientID, sum(Num_orders)
FROM Orders O
WHERE O.ClientID = #enteredClientID
GROUP BY O.ClientID);
-- Insert the orders into the results table --
SELECT *
FROM #Results;
GO;
An to call it:
exec pOrders #enteredClientID = 'ABC123456789'
or simply
exec pOrders 'ABC123456789'

--In stored proc
DECLARE #enteredClientID varchar(20) OUTPUT
--Then insert and set identity
SELECT SCOPE_IDENTITY() AS #enteredClientID
--When calling procedure:
-- DECLARE variables to hold the return value
DECLARE #enteredClientID VARCHAR(20);
-- Execute the procedure, which returns value.
EXEC #enteredClientID = pOrders

Try EXEC pOrders 'ABC123456789'.
The call you provided attempts to execute the procedure (with no parameters passed), then attempts to set a variable named #enteredClientID. Since you have not declared #enteredClientID in the scope of the executing code, it cannot set it.
For more information about how to use parameters with procedures, this article may be helpful:
http://msdn.microsoft.com/en-us/library/ms189915.aspx

Related

How to get Value from Execute command as output parameter in SQL Server?

I need to get the result from the catch block from store procedure and pass it as output parameter. So I could use result in select statement with a field value. For now it is executing correctly, but the select statement returns me NULL Value.
CREATE procedure [dbo].[sp_calc] #mathexpr NVarchar(20), #returnValue decimal(9,2) out
as
declare #query varchar(800)
BEGIN TRY
SELECT #returnValue=CAST(#mathexpr as decimal(9,2))
END TRY
BEGIN CATCH
SET #query='SELECT CAST('+#mathexpr+' as decimal(9,2))'
EXECUTE(#query)
END CATCH
declare #result decimal(9,2)
exec sp_calc #mathexpr='1.600*2.5478/1.2',#returnValue=#result out
select #result as result
Thank's for help.
You would need to use the INSERT..EXECUTE structure to execute your dynamic SQL and store the results in a variable that the code outside of the dynamic sql can access.
Here is full code that do my job. I made little changes like using float instead of decimal, and NVarchar instead of Varchar. Global temp table is created out of the store procedure, so it is can be used out of the sp. Hope this will help and others.
IF OBJECT_ID('tempdb.dbo.##NSesion') IS NOT NULL
BEGIN
DROP TABLE ##NSesion
END
create table ##NSesion (ID int identity,F1 float null)
exec sp_calc #appSesion=##NSesion, #mathexpr='1*2/3'
select F1 as r from ##NSesion
drop table ##NSesion
create procedure [dbo].[sp_calc] #APPSesion NVarchar(10), #mathexpr NVarchar(20)
as
declare #query NVarchar(800)
declare #RV float
BEGIN TRY
SELECT #RV=CAST(#mathexpr as float)
if (#RV<>0) or (not #RV is null)
SET #query='insert into '+#APPSesion+' (F1) values ('+#RV+') '
EXECUTE(#query)
END TRY
BEGIN CATCH
SET #query='insert into '+#APPSesion+' (F1) values (CAST('+#mathexpr+' as float)) '
EXECUTE(#query)
END CATCH

SQL stored procedure - table as parameter

I have a database with different tables (all the same structure) where I'd like to run a stored procedure having a parameter that defines which table to query.
I can't seem to figure it out:
CREATE SCHEMA test;
GO
First I created a schema
CREATE TYPE DataType as TABLE (
[datetime] [datetime] NULL,
[testVar] [bigint] NULL)
GO
Then I created the table type
USE [TestDataFiles]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [test].[testing]
(
-- Add the parameters for the stored procedure here
#datetime datetime,
#t DataType READONLY
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
select top(10) *
from #t
where [datetime] > #datetime
END
GO
Then I created the stored procedure.
Exec test.testing #t = 'table.1', #datetime = '2017-01-01'
However when I call it I get the following error:
Msg 206, Level 16, State 2, Procedure test, Line 0 [Batch Start Line 0]
Operand type clash: varchar is incompatible with DataType
Same happens with:
Exec test.testing #t = [table.1], #datetime = '2017-01-01'
I have seen an example where in the procedure between the begin and select you put something like:
INSERT INTO table.1
( datetime, testVar)
But table.1 (or table.2 etc as I have a list of tables) has data and I don't want to change it.
Unless I'm meant to create a dummy table like I did the TYPE?
The examples I've found online havent been useful.
To do that you will need to use dynamic SQL
The basic procedure is to build up a string that will hold the statement you will execute, then execute it
declare #SQL nvarchar(1000)
declare #t as nvarchar (1000)
set #t = 'MyTable'
set #Sql = 'Select * from ' + #t
exec sp_executesql #sql
You have to pass parameter of type DataType. So, create variable of that type and pass it into stored procedure like
declare #table1 DataType
INSERT INTO #table1(datetime, testVar) values (..., ...)
Exec test.testing #datetime = '2017-01-01', #t = #table1

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

SQL Server: how to create a stored procedure

I'm learning sql from a book and I'm trying to write a stored procedure but I don't believe that I'm doing it correctly. Is the following way not valid in Microsoft SQL? If not, when is it valid, if ever?
create procedure dept_count(in dept_name varchar(20), out d_count integer)
begin
select count(*) into d_count
from instructor
where instructor.dept_name=dept_count.dept_name
end
I get the following error
Msg 156, Level 15, State 1, Procedure wine_change, Line 1
Incorrect syntax near the keyword 'in'.
T-SQL
/*
Stored Procedure GetstudentnameInOutputVariable is modified to collect the
email address of the student with the help of the Alert Keyword
*/
CREATE PROCEDURE GetstudentnameInOutputVariable
(
#studentid INT, --Input parameter , Studentid of the student
#studentname VARCHAR (200) OUT, -- Output parameter to collect the student name
#StudentEmail VARCHAR (200)OUT -- Output Parameter to collect the student email
)
AS
BEGIN
SELECT #studentname= Firstname+' '+Lastname,
#StudentEmail=email FROM tbl_Students WHERE studentid=#studentid
END
In T-SQL stored procedures for input parameters explicit 'in' keyword is not required and for output parameters an explicit 'Output' keyword is required. The query in question can be written as:
CREATE PROCEDURE dept_count
(
-- Add input and output parameters for the stored procedure here
#dept_name varchar(20), --Input parameter
#d_count int OUTPUT -- Output parameter declared with the help of OUTPUT/OUT keyword
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Statements for procedure here
SELECT #d_count = count(*)
from instructor
where instructor.dept_name=#dept_name
END
GO
and to execute above procedure we can write as:
Declare #dept_name varchar(20), -- Declaring the variable to collect the dept_name
#d_count int -- Declaring the variable to collect the d_count
SET #dept_name = 'Test'
Execute dept_count #dept_name,#d_count output
SELECT #d_count -- "Select" Statement is used to show the output
I think it can help you:
CREATE PROCEDURE DEPT_COUNT
(
#DEPT_NAME VARCHAR(20), -- Input parameter
#D_COUNT INT OUTPUT -- Output parameter
-- Remember parameters begin with "#"
)
AS -- You miss this word in your example
BEGIN
SELECT COUNT(*)
INTO #D_COUNT -- Into a Temp Table (prefix "#")
FROM INSTRUCTOR
WHERE INSTRUCTOR.DEPT_NAME = DEPT_COUNT.DEPT_NAME
END
Then, you can call the SP like this way, for example:
DECLARE #COUNTER INT
EXEC DEPT_COUNT 'DeptName', #COUNTER OUTPUT
SELECT #COUNTER
Try this:
create procedure dept_count(#dept_name varchar(20),#d_count int)
begin
set #d_count=(select count(*)
from instructor
where instructor.dept_name=dept_count.dept_name)
Select #d_count as count
end
Or
create procedure dept_count(#dept_name varchar(20))
begin
select count(*)
from instructor
where instructor.dept_name=dept_count.dept_name
end
CREATE PROCEDURE [dbo].[USP_StudentInformation]
#S_Name VARCHAR(50)
,#S_Address VARCHAR(500)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Date VARCHAR(50)
SET #Date = GETDATE()
IF EXISTS (
SELECT *
FROM TB_StdFunction
WHERE S_Name = #S_Name
AND S_Address = #S_Address
)
BEGIN
UPDATE TB_StdFunction
SET S_Name = #S_Name
,S_Address = #S_Address
,ModifiedDate = #Date
WHERE S_Name = #S_Name
AND S_Address = #S_Address
SELECT *
FROM TB_StdFunction
END
ELSE
BEGIN
INSERT INTO TB_StdFunction (
S_Name
,S_Address
,CreatedDate
)
VALUES (
#S_Name
,#S_Address
,#date
)
SELECT *
FROM TB_StdFunction
END
END
Table Name : TB_StdFunction
S_No INT PRIMARY KEY AUTO_INCREMENT
S_Name nvarchar(50)
S_Address nvarchar(500)
CreatedDate nvarchar(50)
ModifiedDate nvarchar(50)
Create this way.
Create procedure dept_count(dept_name varchar(20),d_count integer)
begin
select count(*) into d_count
from instructor
where instructor.dept_name=dept_count.dept_name
end
try this:
create procedure dept_count( #dept_name varchar(20), #d_count INTEGER out)
AS
begin
select count(*) into d_count
from instructor
where instructor.dept_name=dept_count.dept_name
end
To Create SQL server Store procedure in SQL server management studio
Expand your database
Expand programmatically
Right-click on Stored-procedure and Select "new Stored Procedure"
Now, Write your Store procedure, for example, it can be something like below
USE DatabaseName;
GO
CREATE PROCEDURE ProcedureName
#LastName nvarchar(50),
#FirstName nvarchar(50)
AS
SET NOCOUNT ON;
//Your SQL query here, like
Select FirstName, LastName, Department
FROM HumanResources.vEmployeeDepartmentHistory
WHERE FirstName = #FirstName AND LastName = #LastName
GO
Where, DatabaseName = name of your database
ProcedureName = name of SP
InputValue = your input parameter value (#LastName and #FirstName) and type = parameter type example nvarchar(50) etc.
Source: Stored procedure in sql server (With Example)
To Execute the above stored procedure you can use sample query as below
EXECUTE ProcedureName #FirstName = N'Pilar', #LastName = N'Ackerman';

Calling a stored proc that returns a recordset from within a stored proc

Working in SQL Server 2005, I have a stored procedure that inserts a record and returns the new ID via SELECT ##IDENTITY; as the last command.
I then want to call this from another stored proc, and get the value of the new ID.
But I can't work out how to get the value returned from the first procedure.
Example:
CREATE PROCEDURE spMyInsert(#Field1 VARCHAR(10)) AS
BEGIN
INSERT INTO tMyTable (Column1) VALUES (#Field1); // ID column implicitly set
SELECT ##IDENTITY ID;
END
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
EXEC spMyInsert 'TEST';
// How do I set #NewID to the value returned from spMyInsert?
END
There is another question that nearly answers my question, but not quite. This explains how to insert the results into another table, but all I want to do is store it in a local variable.
Looking at other similar questions, the general answer is to change to either set an OUTPUT variable or create a function to do it, but I can't do this in my case as other .NET data access stuff uses the same stored proc, and I don't want to have to duplicate all the work of the stored procs as functions as well.
I couple of things that I've tried but all fail are:
SET #NewID = (EXEC spMyInsert 'TEST');
SET #NewID = (SELECT ID FROM (EXEC spMyInsert 'TEST'));
Anybody know how to do this?
Thanks,
Ben
By the way you should probably check that ##identity is what you need as opposed to scope_identity.
If it is what you need then it will still be accessible in the calling stored procedure too.
CREATE PROCEDURE spMyMain
AS
BEGIN
DECLARE #NewID INT;
EXEC spMyInsert 'TEST';
SET #NewID = ##IDENTITY
SELECT #NewID AS '#NewID'
END
The more general solution that would need to be applied if you use scope_identity and don't want to use either output parameters or the procedure return code is
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
DECLARE #IdHolder TABLE
(
id INT
)
INSERT INTO #IdHolder
EXEC spMyInsert 'TEST';
IF ##ROWCOUNT<>1
RAISERROR('Blah',16,1)
SELECT #NewID = id FROM #IdHolder
END
First, don't use ##IDENTITY, use SCOPE_IDENTITY() instead (search this site or Google for the reason why). Then just return the value in an output parameter:
CREATE PROCEDURE spMyInsert(#Field1 VARCHAR(10), #NewID int output) AS
BEGIN
INSERT INTO tMyTable (Column1) VALUES (#Field1);
SET #NewID = scope_identity();
END
go
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
EXEC spMyInsert #Field1 = 'TEST', #NewID = #NewID OUTPUT;
END
go
The issue here is that the spMyInsert returns a Select. When you execute spMyMain it will return the Select from spMyInsert and then the select from spMyMain
I would suggest that you amend spMyInsert to utilise OUTPUT parameters
CREATE PROCEDURE spMyInsert(#Field1 VARCHAR(10), #NewId int output) AS
BEGIN
INSERT INTO tMyTable (Column1) VALUES (#Field1); // ID column implicitly set
SELECT #NewId = ##SCOPE_IDENTITY;
END
and then
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
Set #NewId = 0
EXEC spMyInsert 'TEST', #NewId output;
select #NewId
// How do I set #NewID to the value returned from spMyInsert?
END
Note that I have also changed ##Identity to ##scope_identity It is better to use ##Scope_Identity as that will return the new ID that applies to the current connection.
Try this:
Execute #NewID = spMyInsert 'TEST'
Edit: After reading his question more thoroughly and realizing he was dealing with a select rather than a return: Could you wrap that procedure in a function call and then call the function?
select #NewId = from fnMyInsert('TEST')
An output parameter is the way to go, but if you really can't change the inner SP then, as you say, you can have the inner SP return its results to a table and then get the value out of there.
eg.
declare #NewID int,
#Customer table(CustomerId int);
insert into #Customer
exec spMyInsert 'TEST';
select #NewID = CustomerId from #Customer;

Resources