Call Stored Procedure within Create Trigger in SQL Server - sql-server

I have a stored procedure named insert2Newsletter with parameters
(#sex nvarchar(10),
#f_name nvarchar(50),
#l_name nvarchar(70),
#email nvarchar(75),
#ip_address nvarchar(50),
#hotelID int,
#maArt nchar(2))
I want call this stored procedure in an insert trigger. How do I retrieve the corresponding fields from inserted and how do i call insert2Newsletter within the trigger?
I tried without success:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER RA2Newsletter
ON [dbo].[Reiseagent]
AFTER INSERT
AS
DECLARE #rAgent_Name nvarchar(50),
DECLARE #rAgent_Email nvarchar(50),
DECLARE #rAgent_IP nvarchar(50),
DECLARE #hotelID int
BEGIN
SET NOCOUNT ON;
-- Insert statements for trigger here
Select #rAgent_Name=rAgent_Name, #rAgent_Email=rAgent_Email, #rAgent_IP=rAgent_IP, #hotelID=hotelID From Inserted
EXEC insert2Newsletter '','',#rAgent_Name,#rAgent_Email,rAgent_IP,#hotelID,'RA'
END
GO
thx a lot for your feedback... greetings...

I think you will have to loop over the "inserted" table, which contains all rows that were updated. You can use a WHERE loop, or a WITH statement if your primary key is a GUID. This is the simpler (for me) to write, so here is my example. We use this approach, so I know for a fact it works fine.
ALTER TRIGGER [dbo].[RA2Newsletter] ON [dbo].[Reiseagent]
AFTER INSERT
AS
-- This is your primary key. I assume INT, but initialize
-- to minimum value for the type you are using.
DECLARE #rAgent_ID INT = 0
-- Looping variable.
DECLARE #i INT = 0
-- Count of rows affected for looping over
DECLARE #count INT
-- These are your old variables.
DECLARE #rAgent_Name NVARCHAR(50)
DECLARE #rAgent_Email NVARCHAR(50)
DECLARE #rAgent_IP NVARCHAR(50)
DECLARE #hotelID INT
DECLARE #retval INT
BEGIN
SET NOCOUNT ON ;
-- Get count of affected rows
SELECT #Count = Count(rAgent_ID)
FROM inserted
-- Loop over rows affected
WHILE #i < #count
BEGIN
-- Get the next rAgent_ID
SELECT TOP 1
#rAgent_ID = rAgent_ID
FROM inserted
WHERE rAgent_ID > #rAgent_ID
ORDER BY rAgent_ID ASC
-- Populate values for the current row
SELECT #rAgent_Name = rAgent_Name,
#rAgent_Email = rAgent_Email,
#rAgent_IP = rAgent_IP,
#hotelID = hotelID
FROM Inserted
WHERE rAgent_ID = #rAgent_ID
-- Run your stored procedure
EXEC insert2Newsletter '', '', #rAgent_Name, #rAgent_Email,
#rAgent_IP, #hotelID, 'RA', #retval
-- Set up next iteration
SET #i = #i + 1
END
END
GO
I sure hope this helps you out. Cheers!

Finally ...
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[RA2Newsletter]
ON [dbo].[Reiseagent]
AFTER INSERT
AS
declare
#rAgent_Name nvarchar(50),
#rAgent_Email nvarchar(50),
#rAgent_IP nvarchar(50),
#hotelID int,
#retval int
BEGIN
SET NOCOUNT ON;
-- Insert statements for trigger here
Select
#rAgent_Name = rAgent_Name,
#rAgent_Email = rAgent_Email,
#rAgent_IP = rAgent_IP,
#hotelID = hotelID
From Inserted
EXEC insert2Newsletter
'',
'',
#rAgent_Name,
#rAgent_Email,
#rAgent_IP,
#hotelID,
'RA',
#retval
END

The following should do the trick - Only SqlServer
Alter TRIGGER Catagory_Master_Date_update ON Catagory_Master AFTER delete,Update
AS
BEGIN
SET NOCOUNT ON;
Declare #id int
DECLARE #cDate as DateTime
set #cDate =(select Getdate())
select #id=deleted.Catagory_id from deleted
print #cDate
execute dbo.psp_Update_Category #id
END
Alter PROCEDURE dbo.psp_Update_Category
#id int
AS
BEGIN
DECLARE #cDate as DateTime
set #cDate =(select Getdate())
--Update Catagory_Master Set Modify_date=''+#cDate+'' Where Catagory_ID=#id --#UserID
Insert into Catagory_Master (Catagory_id,Catagory_Name) values(12,'Testing11')
END

You pass an undefined rAgent_IP parameter in EXEC instead of the local variable #rAgent_IP.
Still, this trigger will fail if you perform a multi-record INSERT statement.

Related

Have anyone a solution to send row parameter to a stored prodedure in MS-SQL Server with dynamic Column Arrangement?

I Could write a trigger for a table that is able to detect updated columns and logs the changes. I want to make a stored procedure from this trigger and call it when required. But I do not know how can I send "inserted" or "updated" rows that are valid in trigger body, to this SP.
Here is my trigger :
CREATE TRIGGER [dbo].[tgr_MyTable_TransactionLogUpdate]
ON [dbo].[MyTable]
AFTER UPDATE
AS
BEGIN
if (select F_SharhRadif from [Payeh.Decode] where F_ShJadval=18 and F_ShRadif=1)='2'
begin
return
end
declare #userid int=(select top 1 userid from inserted)
declare #computername nvarchar(50)=(select top 1 computername from inserted)
declare #ip nvarchar(50)=(select top 1 IP from inserted)
declare #zamantaqeer datetime=(select top 1 F_ZamanTaqeer from inserted)
declare #changetime =GETDATE()
DECLARE #tableID BIGINT=(SELECT id FROM sys.sysobjects WHERE [name]='MyTable')
DECLARE #ColCount INT=(SELECT COUNT(*) FROM sys.syscolumns WHERE id=#tableID)
DECLARE #ColIndex INT=1
DECLARE #UpdateDetails NVARCHAR(MAX)=''
DECLARE #ColName NVARCHAR(1000)
DECLARE #ByteIndex INT
SELECT * INTO #d FROM deleted
SELECT * INTO #i FROM inserted
WHILE (#ColIndex<=#ColCount)
BEGIN
--IF (COLUMNS_UPDATED()&POWER(2,#ColIndex-1) <> 0)
SET #ByteIndex=((#ColIndex-1)/8)+1
IF (CONVERT(INT,SUBSTRING(COLUMNS_UPDATED(),#ByteIndex,1))&POWER(2,((#ColIndex-1)%8)) <> 0)
BEGIN
SET #ColName=(SELECT [name] FROM sys.syscolumns WHERE id=#tableID AND colid=#ColIndex)
DECLARE #OldValue NVARCHAR(MAX)
DECLARE #NewValue NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(100)=N'#DeletedValue NVARCHAR(MAX) OUTPUT'
DECLARE #SQL NVARCHAR(1000)='SELECT #DeletedValue=LTRIM(RTRIM(CONVERT(nvarchar(MAX),'+#ColName+'))) FROM #d'
EXEC sp_executesql #SQL,#ParmDefinition,#DeletedValue=#OldValue OUTPUT
SET #ParmDefinition = N'#InsertedValue NVARCHAR(MAX) OUTPUT'
SET #SQL= 'SELECT #InsertedValue=LTRIM(RTRIM(CONVERT(nvarchar(MAX),'+#ColName+'))) FROM #i'
EXEC sp_executesql #SQL,#ParmDefinition,#InsertedValue=#NewValue OUTPUT
IF (#OldValue<>#NewValue)
BEGIN
SET #UpdateDetails=#UpdateDetails+#ColName+': OLD="'+ #OldValue+'" -New="'+#NewValue+'", '
END
END
SET #ColIndex=#ColIndex+1
END
IF (LEN(#UpdateDetails)>0)
BEGIN
SET #UpdateDetails=SUBSTRING(#UpdateDetails,1,LEN(#UpdateDetails)-1)
END
ELSE
BEGIN
SET #UpdateDetails='No Changes'
END
--[User.TransactionLog] is the name of the table that stores the history of changes
INSERT INTO [User.TransactionLog]
([Tablename],[OperationType],[Desciption],[UserID],[ComputerName],[IP],[ChangeTime])
SELECT 'MyTable',2,#UpdateDetails,'',#userid,#computername,#ip, #changetime
DROP TABLE #d
DROP TABLE #i

Create trigger in stored procedure

I am trying to create a trigger inside stored procedure as it will be removed when the table is dropped.
I am getting an error and am not able to execute it.
CREATE PROCEDURE EC5Trigger2
AS
CREATE TRIGGER trVendorProductsPST
ON VendorProducts
FOR INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE #SKU VARCHAR(64)
SELECT #SKU = I.SKU FROM inserted AS I
INSERT INTO ProductStockTransactions (SKU, stockingCode)
VALUES (#SKU, 'A')
END
RETURN 0
Here is how you create your trigger inside a stored procedure using dynamic SQL, which is the only way to do it.
CREATE PROCEDURE EC5Trigger2
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TriggerCode NVARCHAR(max);
SET #TriggerCode = 'CREATE TRIGGER trVendorProductsPST
ON VendorProducts
FOR INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE #SKU VARCHAR(64)
SELECT #SKU = I.SKU from INSERTED as I
INSERT INTO ProductStockTransactions (SKU, stockingCode)
VALUES (#SKU, ''A'')
END';
EXEC(#TriggerCode);
RETURN 0;
END;

Retrieve values from database through stored procedure

I have this database with table 'crigsStaffActivity'. I managed to retrieve the values and display it. But the result is not showing as my expectation.
Script to create table with values
CREATE TABLE [dbo].[crigsStaffActivity]
(
[projectRef] [varchar](200) NOT NULL,
[activityLine] [int] NOT NULL,
[cost] [real] NOT NULL,
[staffCost] [varchar](500) NOT NULL
) ON [PRIMARY]
GO
INSERT [dbo].[crigsStaffActivity] ([projectRef], [activityLine], [cost], [staffCost])
VALUES (N'MRC/CRIGS/330', 1, 1, N'ProjectLeader'),
(N'MRC/CRIGS/330', 2, 2, N'Research Collaborators'),
(N'MRC/CRIGS/330', 1, 1, N'Project Collaborators'),
(N'MRC/CRIGS/330', 2, 2, N'Project Collaborators'),
(N'MRC/CRIGS/330', 2, 3, N'Research/Project Assistant');
ALTER TABLE [dbo].[crigsStaffActivity]
ADD CONSTRAINT [DF__crigsStaff__cost__5535A963] DEFAULT ((0)) FOR [cost]
GO
Screenshot of table:
My stored procedure:
ALTER PROCEDURE [dbo].[getCrigsStaffActivity]
#ProjectRef AS VARCHAR(1000),
#staffCost AS varchar(1000)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #val AS VARCHAR(2000);
SET #val='';
DECLARE #temp AS VARCHAR(2000);
DECLARE #activityLine AS VARCHAR(2000);
DECLARE #cost AS VARCHAR(2000);
DECLARE #ref as CURSOR;
SET #ref = CURSOR FOR
SELECT activityLine, cost
FROM crigsStaffActivity
WHERE projectRef = #ProjectRef
AND staffCost = #staffCost
OPEN #ref;
FETCH NEXT FROM #ref INTO #activityLine, #cost;
WHILE ##FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM #ref INTO #activityLine, #cost;
SET #val = CONCAT(#activityLine,',',#cost);
END
CLOSE #ref;
DEALLOCATE #ref;
SELECT #val AS ref;
END
When I execute the stored procedure, I get this result:
ref
----
2,2
The issue is that for project collaborators I have two repeating values, thus I need to get a result like this:
ref
-----
1,1
2,2
My question is how to achieve the result mentioned above.
A better result of this stored procedure could have been:
ref
-----------------------------
1,1,ProjectLeader
2,2,Research collaborators
1,1,Project collaborators
2,2,Project collaborators
2,3,Research/Project Assistant
If I got it correct. you don't need to use the cursor.
ALTER PROCEDURE [dbo].[getCrigsStaffActivity]
#ProjectRef AS VARCHAR(1000),
#staffCost AS varchar(1000)
AS
BEGIN
SET NOCOUNT ON;
SELECT CONCAT(activityLine,',', cost,',', staffCost) as ref
FROM crigsStaffActivity
WHERE projectRef = #ProjectRef
AND staffCost = #staffCost
END
Please try this Procedure.
USE [***]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[getCrigsStaffActivity]
#ProjectRef as VARCHAR(1000),
#staffCost as varchar(1000)
AS
BEGIN
SET NOCOUNT ON;
Declare #val as varchar(2000);
set #val='';
Declare #temp as Varchar(2000);
Declare #activityLine as Varchar(2000);
Declare #cost as Varchar(2000);
DECLARE #ref as CURSOR;
SET #ref = CURSOR FOR
SELECT DISTINCT activityLine, cost
FROM crigsStaffActivity
where projectRef = #ProjectRef
and staffCost = #staffCost
OPEN #ref;
FETCH NEXT FROM #ref INTO #activityLine, #cost;
WHILE ##FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM #ref INTO #activityLine, #cost;
set #val = CONCAT(#activityLine,',',#cost);
END
CLOSE #ref;
DEALLOCATE #ref;
select #val as ref;
END

Getting rows affected in stored procedure INSERT statement with NOCOUNT OFF

I have a stored procedure in SQL Server 2014 where I first delete data from a table and execute another stored procedure as shown below. I don't care about rows affected on this code so I use SET NOCOUNT ON. I then perform an Insert statement first setting SET NOCOUNT OFF. I would expect the stored procedure to return the rows affected automatically from the INSERT but that has not proven to be the case. I searched SO and found the ##ROWCOUNT and that is working. However, is that really required? Why wouldn't the INSERT statement in the code below return the records affected?
ALTER PROCEDURE [dbo].[SaveTextSetting]
#UserId INT ,
#SettingType INT = 0 ,
#SettingValue NVARCHAR(MAX)
AS
BEGIN
BEGIN
SET NOCOUNT ON;
DELETE FROM Settings
WHERE UserId = #UserId
AND SettingType = #SettingType;
EXEC dbo.PurgeExpiredSettings;
END;
BEGIN
SET NOCOUNT OFF;
INSERT INTO dbo.Settings
( UserId ,
SettingsText ,
SettingType
)
VALUES ( #UserId ,
#SettingValue ,
#SettingType
);
RETURN ##ROWCOUNT; --without this we don't get the rows affected
END;
END;
Are you sure?
CREATE PROCEDURE spTest AS RETURN
GO
ALTER PROCEDURE spTest
AS
BEGIN
SET NOCOUNT OFF
DECLARE #rt int
CREATE TABLE #t (
v int NOT NULL
)
INSERT INTO #t (v)
SELECT v FROM (VALUES (1), (1), (2)) AS t (v)
SET #rt = ##ROWCOUNT
DROP TABLE #t
RETURN #rt
END
GO
DECLARE #rt int
EXEC #rt = spTest
SELECT #rt
GO
DROP PROCEDURE spTest
GO
I would use an output param something like.....
ALTER PROCEDURE [dbo].[SaveTextSetting]
#UserId INT ,
#SettingType INT = 0 ,
#SettingValue NVARCHAR(MAX),
#RowCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM Settings
WHERE UserId = #UserId
AND SettingType = #SettingType;
EXEC dbo.PurgeExpiredSettings;
INSERT INTO dbo.Settings( UserId ,SettingsText ,SettingType)
VALUES ( #UserId ,#SettingValue ,#SettingType);
SET #RowCount= ##ROWCOUNT;
END

SQL SERVER : How to execute an SP specifed number of time without using loop

I have a scenario wherein i have to execute an SP for specified number of time(number of execution will be mentioned by user) without using loop.
My SP is setting an OUTPUT variable of varchar type. I am willing to insert the output of my SP into a temp table and use it for further processing.
I am unable to modify this SP into function as it contain an Update statement.
Kindly suggest if we can do so without loop.
Whit this solution you do not need an output; #res is your result directly set in a temp table.
CREATE PROCEDURE [dbo].[myStoredProc]
#Counter int,
#params nvarchar(64),
#CreateTable bit
AS
DECLARE #res varchar(64)
IF #CreateTable = 1
BEGIN
IF EXISTS (SELECT 1 FROM dbo.sysobjects WHERE id = object_id(N'[#tempTable]'))
DROP TABLE #tempTable
CREATE TABLE #tempTable ([Res] [nvarchar] (64))
END
SET #res = CONVERT(varchar(64), #Counter)
SET #Counter = #Counter - 1
IF #Counter > 0
exec myStoredProc #Counter, #params, 0
INSERT #tempTable VALUES (#res)
IF #CreateTable = 1
BEGIN
SELECT * FROM #tempTable
DROP TABLE #tempTable
END
GO
DECLARE #o varchar(64)
exec [myStoredProc] 5, '', 1

Resources