Suppress result from insert trigger - sql

A MS SQL insert trigger causes some grief as it returns a result. Is there a way to disable any result from being sent? I've used 'set nocount on', but that doesn't seem to do much...
create trigger tr_insert_raw_data
on raw_data
instead of insert
as
begin
set nocount on
declare #query varchar(max);
declare #rev int;
declare #id int;
declare #oldrev int;
declare #contextinfo VARBINARY(128)
select #contextinfo = context_info()
if #contextinfo = 0x00001
begin
insert into raw_data select * from inserted
return
end
select * into #query from inserted
set #id = (select count(distinct id) from raw_data);
set #id += 1;
insert into revisions (username, hostname, ts) values (SYSTEM_USER, HOST_NAME(), GETDATE())
set #rev = (select max(id) from revisions);
select #oldrev = revision_id from inserted;
if #oldrev is null set #oldrev=#rev-1;
select * into #inserted from inserted
update #inserted set revision_id = #rev, id = #id
select * from #inserted
insert into raw_data select * from #inserted
insert into edges (a, b) values (#oldrev, #rev)
end

what kind of a result are you getting?
After a quick review of your query my first thought is that you're getting results due to the
select * from #inserted
line you have (third line from bottom). This line tells me that you are requesting results which is probably why you're getting some?
If you do need values selected from a table to modify or custom select out of, perhaps CTE's will help you out? (Common Table Expressions)

Related

Separate rows in multiple delete SQL server

I have a trigger. When i delete something in my table i want to create a row in other table named Archive with the row i deleted. All works fine. The problem is when i delete more than one row in the same time. It store just the first row in the table Archive. I think about creating a loop but how i separate them in subqueries to select every row. How do i solve that?
ALTER TRIGGER [dbo].[trigArhiva]
ON [dbo].[student]
AFTER DELETE
AS
SET NOCOUNT ON;
BEGIN
declare #nume varchar(45);
declare #anStudiu int;
declare #prenume varchar(45);
declare #CNP char(13);
declare #grupa int;
declare #idFacult int;
declare #rowss int;
declare #i int;
select #rowss = count(*) from DELETED;
set #i = 1;
while (#i <= #rowss)
begin
select #nume = nume from DELETED;
select #anStudiu = anStudiu from DELETED;
select #prenume = prenume from DELETED;
select #CNP = CNP from DELETED;
select #grupa = idGrupa from DELETED;
select #idFacult = idFacult from DELETED;
insert into arhivaStud(nume, prenume, CNP, grupa, idFacult, anStudiu) values (#nume, #prenume, #CNP, #grupa, #idFacult, #anStudiu);
set #i = #i+1;
end
END
I think you should use something like this (deleted is an "internal" representation of all records deleted during the operation which recall the trigger):
ALTER TRIGGER [dbo].[trigArhiva]
ON [dbo].[student]
AFTER DELETE
AS
SET NOCOUNT ON;
BEGIN
INSERT INTO arhivaStud(nume, prenume, CNP, grupa, idFacult, anStudiu)
SELECT nume, prenume, CNP, idgrupa, idFacult, anStudiu FROM deleted
END

SQL set noCount on in all query

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.

SQL Looping temp table and reading data

I have following script to create temp data
DECLARE #Name NVARCHAR(100), #Marks INT
DECLARE #MYTABLE TABLE
(
[Name][nvarchar](100) NULL,
[Marks][INT] NULL
)
INSERT INTO #MYTABLE ([Name],[Marks]) VALUES ('Mark',50);
INSERT INTO #MYTABLE ([Name],[Marks]) VALUES ('Steve',50);
INSERT INTO #MYTABLE ([Name],[Marks]) VALUES ('Don',50);
Now I want loop it, as shown in below script
SELECT #MaxPK = MAX(PK) from #MYTABLE
WHILE #PK <= #MaxPK
BEGIN
SET #Name = SELECT Name from #MYTABLE
SET #Marks = SELECT Marks from #MYTABLE
print #Name
print #Marks
SET #PK = #PK + 1
END
But I get error near SELECT statement.
"Incorrect syntax near the keyword SELECT"!
The two rows where you set the variables can be put together like this. That way you will only scan the table once.
SELECT #Name = Name, #Marks = Marks FROM #MYTABLE
Just know that the row chosen to be put in your variables is completely arbitary (and will probably be the same row every time) unless you add a whereclause.
Please try below while loop:
WHILE #PK <= #MaxPK
BEGIN
SELECT #Name = Name, #Marks = Marks from #MYTABLE
print #Name
print #Marks
END
Note: I guess, a where condition is required in select statement in order to print all data.

update trigger get the updated primary key

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

Unable to do the union in stored procedure for selected queries

ALTER PROC [dbo].[Usp_SelectQuestion]
#NoOfQuestion int
AS
BEGIN
Declare #CNT int
Declare #test int
Declare #x int
Declare #y int
set #x = 1;
set #y = 1;
set #CNT=(Select Count(*) from (select Distinct(setno)from onlin) AS A)
set #test=#NoOfQuestion/#CNT
while (#x <= #CNT)
begin
select top (#test) * from onlin where setno = #x order by NEWID()
set #x = #x + 1
end
END
In this stored procedure I am getting output as single table for every loop so I am getting multiple tables as output but I want all rows in a single table I think through union we can achieve but I do not know how to use.
Use this:
CREATE TEMPORARY TABLE tmp SELECT * FROM tableName;
then insert to table
INSERT INTO tableName SELECT * FROM tmp;
declare #temptable as table(col1 int, col2 varchar(50),... etc)
while (#x <= #CNT)
begin
insert into #temptable 'temptable columns need to match columns in the SELECT statement
select top (#test) * from onlin where setno = #x order by NEWID()
set #x = #x + 1
end
select * from #temptable
Create a temp table and insert into that in the loop and then the result will be the:
SELECT * FROM tempTable