SQL Server: how to create a stored procedure - sql-server

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';

Related

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

What is the best way to toggle user defined column name or default column name in stored procedure

What is the best approach for stored procedure to toggle between user defined column names or default column name
Here is what I have done so far. This is fine for small query, is there a better way of doing this for larger query.
-- Drop stored procedure if it already exists
IF EXISTS(SELECT * FROM sys.procedures
WHERE schema_id = schema_id('dbo')
AND name = N'sp_test')
DROP PROCEDURE dbo.sp_test
GO
CREATE PROCEDURE [dbo].[sp_test]
-- /* Declare parameters */
#columnName BIT =0
AS
BEGIN
-- SELECT statement to fetch record
IF(#columnName =1)
(
SELECT
TOP 100
IM.INC_REF,
IM.ID
FROM
dbo.TEST AS IM
)
ELSE
(
SELECT
TOP 100
IM.INC_REF AS REF,
IM.ID AS ID
FROM
dbo.TEST AS IM
)
END
GO
-- ============================================
-- Execute stored procedure
-- ============================================
DECLARE #columnName AS BIT
SET #columnName =0
EXEC [dbo].[sp_test] #columnName
Thanks in advance
When we need different results from a stored procedure based on a parameter, we'll call one of two "sub" stored procedures. In your case, that would be:
CREATE PROCEDURE [dbo].[sp_test]
-- /* Declare parameters */
#columnName BIT = 0
AS
BEGIN
IF ( #columnName = 1 )
EXEC dbo.[sp_test1]
ELSE
EXEC dbo.[sp_test2]
END
GO
CREATE PROCEDURE dbo.[sp_test1]
AS
BEGIN
SELECT TOP 100
IM.INC_REF ,
IM.ID
FROM dbo.TEST AS IM
END
GO
CREATE PROCEDURE dbo.[sp_test2]
AS
BEGIN
SELECT TOP 100
IM.INC_REF AS REF ,
IM.ID AS ID
FROM dbo.TEST AS IM
END
GO
I've found this gets around the issue of badly cached plans.

stored procedure too many arguments error

i have written following stored procedure:
in which there are 2 tables arts and artist.artistId is a foreign key in arts table.
create procedure spInsertArts(
#artsId int out,
#name varchar(50),
#category varchar(50),
#artistId int
)
as
begin
declare #artistId int
set #artistId=##IDENTITY
if exists(select artistId from artist)
insert into arts(name,category,artistId) values(#name,#category,#artistId)
end
I am getting error as:
Procedure or function spInsertArts has too many arguments specified.
The code used to call this procedure is:
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#name", TextBox1.Text);
cmd.Parameters.AddWithValue("#category", DropDownList1.SelectedValue);
SqlParameter output = new SqlParameter();
output.ParameterName = "#artsId";
output.SqlDbType = System.Data.SqlDbType.Int;
output.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(output);
con.Open();
cmd.ExecuteNonQuery();
please help
You are not passing any value for parametere #artistId
Either pass a value or change procedure and set it default value null see below:
cmd.Parameters.AddWithValue("#artistId", "VALUE_HERE");
OR
create procedure spInsertArts(
#artsId int out,
#name varchar(50),
#category varchar(50),
#artistId int = null
)
output.ParameterName = "#artsId";
You are using "#artsId" where it should be "#artistId"
Based on your comment that you are aiming to use the last inserted record in the artist table you want to be using either:
DECLARE #artistId INT = IDENT_CURRENT('dbo.Artist');
Or simply
DECLARE #artistId INT = (SELECT MAX(ArtistID) FROM dbo.Artist);
CREATE PROCEDURE dbo.spInsertArts
#name VARCHAR(50),
#category VARCHAR(50),
#artsId INT OUT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM dbo.Artist)
BEGIN
DECLARE #artistId INT = (SELECT MAX(ArtistID) FROM dbo.Artist);
INSERT dbo.Arts (Name, Category, ArtistID)
VALUES (#Name, #Category, #ArtistID);
SET #ArtsID = SCOPE_IDENTITY();
END
END
I have made the following changes to your code:
Removed the redundant parameter #ArtistID and replaced it with a local variable.
Set #ArtsID after the insert.
Terminated all statements with a semi-colon
Used the schema prefix in all object references
Aaron Bertrand has done a great article called My stored procedure "best practices" checklist, which I tend to stick to, although some of it is personal preference, all of it is logical to me.
I really disagree with this logic though, it makes your procedure completely inflexible. What if you need to insert art for an artist that isn't the latest one? If inserting for the last artist is a real requirement then I'd suggest having two procedures:
CREATE PROCEDURE dbo.spInsertArts
#name VARCHAR(50),
#category VARCHAR(50),
#ArtistID INT,
#artsId INT OUT
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.Arts (Name, Category, ArtistID)
VALUES (#Name, #Category, #ArtistID);
END
GO
CREATE PROCEDURE dbo.spInsertArtsWithLatestArtist
#name VARCHAR(50),
#category VARCHAR(50),
#artsId INT OUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #artistId INT = (SELECT MAX(ArtistID) FROM dbo.Artist);
IF #ArtistID IS NOT NULL
BEGIN
EXECUTE dbo.spInsertArts #name, #category, #ArtistID, #artsID OUT;
END
END

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 - Trouble passing variable to a stored procedure

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

Resources