SQL Server trigger double values at first insert - sql-server

I created a trigger on Ames.Details to fire Ames.Sqlclass but when I insert the data into Ames.Details, for example ‘Ken’, ’Math’, 20, ’In’, it shows me 40 marks in Sqlclass.Syntax** below
CREATE SCHEMA Ames
GO
CREATE TABLE Ames.SqlClass
(
Name NVARCHAR(50),
Subject NVARCHAR(50),
Mark INT
)
GO
CREATE TABLE Ames.Details
(
Name NVARCHAR(50),
Subject NVARCHAR(50),
Mark INT,
Status NVARCHAR(20)
)
GO
CREATE TRIGGER SQlDetails
ON Ames.Details
AFTER INSERT
AS
BEGIN
DECLARE #st INT, #Namesql NVARCHAR(50),
#Subject NVARCHAR(50), #pt INT, #Status NVARCHAR(20)
SELECT
#Namesql = i.Name, #Subject = i.subject,
#pt = i.mark, #Status = I.Status
FROM
inserted AS I
IF NOT EXISTS (SELECT * FROM Ames.SqlClass
WHERE #Namesql = Name AND #Subject = Subject)
BEGIN
INSERT INTO Ames.sqlClass (Name, Subject, Mark)
VALUES (#Namesql, #Subject, #pt)
END
SELECT #st = Mark
FROM ames.SqlClass
WHERE #Namesql = Name AND #Subject = Subject
BEGIN
IF #Status = 'IN'
BEGIN
SET #st = #st + #pt
END
IF #Status = 'Out'
BEGIN
SET #st = #st - #pt
END
UPDATE Ames.SqlClass
SET Mark = #st
WHERE Name = #Namesql
END
END

Related

SQL Server stored procedure expects parameter which was not supplied

CREATE TABLE [dbo].[review]
(
[id] [int] IDENTITY(1,1) NOT NULL,
[uID] [varchar](6) NOT NULL,
[pID] [int] NOT NULL,
[email] [nvarchar](255) NOT NULL,
[review] [nvarchar](3000) NULL,
[refURL] [nvarchar](2083) NOT NULL,
[refID] [nvarchar](100) NOT NULL,
[cDate] [datetime] NOT NULL,
CONSTRAINT [PK_review]
PRIMARY KEY CLUSTERED ([id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[review]
ADD CONSTRAINT [DF_review_uID] DEFAULT (LEFT(NEWID(), (6))) FOR [uID]
GO
ALTER TABLE [dbo].[review]
ADD CONSTRAINT [DF_review_cDate] DEFAULT (GETDATE()) FOR [cDate]
GO
I wrote this stored procedure:
ALTER PROCEDURE [dbo].[spReview]
#id INT = 0,
#uID VARCHAR(6),
#pID INT = 0,
#email NVARCHAR(255),
#review NVARCHAR(3000),
#refURL NVARCHAR(2083),
#refID NVARCHAR(100),
#cDate DATETME = NULL,
#OPERATION NVARCHAR(50) = ''
AS
IF #OPERATION = 'Insert'
BEGIN
DECLARE #inserted TABLE ([uID] VARCHAR(6));
INSERT INTO review ([pID], [email], [review], [refURL], [refID])
OUTPUT INSERTED.[uID] INTO #inserted
VALUES (#pID, #email, #review, #refURL, #refID)
SELECT *
FROM #inserted
END
ELSE IF #OPERATION = 'Delete'
BEGIN
DELETE FROM review
WHERE id = #id
END
ELSE IF #OPERATION = 'Update'
BEGIN
UPDATE review
SET pID = #pID,
email = #email,
review = #review,
refURL = #refURL,
refID = #refID
WHERE id = #id
END
uID : left(newid(),(6)) and cDate : getdate() set default value
DECLARE #return_value int
EXEC #return_value = [dbo].[spReview]
#id = N'29',
#OPERATION = N'Delete'
SELECT 'Return Value' = #return_value
GO
I get this error when I execute the delete query:
Procedure or function 'spReview' expects parameter '#uID', which was not supplied
I tried debugging, I can't figure out where I made a mistake. Where did I make a mistake?
ELSE IF #OPERATION = 'Delete'
BEGIN
DELETE FROM review
WHERE id = #id
END
Just waiting for '#id' parameter, it doesn't need '#uID'
This is your code:
ALTER PROCEDURE [dbo].[spReview]
#id INT = 0,
#uID VARCHAR(6),
#pID INT = 0,
#email NVARCHAR(255),
#review NVARCHAR(3000),
#refURL NVARCHAR(2083),
#refID NVARCHAR(100),
#cDate DATETME = NULL,
#OPERATION NVARCHAR(50) = ''
For every parameter without an "=" sign, you need to provide a value. In your case, it means that you need to provide at least the following parameters:
#uID VARCHAR(6),
#email NVARCHAR(255),
#review NVARCHAR(3000),
#refURL NVARCHAR(2083),
#refID NVARCHAR(100),
So either you provide these parameters when calling the procedure, or you rewrite your procedure such that you don't need these parameters.
As mentioned, multiple times, this should be 3 separate SPs, this way you only need the parameters you need for that operation:
CREATE PROC dbo.Review_Delete #id int AS
BEGIN
DELETE FROM dbo.review
WHERE id = #id;
END;
GO
CREATE PROC dbo.Review_Insert #pID int, #email nvarchar(255), #review nvarchar(3000), #RefURL nvarchar(2083), #RefID nvarchar(100) AS
BEGIN
INSERT INTO dbo.review(pID, email, review, refURL, refID)
OUTPUT inserted.uID --This seems like an OUTPUT parameter might be better, as you insert a single row
VALUES(#pID, #Email, #review, #RefURL, #RefID);
END;
GO
CREATE PROC dbo.Review_Update #id int, #pID int, #email nvarchar(255), #review nvarchar(3000), #RefURL nvarchar(2083), #RefID nvarchar(100) AS
BEGIN
UPDATE dbo.review
SET pID = #pID,
email = #email,
review = #review,
refURL = #refURL,
refID = #refID
WHERE ID = #ID;
END;
GO
Notice I never declare the parameter #cDate, as you don't use it once in your SP.
If, for some really odd reason, you really need to have one SP, then create the others and call them dynamically; only passing the parameters you passed to the "master" SP to the "children". I, however, don't recommend this one and you should just call them correct one in the first place:
CREATE PROC Review_Operation #Operation char(6), --No need for this to be an nvarchar, or 50 characters, delete, insert and update are all 6 characters in length and contain no unicode characters
#ID int = NULL, #pID int = NULL, #email nvarchar(255) = NULL, #review nvarchar(3000) = NULL, #RefURL nvarchar(2083) = NULL, #RefID nvarchar(100) = NULL AS
BEGIN
--Because they are all NULL we're going to use Dynamic SQKL to only pass parameters will a value to force the error
DECLARE #SQL nvarchar(MAX),
#Params nvarchar(MAX);
IF #Operation = 'Delete' BEGIN
SET #SQL = N'EXEC Review_Delete ' + CASE WHEN #ID IS NOT NULL THEN N'#id' ELSE N'' END + N';';
SET #Params = N'#ID int';
EXEC sp_executesql #SQL, #Params, #ID;
END ELSE IF #Operation = 'Insert' BEGIN
SET #SQL = N'EXEC Review_Insert ' + STUFF(CASE WHEN #pID IS NOT NULL THEN N',#pID = #pID' ELSE N'' END +
CASE WHEN #email IS NOT NULL THEN N',#email = #email' ELSE N'' END +
CASE WHEN #review IS NOT NULL THEN N',#review = #review' ELSE N'' END +
CASE WHEN #RefURL IS NOT NULL THEN N',#RefURL = #RefURL' ELSE N'' END +
CASE WHEN #RefID IS NOT NULL THEN N',#RefID = #RefID' ELSE N'' END,1,1,N'') + N';';
SET #Params = N'#pID int, #email nvarchar(255), #review nvarchar(3000), #RefURL nvarchar(2083), #RefID nvarchar(100)';
EXEC sp_executesql #SQL, #Params, #pID, #email, #review, #RefURL, #RefID;
END ELSE IF #Operation = 'Update' BEGIN
SET #SQL = N'EXEC Review_Update ' + STUFF(CASE WHEN #ID IS NOT NULL THEN N',#ID = #ID' ELSE N'' END +
CASE WHEN #pID IS NOT NULL THEN N',#pID = #pID' ELSE N'' END +
CASE WHEN #email IS NOT NULL THEN N',#email = #email' ELSE N'' END +
CASE WHEN #review IS NOT NULL THEN N',#review = #review' ELSE N'' END +
CASE WHEN #RefURL IS NOT NULL THEN N',#RefURL = #RefURL' ELSE N'' END +
CASE WHEN #RefID IS NOT NULL THEN N',#RefID = #RefID' ELSE N'' END,1,1,N'') + N';';
SET #Params = N'#id int,#pID int, #email nvarchar(255), #review nvarchar(3000), #RefURL nvarchar(2083), #RefID nvarchar(100)';
EXEC sp_executesql #SQL, #Params, #ID, #pID, #email, #review, #RefURL, #RefID;
END;
END;
GO
Procedure or function 'spReview' expects parameter '#uID', which was
not supplie
This means you are not passing a value to #uID when you are calling the stored procedure. You need to pass a valid parameter during SP execution.
You have couple of issues with your procedure creation and calling.
Creation: You declared a parameter #uID VARCHAR(6) with no use in the Procedure. You can remove the line #uID VARCHAR(6) from the procedur's parameter definition section.
Calling: you defined parameter - #email, #review, #refURL, #refID in the procedure but not providing values to them while calling the procedure. You should call the procedure as below-
DECLARE #return_value int
EXEC #return_value = [dbo].[spReview]
#id = N'29',
#email = N'abc#yahoo.com',
#OPERATION = N'Delete',
#email = 'test#yahoo.com',
#review = 'abc',
#refURL = 'xyz',
#refID = '1' -- ID should be a INT but declared as NVARCHAR
SELECT 'Return Value' = #return_value
GO
Though not really recommended as stated above, you can provide default values, and in fact you have default values set for #id, #pID, and #OPERATION.
Of course, if you default #uID to null, you MUST account for that in the actual procedure to make sure a null #uID won't cause other errors.
create proc [dbo].[spReview]
#id INT = 0,
#uID VARCHAR(6) = null,
#pID INT = 0,
#email NVARCHAR(255),
#review NVARCHAR(3000),
#refURL NVARCHAR(2083),
#refID NVARCHAR(100),
#cDate DATETME = NULL,
#OPERATION NVARCHAR(50) = ''
AS
if #uID is null
begin
-- do something here when #uID is null.
end

Check transaction committed and if so return a value

I want to insert a new user (Email address) into a table of users. If successful (no duplicate), insert basic configurations for new user to other tables, and return some data to client. If not successful, receive relevant notification in dataset in C# project.
Here is sample code so you can easily comment on it
ALTER PROCEDURE [dbo].[CreateUser]
#Email nvarchar(256),
#Password nvarchar(256)
AS
BEGIN
declare #UserID uniqueidentifier;
declare #ConfigID uniqueidentifier;
declare #TopMostNode uniqueidentifier;
BEGIN TRANSACTION;
select #UserID = NEWID();
select #ConfigID = newid();
insert into Users (UserID,Email,Password,CurrentConfig)
values(#UserID, #Email, #Password, #ConfigID);
INSERT INTO Configs (ConfigID, OwnerID, DisplayName, LastPrintID)
VALUES (#ConfigID,#UserID, 'Default Config', 1);
COMMIT TRANSACTION
END
That code is almost complete. Just need to add a SELECT to return the new keys. In case of an error, you will get an exception. EG:
ALTER PROCEDURE [dbo].[CreateUser]
#Email nvarchar(256),
#Password nvarchar(256)
AS
BEGIN
declare #UserID uniqueidentifier;
declare #ConfigID uniqueidentifier;
declare #TopMostNode uniqueidentifier;
BEGIN TRANSACTION;
select #UserID = NEWID();
select #ConfigID = newid();
insert into Users (UserID,Email,Password,CurrentConfig)
values(#UserID, #Email, #Password, #ConfigID);
INSERT INTO Configs (ConfigID, OwnerID, DisplayName, LastPrintID)
VALUES (#ConfigID,#UserID, 'Default Config', 1);
COMMIT TRANSACTION
select #UserID UserID, #ConfigID ConfigID;
END
Here is one possibility where you return a recordset with the data you require and a flag to indicate whether the user already existed or not.
alter procedure [dbo].[CreateUser]
(
#Email nvarchar(256)
, #Password nvarchar(256)
)
as
begin
declare #UserID uniqueidentifier, #ConfigID uniqueidentifier, #TopMostNode uniqueidentifier, #UserExists bit = 0;
select #UserID = UserID, #UserExists = 1 from Users where Email = #Email;
if #UserExists = 0 begin
begin transaction;
set #UserID = newid();
set #ConfigID = newid();
insert into Users (UserID, Email, [Password], CurrentConfig)
values (#UserID, #Email, #Password, #ConfigID);
insert into Configs (ConfigID, OwnerID, DisplayName, LastPrintID)
values (#ConfigID, #UserID, 'Default Config', 1);
commit transaction
end
-- Return whether the user already exists or not and the user id
select #UserExists, #UserId
return 0;
end
Another way to return data to the app is using output parameters e.g.
alter procedure [dbo].[CreateUser]
(
#Email nvarchar(256)
, #Password nvarchar(256)
, #UserId uniqueidentifier out
, #UserExists bit out
)
as
begin
declare #ConfigID uniqueidentifier, #TopMostNode uniqueidentifier;
set #UserExists = 0;
select #UserID = UserID, #UserExists = 1 from Users where Email = #Email;
if #UserExists = 0 begin
begin transaction;
set #UserID = newid();
set #ConfigID = newid();
insert into Users (UserID, Email, [Password], CurrentConfig)
values (#UserID, #Email, #Password, #ConfigID);
insert into Configs (ConfigID, OwnerID, DisplayName, LastPrintID)
values (#ConfigID, #UserID, 'Default Config', 1);
commit transaction
end
return 0;
end

When I execute the stored procedure I get an error

When I execute the stored procedure, I get this error:
Msg 8114, Level 16, State 5, Procedure SPXML, Line 158
Error converting data type varchar to numeric.
I'm using a stored procedure and cursor for the first time.
This is my stored procedure:
CREATE PROCEDURE [dbo].[SPXML]
(#CounterStockMaster text,
#CounterStockDetails text,
#CounterStock text)
AS
DECLARE #M0 VARCHAR(100) --EditStatus
DECLARE #M1 VARCHAR(100) --Counter_Code
DECLARE #M2 VARCHAR(100) --Counter_Name
DECLARE #M3 VARCHAR(100) --To Branch_Code
DECLARE #D1 VARCHAR(100) --Project Type
DECLARE #D2 VARCHAR(100) --drpC.Text
DECLARE #D3 VARCHAR(100) --grdGO.Rows[i].Cells["1"].Value
DECLARE #D4 VARCHAR(100) --grdGO.Rows[i].Cells["2"].Value
DECLARE #D5 VARCHAR(100)
DECLARE #C1 VARCHAR(100) --Cnt Code
DECLARE #C2 VARCHAR(100) --Item
DECLARE #C3 VARCHAR(100) --Qty
BEGIN
DECLARE #CNTNo VARCHAR(100)
DECLARE #idoc INT
DECLARE #INDate Datetime
DECLARE #Branch_Code NUMERIC(18,0)
DECLARE #ItemCode NUMERIC(18,0)
DECLARE #ItemQty NUMERIC(18,3)
DECLARE #PurRate NUMERIC(18,2)
DECLARE #SaleRate NUMERIC(18,2)
DECLARE #MRP NUMERIC(18,2)
DECLARE #PurDate DATETIME
DECLARE #Batch_No VARCHAR(50)
DECLARE #ExpiryDate DATETIME
DECLARE #MultiMRP BIT
BEGIN TRANSACTION
SET DATEFORMAT dmy
SET #MultiMRP = (Select ISNULL(Multiple_Mrp,0) from [Company])
EXEC sp_xml_preparedocument #idoc OUTPUT, #CounterStockMaster
DECLARE GINMasterCursor CURSOR FOR
SELECT * FROM OPENXML (#idoc, '/CSMASTER/ID',1)
WITH (M0 VARCHAR(100), M1 VARCHAR(100), M2 VARCHAR(100),M3 VARCHAR(100))
OPEN GINMasterCursor
FETCH NEXT FROM GINMasterCursor INTO #M0,#M1,#M2,#M3
IF #M0='T' ---Edit Mode TRUE
BEGIN --- Reversing the Item Stock for the Editing Sales START
SET #CNTNo = #M1
DECLARE GInDetailCursor CURSOR FOR
SELECT Counter_Stock_Code,Item_Code,Item_Qty,Branch_Code From [CntDetails]
WHERE Counter_Stock_Code = #CNTNo AND Branch_Code=#M3
OPEN GInDetailCursor
FETCH NEXT FROM GInDetailCursor INTO #CNTNo,#ItemCode,#ItemQty,#Branch_Code
WHILE ##FETCH_STATUS=0
BEGIN
IF #MultiMRP = 0
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL - #ItemQty , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #ItemCode and Type_Code = 0 and Branch_Code = #M3
ELSE
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL - #ItemQty , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #ItemCode and Item_MRP = #MRP and Type_Code = 0 and Branch_Code = #M3
FETCH NEXT FROM GInDetailCursor INTO #CNTNo,#ItemCode,#ItemQty,#Branch_Code
END
CLOSE GInDetailCursor
DEALLOCATE GInDetailCursor
END --- Reversing the Item Stock for the Editing GO END
ELSE
BEGIN
SET #CNTNo = (SELECT ISNULL(MAX(Counter_Stock_Code)+1,1) FROM [Counter Stock Master] where Branch_Code = #M3)
END
INSERT INTO [CntMaster]
(Counter_Stock_Code,Counter_Stock_Date,Branch_Code)
VALUES
(#CNTNo, #INDate, #M3)
CLOSE GINMasterCursor
DEALLOCATE GINMasterCursor
EXEC sp_xml_removedocument #idoc
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #CounterStockDetails
-- Execute a SELECT statement using OPENXML rowset provider.
DECLARE GInDetailsCursor CURSOR FOR
SELECT * FROM OPENXML (#idoc, '/CSDETAILS/ID',1)
WITH ( D1 VARCHAR(100), D2 VARCHAR(100), D3 VARCHAR(100), D4 VARCHAR(100))
OPEN GInDetailsCursor
FETCH NEXT FROM GInDetailsCursor INTO #D1,#D2,#D3,#D4
WHILE ##FETCH_STATUS = 0
BEGIN
IF #D1='A' or #D1='D' --For ProjectType ==> Departmental Stores
BEGIN
SET #D2 = #CNTNo
INSERT INTO [CntDetails]
(Counter_Stock_Code,Item_Code,Item_Qty,Branch_Code)
VALUES
(#D2, #D3, #D4, #M3)
IF #MultiMRP = 0
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
ELSE
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
END
FETCH NEXT FROM GInDetailsCursor INTO #D1,#D2,#D3,#D4
END
CLOSE GInDetailsCursor
DEALLOCATE GInDetailsCursor
***[EXEC sp_xml_removedocument #idoc ----------------------- "I get this error from this line"][1]***
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #CounterStock
-- Execute a SELECT statement using OPENXML rowset provider.
DECLARE CSCursor CURSOR FOR
SELECT * FROM OPENXML (#idoc, '/CounterStock/ID',1)
WITH ( D1 VARCHAR(100), D2 VARCHAR(100), D3 VARCHAR(100), D4 VARCHAR(100))
OPEN CSCursor
FETCH NEXT FROM CSCursor INTO #D1,#D2,#D3,#D4
WHILE ##FETCH_STATUS = 0
BEGIN
IF #D1='A' or #D1='D' --For ProjectType ==> Departmental Stores
BEGIN
INSERT INTO [CntStock]
(Conter_Code,Item_Code,Item_Qty)
VALUES
(#D2, #D3, #D4)
IF #MultiMRP = 0
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
ELSE
UPDATE [ITEM] SET ITEM_BAL = ITEM_BAL + #D4 , Transfer_flag=2, Ascend_flag=1 WHERE Item_Code = #D3 and Type_Code = 0 and Branch_Code = #M3
END
FETCH NEXT FROM CSCursor INTO #D1,#D2,#D3,#D4
END
CLOSE CSCursor
DEALLOCATE CSCursor
EXEC sp_xml_removedocument #idoc
SELECT #CNTNo
COMMIT TRANSACTION
END
GO
I tried many times but i didn't solve this problem.
Does anyone have any suggestions?
Error here:
INSERT INTO [CntStock]
(Conter_Code,Item_Code,Item_Qty)
VALUES
(#D2, #D3, #D4) ---DECLARE #D4 VARCHAR(100) ---What is the type of 'Item_Qty' column in CntStock table,Is it numeric,You are assigning varchar to numberic field.
Try changing the type of #D4

sp_send_dbmail just partially working

Ive got the next query, and the problem is that it work for mail 1 and 2, but not to 3 and 4 (and 3,4 exists in the select table). some idea?
[I looked for help and i guess that the right way to do it, it's cursor, but I did not make it also with cursor).
ALTER PROCEDURE [DBMAIL].[Mail_FOR_USER]
#Mail_1 NVARCHAR (100),
#Mail_2 NVARCHAR (100),
#Mail_3 NVARCHAR (100),
#Mail_4 NVARCHAR (100)
AS
BEGIN TRY
EXEC sp_configure 'show advanced', 1;
RECONFIGURE;
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'Database Mail XPs', 1;
RECONFIGURE
DECLARE
#ID INT=1,
#RN INT,
#xCol XML,
#XML_Creation_Date DATETIME ,
#File_Path NVARCHAR(200),
#USER_1 NVARCHAR(100),
#USER_2 NVARCHAR(100),
#USER_3 NVARCHAR(100),
#USER_4 NVARCHAR(100),
#Recipients_List NVARCHAR(MAX);
---============================================
WHILE #ID<= (SELECT MAX (ID) FROM Report_FOR_Users)
BEGIN
SELECT [ID], [RN], [xCol], [XML_Creation_Date], [File_Path], [USER_1], [USER_2], [USER_3], [USER_4]
FROM Report_FOR_Users WHERE ID=#ID
SET #File_Path= (SELECT File_Path FROM Report_FOR_Users WHERE ID=#ID)
SET #Mail_1= CASE
WHEN (SELECT USER_1 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_1
END
SET #Mail_2= CASE
WHEN (SELECT USER_2 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_2
END
SET #Mail_3= CASE
WHEN (SELECT USER_3 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_3
END
SET #Mail_4= CASE
WHEN (SELECT USER_4 FROM Report_FOR_Users WHERE ID=#ID) IS NULL THEN ' '
ELSE #Mail_4
END
SET #Recipients_List= #Mail_1+';'+#Mail_2+';'+#Mail_3+';'+#Mail_4
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SEmailProfile',
#recipients = #Recipients_List,
#body = 'ola?',
#subject = 'Hopa',
#file_attachments = #File_Path;
SET #ID=#ID+1
END
ALTER PROCEDURE [DBMAIL].[Mail_FOR_USER]
(
#Mail_1 NVARCHAR(100),
#Mail_2 NVARCHAR(100),
#Mail_3 NVARCHAR(100),
#Mail_4 NVARCHAR(100)
)
AS BEGIN
SET NOCOUNT ON;
DECLARE
#UserID INT
, #File_Path NVARCHAR(200)
, #USER_1 NVARCHAR(100)
, #USER_2 NVARCHAR(100)
, #USER_3 NVARCHAR(100)
, #USER_4 NVARCHAR(100)
DECLARE cur CURSOR FAST_FORWARD READ_ONLY LOCAL FOR
SELECT ID, File_Path
FROM dbo.Report_FOR_Users
OPEN cur
FETCH NEXT FROM cur INTO #UserID, #File_Path
WHILE ##FETCH_STATUS = 0 BEGIN
SELECT
#USER_1 = CASE WHEN USER_1 IS NOT NULL THEN #Mail_1 END
, #USER_2 = CASE WHEN USER_2 IS NOT NULL THEN #Mail_2 END
, #USER_3 = CASE WHEN USER_3 IS NOT NULL THEN #Mail_3 END
, #USER_4 = CASE WHEN USER_4 IS NOT NULL THEN #Mail_4 END
FROM dbo.Report_FOR_Users
WHERE ID = #ID
SELECT #Recipients_List = STUFF((
SELECT ';' + val
FROM (
VALUES (#USER_1), (#USER_2), (#USER_3), (#USER_4)
) t(val)
WHERE t.val IS NOT NULL
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SEmailProfile',
#recipients = #Recipients_List,
#body = 'ola?',
#subject = 'Hopa',
#file_attachments = #File_Path
FETCH NEXT FROM cur INTO #UserID, #File_Path
END
CLOSE cur
DEALLOCATE cur
END

Insert/Update Stored Procedure with Output Parameter

Background:
I have a series of stored procedures that inserts one new record into 5 tables (all have a one-to-one relationship). Each stored procedure creates a unique ID for the related table. The last stored procedure adds all of those unique IDs into the last table (to allow for an INNER JOIN to retrieve all information across the individual tables).
I have created an additional stored procedure (let's call it spWrapper) that calls the 4 individual stored procedures (mentioned above). I would like to use the spWrapper to both insert and update a record. The current (insert) spWrapper only inserts a record; the 5 unique IDs are declared as OUTPUT parameters. My T-SQL knowledge is still basic and I am not sure how OUTPUT parameters affect stored procedures.
The current spWrapper code (shortened example):
ALTER PROCEDURE [dbo].[spWrapper]
-- Return values
#idAddress INT = NULL OUTPUT,
#idDetermination INT = NULL OUTPUT,
#idLegalDescription INT = NULL OUTPUT,
#idAddresses_LegalDescriptions_Determinations INT = NULL OUTPUT,
#idLOMC INT = NULL OUTPUT,
-- [Table#1] parameters
#Street VARCHAR(50) = NULL,
#City VARCHAR(50) = NULL,
#State VARCHAR(2) = NULL,
#ZipCode5 VARCHAR(5) = NULL,
#ZipCode4 VARCHAR(4) = NULL,
#GISCode VARCHAR(15) = NULL
AS
SET NOCOUNT OFF
SET ROWCOUNT 0
-- =================================
-- Declare and initialize variables
-- =================================
DECLARE #Error INT,
#RC INT,
#Trancount INT,
#Message VARCHAR(255)
SELECT #Error = 0,
#RC = 0,
#Trancount = ##TRANCOUNT,
#Message = NULL
-- ==========================================
-- Insert record into [Table#1]
-- ==========================================
IF #idAddress IS NULL
BEGIN
IF #Trancount = 0 BEGIN TRANSACTION
EXEC #RC = [spTable#1]
#idLogin = #idLogin,
#idAddress = #idAddress,
#Street = #Street,
#State = #State,
#City = #City,
#ZipCode5 = #ZipCode5,
#ZipCode4 = #ZipCode4,
#GISCode = #GISCode
SELECT #Error = ##ERROR
IF #RC <> 0 OR #Error <> 0
BEGIN
IF #Trancount = 0 ROLLBACK TRANSACTION
SELECT #Message = 'dbo.spWrapper: Error inserting record into [Table#1]'
GOTO lbl_abort
END
END
IF #Trancount = 0 COMMIT TRANSACTION
The current spTable#1 code
ALTER PROCEDURE [spTable#1]
#idLogin INT,
#idAddress INT = NULL OUTPUT,
#Street VARCHAR(50),
#State CHAR(2),
#City VARCHAR(50),
#ZipCode5 CHAR(5),
#ZipCode4 CHAR(4),
#GisCode VARCHAR(15)
IF #TranCount = 0 BEGIN TRANSACTION
IF #idAddress IS NULL
BEGIN
INSERT [dbo].[Table#1]
(Street,
[State],
City,
ZipCode5,
ZipCode4,
GisCode,
InsertedidLogin,
InsertedDate)
VALUES
(#Street,
#State,
#City,
#ZipCode5,
#ZipCode4,
#GisCode,
#idLogin,
GETDATE())
SELECT #Error = ##ERROR,
#RC = ##ROWCOUNT,
#idAddress = SCOPE_IDENTITY()
IF #Error <> 0 OR #RC <> 1
BEGIN
IF #TranCount = 0 ROLLBACK TRANSACTION
SELECT #Message = 'spTable#1: Error inserting record into [Table#1]'
GOTO lbl_abort
END
END
My main question:
With the unique ID set as an OUTPUT parameter, can I insert an existing ID to call an UPDATE portion of spTable#1 (and subsequently spWrapper)? OR can I declare those unique IDs (ie: not as an OUTPUT parameter)?
Proposed change
CREATE PROCEDURE [dbo].[spWrapper]
#idLOMC INT = NULL
DECLARE #idAddress INT,
#idLegalDescription INT,
#idDetermination INT,
#idCommunity INT,
#idFirm INT,
#idCounty INT,
#idFloodZone INT,
#Error INT,
#RC INT,
#Trancount INT,
#Message VARCHAR(255)
SELECT #idAddress = NULL,
#idLegalDescription = NULL,
#idDetermination = NULL,
#Error = 0,
#RC = 0,
#Trancount = ##TRANCOUNT,
#Message = NULL
/* Lookup idAddress, idLegalDescription, idDetermination */
IF #idLOMC IS NOT NULL
BEGIN
SELECT #idAddress = A.idAddress, #idLegalDescription = LD.idLegalDescription, #idDetermination = D.idDetermination
FROM [Table#2] L
INNER JOIN [Table#5] ALD
ON L.idAddresses_LegalDescriptions_Determinations = ALD.idAddresses_LegalDescriptions_Determinations
INNER JOIN [Table#1] A
ON ALD.idAddress = A.idAddress
INNER JOIN [Table#3] LD
ON ALD.idLegalDescription = LD.idLegalDescription
INNER JOIN [Table#4] D
ON ALD.idDetermination = D.idDetermination
WHERE L.idLOMC = #idLOMC
IF ##ROWCOUNT = 0
BEGIN
SELECT #Message = 'dbo.spWrapper: Invalid idLOMC'
GOTO lbl_abort
END
END
/* Insert record into [Table#1] */
IF #idAddress IS NULL
BEGIN
IF #Trancount = 0 BEGIN TRANSACTION
EXEC #RC = [spTable#1]
#idLogin = #idLogin,
#idAddress = #idAddress OUTPUT,
#Street = #Street,
#State = #State,
#City = #City,
#ZipCode5 = #ZipCode5,
#ZipCode4 = #ZipCode4,
#GisCode = #GisCode
SELECT #Error = ##ERROR
IF #RC <> 0 OR #Error <> 0
BEGIN
IF #Trancount = 0 ROLLBACK TRANSACTION
SELECT #Message = 'spWrapper: Error inserting record into [Table#1]'
GOTO lbl_abort
END
END
/* Update record into [Table#1] */
ELSE
BEGIN
IF #Trancount = 0 BEGIN TRANSACTION
EXEC #RC = [spTable#1]
#idLogin = #idLogin,
#idAddress = #idAddress,
#Street = #Street,
#State = #State,
#City = #City,
#ZipCode5 = #ZipCode5,
#ZipCode4 = #ZipCode4,
#GisCode = #GisCode
SELECT #Error = ##ERROR
IF #RC <> 0 OR #Error <> 0
BEGIN
IF #Trancount = 0 ROLLBACK TRANSACTION
SELECT #Message = 'spWrapper: Error updating record in [TspTable#1]'
GOTO lbl_abort
END
END

Resources