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.
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 been trying to print all values of two columns of table using loop in sql stored procedure but no luck yet.
CREATE PROCEDURE [usp_my_procedure_name]
AS
SET NOCOUNT ON;
BEGIN
DECLARE #User_ID INT =16
DECLARE #ID INT
DECLARE #Count INT
DECLARE #Count1 INT
DECLARE #Code VARCHAR(500)
SELECT #Count1= MAX(ID), #Count = MIN(ID)
FROM ABC
WHERE ID = 10 AND Code NOT LIKE '%ABC%'
WHILE (#Count <= #count1)
BEGIN
SELECT #ID = (ID), #Code = Code
FROM ABC
WHERE ID = 10 AND Code NOT LIKE '%ABC%
PRINT #ID
PRINT #Code
SET #Count = #Count + 1
END
END
Also how to optimize it further as i have to traverse for 7k records
Try this, and share with us what it gives you, and what the ideal result would look like (also share some of the input rows from ABC).
CREATE PROCEDURE [usp_my_procedure_name]
AS
SET NOCOUNT ON;
BEGIN
SELECT Distinct ID, Code
FROM ABC
WHERE Code NOT LIKE '%ABC%
ORDER BY ID
END
I have a stored proecdure like below:
#userInput int
as
declare isSuperUser int
declare IDs table(
recordID int
);
set isSuper = select isSuper from [User]
if(#isSuper = 1)
Begin
insert into recordID select * from TableA
End
else
Begin
insert into recordID select * from TableB
End
select * from recordID
And I would like to add "set noCount on" on every query, so the question is: is the performance in store procedureA equivalent to store procedureB?
store procedureA :
#userInput int
as
declare isSuperUser int
declare IDs table(
recordID int
);
set noCount on
set isSuper = select isSuper from [User]
if(#isSuper = 1)
Begin
insert into recordID select * from TableA
End
else
Begin
insert into recordID select * from TableB
End
select * from recordID
set noCount off
store procedureB:
#userInput int
as
declare isSuperUser int
declare IDs table(
recordID int
);
set noCount on
set isSuper = select isSuper from [User]
set noCount off
if(#isSuper = 1)
Begin
set noCount on
insert into recordID select * from TableA
set noCount off
End
else
Begin
set noCount on
insert into recordID select * from TableB
set noCount off
End
set noCount on
select * from recordID
set noCount off
SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.
TechNet
While storedProcedure is executing , there is no point of sending data back to client, setting noCount On increases performance as it reduces network traffic .
In your Store Procedure B you are switching NoCount on to off which increases network traffic.
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.
I have a trigger ,but I need to get the updated record's primary key (like as inserting the data SELECT #Id= ##IDENTITY) thus, I can pass it to where condition. How can I do that?
ALTER TRIGGER [dbo].[CariBakiyeBorcAktar]
ON [dbo].[BakimKartiDegisenParcalar]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id int
DECLARE #CariId int
DECLARE #SId int
DECLARE #MId int
declare #Tutar decimal
declare #Bakiye decimal
declare #s decimal = 0
DECLARE #ParcaId int
--how I can I get the last updateed record Identity like this??
--and pass it to update query as a where condition
SELECT #Id= ##IDENTITY
set #SId=(select SId from CariBakiye where Id =#Id)
select #CariId=tblk.CariId ,#MId=tblk.MId, #SId= tblk.SId,#Tutar=tblk.Tutar from (
SELECT tbl.CariId , tbl.MId,tbl.SId,tbl.Tutar from (select cb.MId,SUM(bk.Tutar) as Tutar,bk.SId,cb.Id as CariId FROM [BakimKartiDegisenParcalar] bk
join CariBakiye cb on cb.SId=bk.SId
where bk.SId =cb.SId group by bk.SId,cb.MId,cb.Id ) as tbl
) as tblk where SId = #SId
set #Bakiye = #s-#Tutar
update CariBakiye set Borc=#Tutar,Bakiye=#Bakiye where Id=#CariId
print #Id
-- Insert statements for trigger here
END
As Martin said, you have to understand that SQL Server triggers are per statement, not per row. So in context of your trigger you have two tables - inserted and deleted, where you could find all information about data updated. If you really want to do per row processing, you could use cursor:
ALTER TRIGGER [dbo].[CariBakiyeBorcAktar] ON [dbo].[BakimKartiDegisenParcalar]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id int
DECLARE #CariId int
DECLARE #SId int
DECLARE #MId int
declare #Tutar decimal
declare #Bakiye decimal
declare #s decimal = 0
DECLARE #ParcaId int
declare tr_cursor cursor local fast_forward for
select ID from inserted
while 1 = 1
begin
fetch tr_cursor into #Id
if ##fetch_status <> 0 break
set #SId=(select SId from CariBakiye where Id =#Id)
select #CariId=tblk.CariId ,#MId=tblk.MId, #SId= tblk.SId,#Tutar=tblk.Tutar from (
SELECT tbl.CariId , tbl.MId,tbl.SId,tbl.Tutar from (select cb.MId,SUM(bk.Tutar) as Tutar,bk.SId,cb.Id as CariId FROM [BakimKartiDegisenParcalar] bk
join CariBakiye cb on cb.SId=bk.SId
where bk.SId =cb.SId group by bk.SId,cb.MId,cb.Id ) as tbl
) as tblk where SId = #SId
set #Bakiye = #s-#Tutar
update CariBakiye set Borc=#Tutar,Bakiye=#Bakiye where Id=#CariId
print #Id
-- Insert statements for trigger here
end
close tr_cursor
deallocate tr_cursor
END