I have written the following SQL Stored Procedure, and it keeps giving me the error at
#pid = SELECT MAX(... The whole procedure is:
Alter PROCEDURE insert_partyco
#pname varchar(200)
AS
BEGIN
DECLARE #pid varchar(200);
#pid = SELECT MAX(party_id)+1 FROM PARTY;
INSERT INTO party(party_id, name) VALUES(#pid, #pname)
SELECT SCOPE_IDENTITY() as PARTY_ID
END
GO
Can anyone please tell me what I'm doing wrong here?
Alter PROCEDURE insert_partyco
#pname varchar(200)
AS
BEGIN
DECLARE #pid varchar(200);
SELECT #pid = MAX(party_id)+1 FROM PARTY;
INSERT INTO party(party_id, name) VALUES(#pid, #pname)
SELECT SCOPE_IDENTITY() as PARTY_ID
END
This has an advantage over SET with SELECT in that you can select expressions in multiple variables in one statement:
SELECT #var1 = exp1, #var2 = expr2 ... etc
declare #total int
select #total = count(*) from news;
select * from news where newsid = #total+2
//**news** table name and **newsid** column name
You need to use SET.
Alter PROCEDURE insert_partyco
#pname varchar(200)
AS
BEGIN
DECLARE #pid varchar(200);
SET #pid = (SELECT MAX(party_id)+1 FROM PARTY);
INSERT INTO party(party_id, name) VALUES(#pid, #pname)
SELECT SCOPE_IDENTITY() as PARTY_ID
END
GO
Alternatively, in your case you could make party_id an autoincremented value, so you wouldn't need to query the table.
Related
I'm going to create different temp tables depending on the #selection parameter I get, and then I want to return the table I created.
I actually wanted to do it with the function, but I got an error for variable parameter tables. The sql procedur I wrote is as follows:
ALTER PROCEDURE [dbo].[Report]
(#Id BIGINT = 55,
#selection INT)
AS
BEGIN
IF #selection=1
BEGIN
Declare #tep_table table (Id int
,Name varchar(250)
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table
Select * from User
END
IF #selection=1
BEGIN
Declare #tep_table2 table (Id int
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table2
Select * from Client
END
IF #selection=1
BEGIN
RETURN #tep_table
END
ELSE
BEGIN
RETURN #tep_table2
END
END
I am getting this error:
Must declare the scalar variable "#tep_table"
Personally I would turn this into three procedures to avoid the performance problems faced with multiple execution paths.
Something like this.
ALTER Procedure [dbo].[Report]
(
#Id bigint = 55 --not sure what the point of this parameter is as it wasn't used anywhere in the sample code
, #selection int
) AS
set nocount on;
IF #selection = 1
exec GetUserData;
IF #selection = 2
exec GetClientData;
GO
create procedure GetUserData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from [User];
GO
create procedure GetClientData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from Client;
GO
I have a stored procedure that looks like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE Guests_Load
#Id AS Varchar(30)
AS
SET NOCOUNT ON
SELECT *
FROM Guests
WHERE HotelId = #Id
SELECT
GroupId,
HotelName,
FROM
HotelView(NOLOCK)
WHERE
HotelId = #Id
GO
Now, I want to create a new result set by writing another SELECT statement.
However, I want the groupId that is returned from the second SELECT. How do I do this? I tried:
DECLARE #hotelId int;
SELECT
#hotelId = GroupId,
HotelName,
FROM
HotelView(NOLOCK)
WHERE
HotelId = #Id
but I get an error saying
A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations
A simple solution is just to run the query twice:
CREATE PROCEDURE Guests_Load (
#Id AS Varchar(30)
) AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM Guests
WHERE HotelId = #Id;
SELECT GroupId, HotelName
FROM HotelView
WHERE HotelId = #Id;
DECLARE #GroupId int;
SELECT #GroupId = GroupId
FROM HotelView
WHERE HotelId = #Id;
END;
Personally, I am not a fan of stored procedures printing out tables. So, I would be inclined to have all the SELECTs use only variables. But if you want the print-out, then one method is to run the code twice.
I am using SQL Server 2008 R2. I am having some problems finding an effective coding pattern for SQL which supports code re-usability as well as flexibility. By re-usability, what I mean is keeping SQL queries in Stored Procedures and User Defined Functions.
Now, if I choose Stored Procedures, I will be sacrificing its usability in a query directly. If I choose User Defined Functions, I won't be able to use DML statements.
For example, suppose I created a Stored Procedures which inserts one contact record. Now, if I am having a table which can act as a source of multiple contact records, all I am left with are either WHILE loops or CURSORs, which is clearly not a recommended option, due to its performance drawbacks. And due to the fact that DML statements are not allowed in User Defined Functions, I simply cannot use them for this purpose.
Although, If I am not concerned with code re-usability, then instead of using Stored Procedures I can surely use same set of queries again and again to avoid while loops.
What pattern should I follow?
Here is a similar Stored Procedures:-
ALTER Proc [dbo].[InsertTranslationForCategory]
(
#str nvarchar(max),
#EventId int,
#CategoryName NVarchar(500),
#LanguageId int,
#DBCmdResponseCode Int Output,
#KeyIds nvarchar(max) Output
)as
BEGIN
DECLARE #XmlData XML
DECLARE #SystemCategoryId Int
DECLARE #CategoryId Int
Declare #Counter int=1
Declare #tempCount Int
Declare #IsExists int
Declare #TranslationToUpdate NVarchar(500)
Declare #EventName Varchar(200)
declare #Locale nvarchar(10)
declare #Code nvarchar(50)
declare #KeyName nvarchar(200)
declare #KeyValue nvarchar(500)
select #Locale=locale from languages where languageid = #LanguageId
SET #DBCmdResponseCode = 0
SET #KeyIds = ''
select #EventName = eventName from eventLanguages
where eventID = #EventId
--BEGIN TRY
Select #SystemCategoryId=CategoryId from SystemCategories where Name=rtrim(ltrim(#CategoryName))
Select #CategoryId=CategoryId from Categories where Name=rtrim(ltrim(#CategoryName)) and EventId=#EventId
if (#str='deactivate')
Begin
Delete from Codetranslation where CategoryId=#CategoryId
Update Categories set [Status]=0, Isfilter=0 where CategoryId=#CategoryId and Eventid=#EventId
Set #DBCmdResponseCode=2
return
End
set #XmlData=cast(#str as xml)
DECLARE #temp TABLE
(
Id int IDENTITY(1,1),
Code varchar(100),
Translation varchar(500),
CategoryId int
)
Insert into #temp (Code,Translation,CategoryId)
SELECT
tab.col.value('#Code', 'varchar(200)'),
tab.col.value('#Translation', 'varchar(500)'),#SystemCategoryId
FROM #XmlData.nodes('/Data') AS tab (col)
select #tempCount=Count(*) from #temp
if(IsNull(#CategoryId,0)>0)
Begin
While (#Counter <= #tempCount)
Begin
Select #IsExists= count(sc.categoryid) from #temp t Inner Join SystemCodetranslation sc
On sc.categoryid=t.CategoryId
where ltrim(rtrim(sc.code))=ltrim(rtrim(t.code)) and ltrim(rtrim(sc.ShortTranslation))=ltrim(rtrim(t.Translation))
and t.Id= #Counter
print #IsExists
Select #Code = Code , #KeyValue = Translation from #temp where id=#counter
set #KeyName = ltrim(rtrim(#EventName)) + '_' + ltrim(rtrim(#CategoryName)) + '_' + ltrim(rtrim(#Code)) + '_LT'
exec dbo.AddUpdateKeyValue #EventId,#Locale, #KeyName,#KeyValue,NULL,12
select #KeyIds = #KeyIds + convert(varchar(50),keyvalueId) + ',' from dbo.KeyValues
where eventid = #EventId and keyname = #KeyName and locale = #Locale
set #KeyName = ''
set #KeyValue = ''
Set #Counter= #Counter + 1
Set #IsExists=0
End
End
--- Inser data in Codetranslation table
if(isnull(#CategoryId,0)>0)
Begin
print #CategoryId
Delete from codetranslation where categoryid=#CategoryId
Insert into codetranslation (CategoryId,Code,LanguageId,ShortTranslation,LongTranslation,SortOrder)
SELECT
#CategoryId,
tab.col.value('#Code', 'varchar(200)'), #LanguageId,
tab.col.value('#Translation', 'varchar(500)'),
tab.col.value('#Translation', 'varchar(500)'),0
FROM #XmlData.nodes('/Data') AS tab (col)
Update Categories set [Status]=1 where CategoryId=#CategoryId and Eventid=#EventId
End
Set #DBCmdResponseCode=1
set #KeyIds = left(#KeyIds,len(#KeyIds)-1)
END
You can use table variable parameter for your user defined functions.
following code is an example of using table variable parameter in stored procedure.
CREATE TYPE IdList AS TABLE (Id INT)
CREATE PROCEDURE test
#Ids dbo.IdList READONLY
AS
Select *
From YourTable
Where YourTable.Id in (Select Id From #Ids)
End
GO
In order to execute your stored procedure use following format:
Declare #Ids dbo.IdList
Insert into #Ids(Id) values(1),(2),(3)
Execute dbo.test #Ids
Edit
In order to return Inserted Id, I don't use from Table Variable Parameter. I use following query sample for this purpose.
--CREATE TYPE NameList AS TABLE (Name NVarChar(100))
CREATE PROCEDURE test
#Names dbo.NameList READONLY
AS
Declare #T Table(Id Int)
Insert Into YourTable (Name)
OUTPUT Inserted.Id Into #T
Select Name
From #Names
Select * From #T
End
GO
I have to implement SELECT ... FROM ... WHERE .. IN query in my stored procedure.
Below is the code from my stored procedure
ALTER PROCEDURE [dbo].[SP_GetQuestionSetMultiCat]
-- Add the parameters for the stored procedure here
#PIN varchar(50),
#CatIds varchar(50),
#Range int,
#Que_Type varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #qtId as int;
select #qtId = Que_Type_Id from dbo.QuestionType_Tbl where Que_Type=#Que_Type;
-- Insert statements for procedure here
Select Top(#Range)
QId,
Que_Type_Id,
Que_Level_Id,
Que_Category_Id,
Que,
Opt1,
Opt2,
Opt3,
Opt4,
Ans
From
dbo.Que_Tbl
Where
(Que_Category_Id in (cast(#CatIds as varchar)))
and (Que_Type_Id=#qtId)
and (Qid not in (Select Que_Id From dbo.UserQuestion_Mapping where PIN=#PIN and Que_typeID=#qtId))
END
Look at the where condition. The Que_Category_Id is int type. What i want to perform is -
Where Que_Category_Id in (1,2,3,4)
The in values i m passing is a string converted from my C# code.
When I am executing this query like -
exec SP_GetQuestionSetMultiCat '666777','4,5,6',5,'Practice'
it is generating an error -
Conversion failed when converting the varchar value '{4,5,6}' to data type int.
Can anybody help me out how to solve this problem.
Thanks for sharing your valuable time.
1)Conversion failed when converting the varchar value '{4,5,6}' to data type int.
The reason of this error is data type precedence. INT data type has "higher" precedence than VARCHAR data type (16-INT vs. 27-VARCHAR).
So, SQL Server is trying to convert '{4,5,6}' to INT and not vice versa.
2) Instead, I would convert #CatIds to XML and then to a table variable (#IDs) using nodes(...) method:
SET ANSI_WARNINGS ON;
DECLARE #CatIds VARCHAR(50) = '4,5,6';
DECLARE #x XML;
SET #x = '<node>' + REPLACE(#CatIds, ',', '</node> <node>') + '</node>';
DECLARE #IDs TABLE
(
ID INT PRIMARY KEY
);
INSERT #IDs(ID)
SELECT t.c.value('.', 'INT')
FROM #x.nodes('/node') t(c);
--Test
SELECT *
FROM #IDs
3) The next step is to rewrite the query using IN (SELECT ID FROM #IDs) instead of in (cast(#CatIds as varchar)):
SET ANSI_WARNINGS ON;
ALTER PROCEDURE [dbo].[SP_GetQuestionSetMultiCat]
-- Add the parameters for the stored procedure here
#PIN varchar(50),
#CatIds varchar(50),
#Range int,
#Que_Type varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #qtId as int;
select #qtId = Que_Type_Id from dbo.QuestionType_Tbl where Que_Type=#Que_Type;
--Start: New T-SQL code
DECLARE #x XML;
SET #x = '<node>' + REPLACE(#CatIds, ',', '</node> <node>') + '</node>';
DECLARE #IDs TABLE
(
ID INT PRIMARY KEY
);
INSERT #IDs(ID)
SELECT t.c.value('.', 'INT')
FROM #x.nodes('/node') t(c);
--End
-- Insert statements for procedure here
Select Top(#Range)
QId,
Que_Type_Id,
Que_Level_Id,
Que_Category_Id,
Que,
Opt1,
Opt2,
Opt3,
Opt4,
Ans
From
dbo.Que_Tbl
Where
--The search condition is rewritten using IN(subquery)
Que_Category_Id in (SELECT ID FROM #IDs)
and (Que_Type_Id=#qtId)
and (Qid not in (Select Que_Id From dbo.UserQuestion_Mapping where PIN=#PIN and Que_typeID=#qtId))
END
4) Call stored procedure:
exec SP_GetQuestionSetMultiCat '666777','4,5,6',5,'Practice'
Does anyone know how to write a script in stored proc to run the table based on the variable (or will it possible to do so?)?
for example:
I have 3 tables name called customer, supplier, and support
when user input 1, then run table customer, 2 table supplier and 3 table support
declare #input int;
if #input =1
begin
declare #table varchar(50); set #table = 'customer'
end
if #input =2
begin
declare #table varchar(50); set #table = 'supplier '
end
if #input =3
begin
declare #table varchar(50); set #table = 'support'
end
select *
INTO ##test
from #table
IF it really is that simple, why not just repeat the Select?
if #input =1
begin
Select * INTO ##test From customer
end
if #input =2
begin
Select * INTO ##test From supplier
end
if #input =3
begin
Select * INTO ##test From support
end
yes you can do it by using dynamic sql "EXEC" or by "Sp_Executesql" command.
Example :
USE Northwind
GO
CREATE TABLE #MyTemp
( RowID int IDENTITY,
LastName varchar(20)
)
DECLARE #SQL nvarchar(250)
SET #SQL = 'INSERT INTO #MyTemp SELECT LastName FROM Employees;'
EXECUTE sp_executesql #SQL
Why do you want to do this? It seems like a bad idea at first glance.
Can you post what your stored procedure is doing and any relevant tables? I suspect that you may be able to either:
Modify your schema in such a way
that you would no longer to do
this
Create different stored procedures
to do what you want on each table instead of forcing it into one proc.
There are several issues that come up when you use dynamic SQL that you should be aware of. Here is a fairly comprehensive article on the pros and cons.