Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

MULTIROW UPDATE TRIGGER WITH SP 1

Status
Not open for further replies.

mapfax

Technical User
Apr 23, 2002
29
0
0
GB
I am going round in circles with this, can someone point me in the right direction. I am not sure if I am approaching this the correct way.

I have a table with dates, e.g. received, acknowledged, closed. I am trying to calculate the business days using a stored procedure which works for 1 record but is not working for multirow updates (DTS daily import routine appx 40,000 records). Getting the error: Server Msg 512, Level 16, State1 subquery returned more than 1 value.

I think correlated subqueries might solve my problem but I can't figure out the syntax for the trigger to handle 2 date parameters and pass them to the procedure for all the rows that are updated. I acknowledge that the trigger is poorly written but I have hit a brick wall so please be gentle!

Thanks in advance.
----------------------------

CREATE TRIGGER [PostcardDays] ON [tblSubComments]
FOR INSERT, UPDATE
AS
DECLARE @bdays INT
DECLARE @dtFrom CHAR(20)
DECLARE @dtTo CHAR(20)

SET DATEFIRST 1

--CALCULATE BUSINESS DAYS BETWEEN RAISED AND ACKNOWLEDGED
IF UPDATE (dtPostcardSent)
--I AM HAVING DIFFICULTY FIGURING OUT A FIX FOR BELOW
SELECT @dtFrom = (SELECT dtSubCaseReceived FROM inserted)
SELECT @dtTo = (SELECT dtPostCardSent FROM inserted)
SELECT @dtFrom = CONVERT(CHAR(20), @dtFrom, 103) --UK
SELECT @dtTo = CONVERT(CHAR(20), @dtTo, 103) --UK

--PASS DATE PARAMETERS TO STORED PROCEDURE
EXEC busdays @dtFrom, @dtTo, @bdays OUTPUT

--UPDATE TABLE WITH TOTAL NUMBER OF BUSINESS DAYS RETURNED
UPDATE t SET
LPI_1 = @bdays
FROM tblsubcomments AS t INNER JOIN inserted AS i
ON t.subcaseid = i.subcaseid

---------------------------

CREATE PROCEDURE Busdays @dtFrom CHAR(20), @dtTo CHAR(20), @bdays INT OUTPUT

AS
DECLARE @from_dt DATETIME,
DECLARE @to_dt DATETIME,
DECLARE @days INT,
DECLARE @dp INT,
DECLARE @cnt INT

SET @from_dt = CONVERT(DATETIME, @dtFrom, 103)
SET @to_dt = CONVERT(DATETIME, @dtTo, 103)
SET @bdays=0
SET @cnt=0
SET @days=DATEDIFF(d,@from_dt,@to_dt)

--COUNT BUSINESS DAYS AS MON - FRI
WHILE @cnt <= @days
BEGIN
SET @dp=DATEPART(dw,DATEADD(day,@cnt,@from_dt))
IF @dp NOT IN (6, 7)
BEGIN
SET @bdays=@bdays+1
SET @cnt=@cnt+1
END
ELSE
SET @cnt=@cnt+1
END

 
Instead of stored procedure, write function. Then you can easily modify UPDATE to properly handle multirow updates.

Also: @dtFrom and @dtTo dates are converted to char(20) back and forth. This is not necessary.

------
Math problems? Call 0800-[(10x)(13i)^2]-[sin(xy)/2.362x]
 
Sorry I neglected to mention I am using version 7 if you are referring to UDF's. I presume that means I cannot use a function, correct?

ps. I had problems with the date datatypes going over as nvarchar. When I used datetime they seemed to be passed in the wrong format. It seems to work for what I need for now (single row update), but I will look at this again later.
 
Correct.

We'll skip cursors for obvious reasons :X

Another idea: create "helper" calendar table containing at least two columns:

- calDate smalldatetime primary key (calendar day)
- isBusinessDay tinyint (1-business day, 0-not)

... then populate it with all possible days (within reasonable range of course). Mark Mon-Fri dates as business days, also unmark holidays if necessary (good extra option). After that use single multirow UPDATE with join on helper table and SUM(isBusinessDay).

------
Math problems? Call 0800-[(10x)(13i)^2]-[sin(xy)/2.362x]
 
Hi

I actually had a calendar table tblDWPeriod courtesy of but wasn't sure how to implement that idea. I have changed the trigger code but still can't figure how to evaluate multirows, works with 1 record. Is it done with a subquery, if so, how?

--CALCULATE NO OF DAYS BETWEEN COMMENT RAISED AND COMMENT ACKNOWLEDGED BY POSTCARD
IF UPDATE (dtPostcardSent)
--SELECT @dtFrom = (SELECT dtSubCaseReceived FROM INSERTED)
--SELECT @dtTo = (SELECT dtPostCardSent FROM INSERTED)
--SELECT @dtFrom = CONVERT(CHAR(20), @dtFrom, 103)
--SELECT @dtTo = CONVERT(CHAR(20), @dtTo, 103)
--EXEC busdays @dtFrom, @dtTo, @Bdays OUTPUT
--SELECT dtSubCaseReceived, dtPostcardSent FROM inserted

UPDATE L
SET LPI_1 =
(SELECT COUNT(bitworkingday)
FROM tblDWPeriod
WHERE dtsActivityDate
BETWEEN i.dtSubCaseReceived
AND i.dtPostcardSent
AND bitworkingday = 1)
FROM tblsubcomments AS L INNER JOIN inserted AS i
ON L.subcaseid = i.subcaseid
 
I've just changed it to this (as per BOL's multirow trigger)

IF UPDATE (dtPostcardSent)
UPDATE tblsubcomments
SET LPI_1 =
(SELECT COUNT(bitworkingday)
FROM tblDWPeriod
WHERE dtsActivityDate
BETWEEN dtSubCaseReceived
AND dtPostcardSent
AND bitworkingday = 1)
WHERE subcaseid IN
(SELECT subcaseid FROM inserted)

Seems to be working, will need to test further. Would this be correct for multirow processing?
 
What was wrong with previous version? I think you already made it, assuming that subcaseid is unique/primary key that can be only inserted but not updated.

------
Math problems? Call 0800-[(10x)(13i)^2]-[sin(xy)/2.362x]
 
I'm not sure, I've just changed it back and it is now working after checking out your note, whereas before I was sure I was getting the same multirow error.

I also didn't have a PK just an identity. I had just added a PK to test this and have removed again. But both versions now work with or w/o a PK?

Here is my table, ps how do you add these code snippets in their own little window on this forum?

CREATE TABLE [dbo].[tblSubComments] (
[SubCaseID] [int] IDENTITY (1, 1) NOT NULL ,
[SubCaseNo] [char] (20) NOT NULL ,
[CaseID] [char] (20) NULL ,
[SvcSecReceived] [int] NOT NULL ,
[SvcSecAssigned] [int] NULL ,
[OffrAssigned] [char] (35) NULL ,
[Category1] [char] (4) NULL ,
[Category2] [int] NULL ,
[Category3] [int] NULL ,
[PNSOE] [char] (1) NULL ,
[CommentText] [text] NULL ,
[dtSubCaseReceived] [datetime] NULL ,
[SubCaseReferred] [char] (35) NULL ,
[dtSubCaseReferred] [datetime] NULL ,
[dtPostcardSent] [datetime] NULL ,
[dtHoldingLtrSent] [datetime] NULL ,
[dtAgreedResponseReq] [datetime] NULL ,
[dtResponded] [datetime] NULL ,
[ImprovementAction] [char] (254) NULL ,
[dtSubCaseClosed] [datetime] NULL ,
[SubCaseNote] [char] (254) NULL ,
[au_user] [char] (35) NULL ,
[au_last_upd] [datetime] NULL ,
[LPI_1] [int] NULL ,
[LPI_2] [int] NULL ,
[LPI_3] [int] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
 
OK, subcaseid is identity. Looks fine. Unique column (PK) is necessary to link inserted table ("data after") with physical table ("data before") in trigger code.

For "frames" around code snippets: click on "Process TGML" link above "Submit Post" button :X

------
Math problems? Call 0800-[(10x)(13i)^2]-[sin(xy)/2.362x]
 
Thanks for your assistance...v much appreciate :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top