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!

Conditional INSERT Trigger 1

Status
Not open for further replies.

LMGroup

MIS
Apr 10, 2006
85
CA
I'm using SQL Server 2005, trying to create a conditional trigger that will fire when one of 2 status codes are entered. Once they are entered, I need it to get all the records from the PrintItems table that have the same job number and also have an MCC code and generate records in a 3rd table based on those. I'm not sure if I should be using the WHILE statement or some other method to search the PrintItems table or if I've got the whole thing muddled up. The @ItemImps formula has not yet been determined.

Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Trigger_DigiCost]
   ON  [dbo].[JobStatus1] 
   AFTER INSERT
AS 
IF Inserted.StatusCode in (57098,60599)
BEGIN
	WHILE CT_PrintItems.JobN=Inserted.JobN AND CT_PrintItems.RunMCCN > 0
	BEGIN
		SET NOCOUNT ON;

		DECLARE @JOBN INT
		DECLARE @RunMCC INT 
		DECLARE @ItemImps INT
		DECLARE @AICRate DECIMAL
		DECLARE @overs DECIMAL
		DECLARE @copies INT
	
		SELECT @JOBN=Inserted.JobN, @RunMCC=CT_PrintItems.RunMCCN, @overs=((CT_PrintItems.Qty * OpenJob.OversAllowed)/100), @ItemImps='TBD', @AICRate=MatlCostCntr.AICRate

		FROM Inserted
			INNER JOIN OpenJob ON OpenJob.JobN=Inserted.JobN
			INNER JOIN CT_PrintItems ON CT_PrintItems.JobN=Inserted.JobN
			INNER JOIN MatlCostCntr ON MatlCostCntr.MccN=CT_PrintItems.RunMCCN

		INSERT INTO dbo.JobMaterial(JobMaterial.JobN, JobMaterial.MccN, JobMaterial.MatlQuantity, JobMaterial.Employee, JobMaterial.Shift, 
			JobMaterial.TransDate, JobMaterial.TransTime, JobMaterial.Unit, JobMaterial.AICCost, JobMaterial.UpdateDate, JobMaterial.LastChanged, 
			JobMaterial.ChangedBy)
		VALUES (@JOBN, @RunMCC, @ItemImps, 999, 1, GetDate(), CURRENT_TIMESTAMP, @AICRate, (@ItemImps * @AICRate), GetDate(), GetDate(), 'digicost')

	END
END
GO

Thanks in advance for any advice or help!
 
Based on what I see, there are lots of mistakes, and probably is an over-complication of what is needed. Again.... based on what I see.

I think the trigger you are looking for is this:

Code:
CREATE TRIGGER [dbo].[Trigger_DigiCost]
   ON  [dbo].[JobStatus1] 
   AFTER INSERT
AS 
BEGIN
  INSERT 
  INTO    dbo.JobMaterial(
              JobN, 
              MccN, 
              MatlQuantity, 
              Employee, 
              Shift, 
              TransDate, 
              TransTime, 
              Unit, 
              AICCost, 
              UpdateDate, 
              LastChanged, 
              ChangedBy)
  SELECT   Inserted.JobN, 
           CT_PrintItems.RunMCCN, 
           'TBD', 
           999,
           1,
           GetDate(),
           CURRENT_TIMESTAMP,
           MatlCostCntr.AICRate,
           MatlCostCntr.AICRate * CT_PrintItems.Qty * OpenJob.OversAllowed / 100, 
           GetDate(), 
           GetDate(), 
           'digicost'
  FROM     Inserted
           INNER JOIN OpenJob 
             ON OpenJob.JobN=Inserted.JobN
           INNER JOIN CT_PrintItems 
             ON CT_PrintItems.JobN=Inserted.JobN
           INNER JOIN MatlCostCntr 
             ON MatlCostCntr.MccN=CT_PrintItems.RunMCCN
  WHERE    Inserted.StatusCode In (57098,60599)
           And CT_PrintItems.RunMCCN > 0
END
GO

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
Thanks for replying so quickly. I thought it was looking a little complicated. Will this insert multiple records into JobMaterial is there are multiple records for the job in PrintItems? I guess I better check it out.
 
If there are... then it will.

As always, I encourage vigorous testing before putting any code in to production.

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
I figured out what the required formulae are. Now it doesn't like the code again. I hate those "could not be bound" errors. I know they're coming from the way I set the variables. Do I have to embed everything into the SELECT statement? (I modified the code to turn it into a query and look at a test job on the test database so I could see what would happen before I put all the calculations into the trigger!)


Code:
DECLARE @overs DECIMAL
DECLARE @copies DECIMAL
DECLARE @origs INTEGER
DECLARE @imps INTEGER

SET @overs =((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100)
SET @copies = (CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((@overs + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((@overs + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((overs + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END)
SET @origs = (CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END)
SET @imps = (CASE WHEN CT_PrintItems.PgRec > 0 THEN
		CASE WHEN ((@origs + CT_PrintItems.Setup) % CT_PrintItems.Up > 0) THEN
			(FLOOR((@origs + CT_PrintItems.Setup)/CT_PrintItems.Up) + 1) * @copies * CT_PrintItems.PgRec
		ELSE
			((@origs + CT_PrintItems.Setup)/CT_PrintItems.Up) * @copies * CT_PrintItems.PgRec
		END
		ELSE
			@copies * @origs
		END)

  SELECT   OpenJob.JobN, 
           CT_PrintItems.RunMCCN, 
           @imps,
           999,
           1,
           GetDate(),
           Cast(Replace(Convert(varchar,GetDate(),108),':','') as int),
           MatlCostCntr.AICRate,
           MatlCostCntr.AICRate * @imps, 
           GetDate(), 
           GetDate(), 
           'digicost'
  FROM     OpenJob 
           INNER JOIN CT_PrintItems 
             ON CT_PrintItems.JobN=OpenJob.JobN
           INNER JOIN MatlCostCntr 
             ON MatlCostCntr.MccN=CT_PrintItems.RunMCCN
  WHERE    OpenJob.JobN=632439
           And CT_PrintItems.RunMCCN > 0
 
Let's look at this line:

Code:
SET @overs =((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100)

You get the error:

[red]The multi-part identifier "CT_PrintItems.Qty" could not be bound.[/red]

This is because you are trying to use data from the CT_PrintItems table without specifying the table. There's no from clause so SQL doesn't know where to go to get that data.

Ok... so I know what you're thinking... and it would probably be a mistake.

You're probably thinking, I'll just add a from clause to get it to work. In fact, you could probably get it to work, but it would be the wrong approach. You see, when you write trigger code, you absolutely MUST think in sets. Specifically, your code must accommodate multiple rows simultaneously.

The trigger you are writing is an insert trigger, right?

Well, if you had an insert that looked like this:

Code:
Insert Into YourTable(Column1, Column2)
Select Column1, Column2
From   SomeOtherTable

It's possible to get multiple rows being inserted simultaneously. Even if you think there will only ever be 1 row inserted at a time (because that's how things are right now), you cannot predict the future and you could end up with faulty code that doesn't "break" for 6 months or more. What's worse is that it would silently fail and also silently mess up your data.

Whew... sorry about the rant. I'm passionate about data (which probably makes me weird).

Anyway... the best way to handle this situation is to basically put the calculations for the variables directly in to the select clause of the bottom query. I know it will make the query super ugly to read, but it will perform better and (more importantly) accommodate multiple rows and not silently fail some time in the future.

Does this make sense?

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
A straight up copy/replace produced this query:

Code:
  SELECT   OpenJob.JobN, 
           CT_PrintItems.RunMCCN, 
           (CASE WHEN CT_PrintItems.PgRec > 0 THEN
		CASE WHEN (((CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END) + CT_PrintItems.Setup) % CT_PrintItems.Up > 0) THEN
			(FLOOR(((CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END) + CT_PrintItems.Setup)/CT_PrintItems.Up) + 1) * (CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END) * CT_PrintItems.PgRec
		ELSE
			(((CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END) + CT_PrintItems.Setup)/CT_PrintItems.Up) * (CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END) * CT_PrintItems.PgRec
		END
		ELSE
			(CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END) * (CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END)
		END),
           999,
           1,
           GetDate(),
           Cast(Replace(Convert(varchar,GetDate(),108),':','') as int),
           MatlCostCntr.AICRate,
           MatlCostCntr.AICRate * (CASE WHEN CT_PrintItems.PgRec > 0 THEN
		CASE WHEN (((CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END) + CT_PrintItems.Setup) % CT_PrintItems.Up > 0) THEN
			(FLOOR(((CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END) + CT_PrintItems.Setup)/CT_PrintItems.Up) + 1) * (CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END) * CT_PrintItems.PgRec
		ELSE
			(((CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END) + CT_PrintItems.Setup)/CT_PrintItems.Up) * (CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END) * CT_PrintItems.PgRec
		END
		ELSE
			(CASE WHEN CT_PrintItems.PgRec > 0 THEN
			CT_PrintItems.Qty
		WHEN (CT_PrintItems.PgRec = 0 AND CT_PrintItems.Up > 0) THEN
			CASE WHEN ((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) % CT_PrintItems.Up) > 0 then
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up) + 1
			ELSE
				FLOOR((((CT_PrintItems.Qty * OpenJob.OversAllowed) / 100) + CT_PrintItems.Qty + CT_PrintItems.Setup) / CT_PrintItems.Up)
			END
		END) * (CASE WHEN CT_PrintItems.Format = "Signature" THEN
			CT_PrintItems.Pages/2
		ELSE
			CT_PrintItems.Pages
		END)
		END), 
           GetDate(), 
           GetDate(), 
           'digicost'
  FROM     OpenJob 
           INNER JOIN CT_PrintItems 
             ON CT_PrintItems.JobN=OpenJob.JobN
           INNER JOIN MatlCostCntr 
             ON MatlCostCntr.MccN=CT_PrintItems.RunMCCN
  WHERE    OpenJob.JobN=632439
           And CT_PrintItems.RunMCCN > 0

Don't forget to add the inserted table back in before you put this in the trigger.

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
It makes perfect sense :) I hate messy code but hate messed up data even more. I thought the variables would make things easier to deal with. Oh well. The data itself is much more important and I'll be the only one looking at the code. I started working with triggers about 2 months ago. Before that, the queries I wrote were fairly basic. Some looked (and performed) impressive but weren't that difficult. I just need to start wrapping my head around the data set mentality. I'm glad you were able to grasp what I was trying to do. It seemed so muddled in my mind that I didn't think anyone would get it. I truly appreciate your help and explanations AND rant! lol Thank you!
 
George said:
I'm passionate about data (which probably makes me weird)

It also makes you a great asset to TT... and a person who I am proud to know.

:)


Just my 2¢

"What the captain doesn't realize is that we've secretly replaced his Dilithium Crystals with new Folger's Crystals."

--Greg
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top