Fred Webb
asked on
SQL Trigger with condition
I have a trigger on a table that has serial numbers, and I want to track when someone deletes a serial number from an order or voids the whole order. I have an action flag that if the order is voided I want it to put a V in the action Column and if the serial number is deleted it puts a D in that column. My problem is that that it puts a V in that column for both Voids and Deletes.
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_trigger] ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
---
DECLARE @inserted_ct AS INT
DECLARE @deleted_ct AS INT
--DECLARE @Void_ct AS CHAR(25)
DECLARE @action AS CHAR(3)
DECLARE @a_ACTION AS CHAR(3)
DECLARE @a_CSREP AS CHAR(10)
DECLARE @a_DEX_ROW_ID AS INT
SET @a_CSREP = SYSTEM_USER
SET @inserted_ct = 0
SET @deleted_ct = 0
--SET @Void_ct = 0
SET @inserted_ct = (
SELECT count(*)
FROM inserted
)
SET @deleted_ct = (
SELECT count(*)
FROM deleted
)
IF (EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'V'
,GetDate()
,@a_CSREP
FROM deleted
END
IF(NOT EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted
END
IF @inserted_ct > 0
SET @action = 'I'
--IF @deleted_ct > 0
-- SET @action = 'D'
IF (@inserted_ct > 0)
AND (@deleted_ct > 0)
SET @action = 'U'
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201
-- SELECT *
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_I'
,GetDate()
,@a_CSREP
FROM inserted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
GO
ASKER
Kyle, Thanks for the quick response. So would I replace
IF(NOT EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted
END
With
IF EXISTS (
SELECT
*
FROM
INSERTED I
JOIN
DELETED D ON D.SerialNumber<> I.SerialNumber
-- and i.SerialNumber = 'deleted value' or is null? <Is this line commented out deliberately?>
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted
END
IF(NOT EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted
END
With
IF EXISTS (
SELECT
*
FROM
INSERTED I
JOIN
DELETED D ON D.SerialNumber<> I.SerialNumber
-- and i.SerialNumber = 'deleted value' or is null? <Is this line commented out deliberately?>
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted
END
I've rewritten the query to get rid of unnecessary elements.
I'm not sure what the unique column(s) are for table SOP10201, but my best guess was SOPNUMBE. If that's not right, change the joins below to use the appropriate column(s).
--
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_ trigger]
ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
SET NOCOUNT ON
---
DECLARE @action char(1)
DECLARE @a_CSREP char(10)
SET @a_CSREP = SYSTEM_USER
IF EXISTS(SELECT TOP (1) * FROM inserted)
IF EXISTS(SELECT TOP (1) * FROM deleted)
SET @action = 'U'
ELSE
SET @action = 'I'
ELSE
SET @action = 'D'
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'V'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN inserted i ON
i.SOPNUMBE = d.SOPNUMBE
WHERE d.VOIDSTTS = 1
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN inserted i ON
i.SOPNUMBE = d.SOPNUMBE
WHERE d.VOIDSTTS IS NULL OR d.VOIDSTTS <> 1
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201
-- SELECT *
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_I'
,GetDate()
,@a_CSREP
FROM deleted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
GO
I'm not sure what the unique column(s) are for table SOP10201, but my best guess was SOPNUMBE. If that's not right, change the joins below to use the appropriate column(s).
--
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_
ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
SET NOCOUNT ON
---
DECLARE @action char(1)
DECLARE @a_CSREP char(10)
SET @a_CSREP = SYSTEM_USER
IF EXISTS(SELECT TOP (1) * FROM inserted)
IF EXISTS(SELECT TOP (1) * FROM deleted)
SET @action = 'U'
ELSE
SET @action = 'I'
ELSE
SET @action = 'D'
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'V'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN inserted i ON
i.SOPNUMBE = d.SOPNUMBE
WHERE d.VOIDSTTS = 1
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN inserted i ON
i.SOPNUMBE = d.SOPNUMBE
WHERE d.VOIDSTTS IS NULL OR d.VOIDSTTS <> 1
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201
-- SELECT *
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_I'
,GetDate()
,@a_CSREP
FROM deleted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
GO
ASKER
Scott, thanks for responding, however I am getting an error
Msg 207, Level 16, State 1, Procedure SSG_Audit_SOP10201_trigger , Line 30
Invalid column name 'VOIDSTTS'.
The above one may be caused by the fact that VOIDSTTS is not in the SOP10201 table but in table SOP30200
that is what I used to validate whether the order was voided as that table contains the void status.
IF (EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
Msg 8101, Level 16, State 1, Procedure SSG_Audit_SOP10201_trigger , Line 22
An explicit value for the identity column in table 'SSG_Audit_SOP10201' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Msg 207, Level 16, State 1, Procedure SSG_Audit_SOP10201_trigger
Invalid column name 'VOIDSTTS'.
The above one may be caused by the fact that VOIDSTTS is not in the SOP10201 table but in table SOP30200
that is what I used to validate whether the order was voided as that table contains the void status.
IF (EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
Msg 8101, Level 16, State 1, Procedure SSG_Audit_SOP10201_trigger
An explicit value for the identity column in table 'SSG_Audit_SOP10201' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Sorry, overlooked which table that column was coming from.
As the other error, you really ought to remove the identity property from that column in the audit table. Unfortunately, there's no easy, direct way to do that. But you don't really need an identity column in an audit table.
You could for now instead code specific columns to be inserted into the table:
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_ trigger]
ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
SET NOCOUNT ON
---
DECLARE @action char(1)
DECLARE @a_CSREP char(10)
SET @a_CSREP = SYSTEM_USER
IF EXISTS(SELECT TOP (1) * FROM inserted)
IF EXISTS(SELECT TOP (1) * FROM deleted)
SET @action = 'U'
ELSE
SET @action = 'I'
ELSE
SET @action = 'D'
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'V'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN (
SELECT DISTINCT SOPNUMBE, VOIDSTTS
FROM SOP30200
) AS S ON
S.SOPNUMBE = d.SOPNUMBE
WHERE S.VOIDSTTS = 1
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'D'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN (
SELECT DISTINCT SOPNUMBE, VOIDSTTS
FROM SOP30200
) AS S ON
WHERE S.VOIDSTTS IS NULL OR S.VOIDSTTS <> 1
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
-- SELECT * --( ...column_list... )
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'U_I'
,GetDate()
,@a_CSREP
FROM deleted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
GO
As the other error, you really ought to remove the identity property from that column in the audit table. Unfortunately, there's no easy, direct way to do that. But you don't really need an identity column in an audit table.
You could for now instead code specific columns to be inserted into the table:
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_
ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
SET NOCOUNT ON
---
DECLARE @action char(1)
DECLARE @a_CSREP char(10)
SET @a_CSREP = SYSTEM_USER
IF EXISTS(SELECT TOP (1) * FROM inserted)
IF EXISTS(SELECT TOP (1) * FROM deleted)
SET @action = 'U'
ELSE
SET @action = 'I'
ELSE
SET @action = 'D'
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'V'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN (
SELECT DISTINCT SOPNUMBE, VOIDSTTS
FROM SOP30200
) AS S ON
S.SOPNUMBE = d.SOPNUMBE
WHERE S.VOIDSTTS = 1
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'D'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN (
SELECT DISTINCT SOPNUMBE, VOIDSTTS
FROM SOP30200
) AS S ON
WHERE S.VOIDSTTS IS NULL OR S.VOIDSTTS <> 1
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
-- SELECT * --( ...column_list... )
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'U_I'
,GetDate()
,@a_CSREP
FROM deleted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
GO
ASKER
OK, I got the errors to go away, but now it won't insert Voided or Deleted records but it does the inserted records
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_trigger]
ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
SET NOCOUNT ON
---
DECLARE @action char(1)
DECLARE @a_CSREP char(10)
SET @a_CSREP = SYSTEM_USER
IF EXISTS(SELECT TOP (1) * FROM inserted)
IF EXISTS(SELECT TOP (1) * FROM deleted)
SET @action = 'U'
ELSE
SET @action = 'I'
ELSE
SET @action = 'D'
INSERT INTO SSG_Audit_SOP10201 ( SOPTYPE, SOPNUMBE, LNITMSEQ, CMPNTSEQ, QTYTYPE, SERLTNUM, SERLTQTY, SLTSQNUM, DATERECD, DTSEQNUM, UNITCOST, ITEMNMBR, TRXSORCE,
POSTED, OVRSERLT, BIN, MFGDATE, EXPNDATE, ORIGINAL_DEX_ROW_ID, ACTION, EVENT_DT_TM, GPUSER )
SELECT d.SOPTYPE, d.SOPNUMBE, d.LNITMSEQ, d.CMPNTSEQ, d.QTYTYPE, d.SERLTNUM, d.SERLTQTY, d.SLTSQNUM, d.DATERECD, d.DTSEQNUM, d.UNITCOST, d.ITEMNMBR, d.TRXSORCE,
d.POSTED, d.OVRSERLT, d.BIN, d.MFGDATE, d.EXPNDATE, d.DEX_ROW_ID
,'V'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN (
SELECT DISTINCT SOPNUMBE, VOIDSTTS
FROM SOP30200
) AS S ON
S.SOPNUMBE = d.SOPNUMBE
WHERE S.VOIDSTTS = 1
INSERT INTO SSG_Audit_SOP10201 ( SOPTYPE, SOPNUMBE, LNITMSEQ, CMPNTSEQ, QTYTYPE, SERLTNUM, SERLTQTY, SLTSQNUM, DATERECD, DTSEQNUM, UNITCOST, ITEMNMBR, TRXSORCE,
POSTED, OVRSERLT, BIN, MFGDATE, EXPNDATE, ORIGINAL_DEX_ROW_ID, ACTION, EVENT_DT_TM, GPUSER )
SELECT d.SOPTYPE, d.SOPNUMBE, d.LNITMSEQ, d.CMPNTSEQ, d.QTYTYPE, d.SERLTNUM, d.SERLTQTY, d.SLTSQNUM, d.DATERECD, d.DTSEQNUM, d.UNITCOST, d.ITEMNMBR, d.TRXSORCE,
d.POSTED, d.OVRSERLT, d.BIN, d.MFGDATE, d.EXPNDATE, d.DEX_ROW_ID
,'D'
,GetDate()
,@a_CSREP
FROM deleted d
INNER JOIN (
SELECT DISTINCT SOPNUMBE, VOIDSTTS
FROM SOP30200
) AS S ON
S.SOPNUMBE = d.SOPNUMBE
WHERE S.VOIDSTTS IS NULL OR S.VOIDSTTS <> 1
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
-- SELECT * --( ...column_list... )
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'U_I'
,GetDate()
,@a_CSREP
FROM deleted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201 --( ...column_list... )
SELECT * --( ...column_list... )
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
GO
Those Void/Delete actions are DELETEs or UPDATEs, right? That code uses the "deleted" table, which will be empty for INSERTs, of course.
Sorry, no time now. But check the JOIN results and do normal debugging for missing rows.
Sorry, no time now. But check the JOIN results and do normal debugging for missing rows.
ASKER
Yes Void/Deletes are actually deletes
ASKER
I looked through the code and cant find the problem
ASKER
OK, I had been playing with this all day yesterday, I have Modified the code yet again, I can get it to flag the insert and the delete but not the void
here is the code:
here is the code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[SSG_Audit_SOP10201_trigger] ON [dbo].[SOP10201]
AFTER INSERT
,UPDATE
,DELETE
AS
---
DECLARE @inserted_ct AS INT
DECLARE @deleted_ct AS INT
DECLARE @Void_ct AS INT
DECLARE @action AS CHAR(3)
DECLARE @a_ACTION AS CHAR(3)
DECLARE @a_CSREP AS CHAR(10)
DECLARE @a_DEX_ROW_ID AS INT
SET @a_CSREP = SYSTEM_USER
SET @inserted_ct = 0
SET @deleted_ct = 0
SET @Void_ct = 0
SET @inserted_ct = (
SELECT count(*)
FROM inserted
)
SET @deleted_ct = (
SELECT count(*)
FROM deleted
)
SET @Void_ct = (
SELECT count(*)
FROM SOP30200 S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1))
IF @Void_ct >0
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'V'
,GetDate()
,@a_CSREP
FROM deleted
END
ELSE
IF @Void_ct <= 0
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'D'
,GetDate()
,@a_CSREP
FROM deleted
END
IF @inserted_ct > 0
SET @action = 'I'
--IF @deleted_ct > 0
-- SET @action = 'D'
IF (@inserted_ct > 0)
AND (@deleted_ct > 0)
SET @action = 'U'
--IF (@action = 'D')
--BEGIN
-- INSERT INTO SSG_Audit_SOP10201
-- SELECT *
-- ,'D'
-- ,GetDate()
-- ,@a_CSREP
-- FROM deleted
--END
IF (@action = 'U')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_D'
,GetDate()
,@a_CSREP
FROM deleted
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'U_I'
,GetDate()
,@a_CSREP
FROM inserted
END
IF (@action = 'I')
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'I'
,GetDate()
,@a_CSREP
FROM inserted
END
ASKER
Hello...
You've reverted to the old code. Technically you can never count on that code being accurate as you can a mix of Delete and Void rows in the same trigger.
Hopefully someone else can help you with this.
Hopefully someone else can help you with this.
ASKER
Your code did not work either
I agree. That's why I'm hoping someone else can help you.
ASKER
Well thanks anyway Scott, I may have approach this another way and just bypass attempting to set the void flag within the the trigger and find a way to update it after.
> I have a trigger on a table that has serial numbers
What is the name of that table in your code? if it's SOP10201, then what is SOP30200?
> and I want to track when someone deletes a serial number from an order or voids the whole order
For that, there should be two triggers, one of the orders table, to track when it's voided, and another on order lines table, to track when order line is deleted. Please explain what tables you have for the serial numbers and for the orders.
What is the name of that table in your code? if it's SOP10201, then what is SOP30200?
> and I want to track when someone deletes a serial number from an order or voids the whole order
For that, there should be two triggers, one of the orders table, to track when it's voided, and another on order lines table, to track when order line is deleted. Please explain what tables you have for the serial numbers and for the orders.
ASKER
The SOP10201 is the table that has the trigger on it and it is the serial table, SOP30200 is the history table and adds an entry with the SOPNUMBE from SOP10201 along with setting the VOIDSTTS = 1 if the order was Voided it would be the last entry in the audit table (SSG_Audit_SOP10201). If a serial number or line item was deleted from the order it is not entered into the SOP30200 table. what I am trying to do is differentiate between a voided record and a deleted record.
This code joins the audit table SOPNUMBE to the SOP30200 table which indicates a voided order
IF (EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
This code joins the audit table SOPNUMBE to the SOP30200 table which indicates a voided order
IF (EXISTS (SELECT COUNT(DISTINCT S.SOPNUMBE) AS SOP_COUNT
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
You say that SOP30200 is "history table and adds an entry with the SOPNUMBE from SOP10201 along with setting the VOIDSTTS = 1 if the order was Voided"
Then, if you want to capture the event of the order being voided, it probably makes sense to create the trigger on SOP30200?
Then, you did not say what happens and in which table when the order line is deleted.
You also did not say what events occur in the table of serial numbers when either of these two events takes place.
I.e. you create trigger on the table with the serial numbers, but the changes you want to capture occur in other tables. Usually, we create trigger on the table where the change takes place, i.e. if we delete an order line, then we create on-delete trigger on the table with order lines; if the order is voided, then on-update on the table with the orders that has column "void" which was just changed; and so on.
Then, if you want to capture the event of the order being voided, it probably makes sense to create the trigger on SOP30200?
Then, you did not say what happens and in which table when the order line is deleted.
You also did not say what events occur in the table of serial numbers when either of these two events takes place.
I.e. you create trigger on the table with the serial numbers, but the changes you want to capture occur in other tables. Usually, we create trigger on the table where the change takes place, i.e. if we delete an order line, then we create on-delete trigger on the table with order lines; if the order is voided, then on-update on the table with the orders that has column "void" which was just changed; and so on.
ASKER
<Then, you did not say what happens and in which table when the order line is deleted.>
<You also did not say what events occur in the table of serial numbers when either of these two events takes place.>
If the item has a serial number assigned on the order, the SOPNUMBE (Order Number), Item number, and serial number are added to SOP10201 which is the serial lines table, when the serial number is deleted from the order or changed it is removed from this table and the trigger fires, which is why I am auditing it to see who removed and when it was removed or changed. If the Item has no serial number assigned to it on the SOPNUMBE (Order Number) and the item is removed from the order the trigger does not fire. it track the insert and deletions of serial numbers just fine, and flags inserts with the I flag and deletions with the D flag, but I want it to flag just voids with the V flag. When an order is voided it adds an entry into the SOP30200 with the VOIDSTTS = 1, and will the last entry in the audit table (SSG_Audit_SOP10201) What I was trying to do was compare Item number in SSG_Audit_SOP10201 to the Item number in SOP30200 where the VOIDSTTS = 1 and change that last Deleted record flag from D to V. If I understand you correctly I should have a separate trigger on the SOP30200 table and have that fire on insert and add a record to SSG_Audit_SOP10201, I only want it to add a record if there is a match on SOPNUMBE (Order Number) in the SSG_Audit_SOP10201 and SOP30200 where the VOIDSTTS = 1 Maybe something like
IF (EXISTS (SELECT (DISTINCT S.SOPNUMBE) AS SOP
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'V'
,GetDate()
,@a_CSREP
FROM deleted
END
<You also did not say what events occur in the table of serial numbers when either of these two events takes place.>
If the item has a serial number assigned on the order, the SOPNUMBE (Order Number), Item number, and serial number are added to SOP10201 which is the serial lines table, when the serial number is deleted from the order or changed it is removed from this table and the trigger fires, which is why I am auditing it to see who removed and when it was removed or changed. If the Item has no serial number assigned to it on the SOPNUMBE (Order Number) and the item is removed from the order the trigger does not fire. it track the insert and deletions of serial numbers just fine, and flags inserts with the I flag and deletions with the D flag, but I want it to flag just voids with the V flag. When an order is voided it adds an entry into the SOP30200 with the VOIDSTTS = 1, and will the last entry in the audit table (SSG_Audit_SOP10201) What I was trying to do was compare Item number in SSG_Audit_SOP10201 to the Item number in SOP30200 where the VOIDSTTS = 1 and change that last Deleted record flag from D to V. If I understand you correctly I should have a separate trigger on the SOP30200 table and have that fire on insert and add a record to SSG_Audit_SOP10201, I only want it to add a record if there is a match on SOPNUMBE (Order Number) in the SSG_Audit_SOP10201 and SOP30200 where the VOIDSTTS = 1 Maybe something like
IF (EXISTS (SELECT (DISTINCT S.SOPNUMBE) AS SOP
FROM SOP30200 AS S INNER JOIN
SSG_Audit_SOP10201 AS V ON S.SOPNUMBE = V.SOPNUMBE
WHERE (S.VOIDSTTS = 1)))
BEGIN
INSERT INTO SSG_Audit_SOP10201
SELECT *
,'V'
,GetDate()
,@a_CSREP
FROM deleted
END
It's still indirect. If I understand correctly, besides SOP30200 you probably have the actual table X with the orders, where the order is marked as void, and when that happens, a record is added to SOP30200, probably by an update trigger in X. If this is correct, then the most straightforward is to create update trigger not on SOP30200 but directly on X; or in fact, modify the already existing one by adding INSERT INTO SSG_Audit_SOP10201 to it.
Basing trigger that writes into audit table on another record already existing in the audit table is very convoluted.
If I'm wrong and there's no table X, then "When an order is voided it adds an entry into the SOP30200 with the VOIDSTTS = 1" translates into the following in insert trigger on SOP3200:
insert into SSG_Audit_SOP10201 (..) select 'V',getdate(),@a_csrep
from inserted where VOIDSTTS = 1
Basing trigger that writes into audit table on another record already existing in the audit table is very convoluted.
If I'm wrong and there's no table X, then "When an order is voided it adds an entry into the SOP30200 with the VOIDSTTS = 1" translates into the following in insert trigger on SOP3200:
insert into SSG_Audit_SOP10201 (..) select 'V',getdate(),@a_csrep
from inserted where VOIDSTTS = 1
ASKER
No... SOP30200 is where the order number and line data is inserted when an order is voided
Right, so you create the trigger on it. (in the prev. post when I typed "SOP3200" I meant "SOP30200").
ASKER
Ok, but I only want SOP30200 trigger to do an insert into SSG_Audit_SOP10201 if there is a SOPNUMBE match in both SSG_Audit_SOP10201 and SOP30200 insert table which means that an order with a serial number has been voided not just updated. So if there is an insert on SOP30200 I need a script to compare the SOPNUMBE in SSG_Audit_SOP10201 to SOPNUMBE in SOP30200 insert table which will then add a record into SSG_Audit_SOP10201
You said "when an order is voided it adds an entry into the SOP30200 with the VOIDSTTS = 1". So, if you want to determine if the order was voided, you look at whether the new record being inserted into SOP30200 has VOIDSTTS = 1.
If I understand correctly, you want that done only when the order line of the order being voided had serial number, and you try to identify that by looking at the prior record in the audit table. This is what I say is unstable, i.e. you better not base new audit record on an old audit record. Whether order line had serial number or not is based on the entry in SOP10201, so it's better to find the match of SOP30200 not with SSG_Audit_SOP10201 but with SOP10201 itself.
If I understand correctly, you want that done only when the order line of the order being voided had serial number, and you try to identify that by looking at the prior record in the audit table. This is what I say is unstable, i.e. you better not base new audit record on an old audit record. Whether order line had serial number or not is based on the entry in SOP10201, so it's better to find the match of SOP30200 not with SSG_Audit_SOP10201 but with SOP10201 itself.
ASKER
What makes it unstable? The problem with matching SOP30200 with SOP10201 is that as soon as the order is voided the SOPNUMBE along with the serial is removed from SOP10201thats why I wanted to use SSG_Audit_SOP10201 because that will contain the SOPNUMBE along with the serial that was voided
> What makes it unstable?
The fact that success of your operation will depend on two conditions: (1) order is voided (2) there is a prior record in audit table. While if you make it direct, then there's only (1). Less conditions → less possibilities that something goes wrong → more stability.
> as soon as the order is voided the SOPNUMBE along with the serial is removed from SOP10201
which is the exact place where it makes the most sense to put writing into audit table:
1. check if serial record exists in SOP10201
2. if it does, then
2.1 remove it
2.2 put audit record into SSG_Audit_SOP10201
The fact that success of your operation will depend on two conditions: (1) order is voided (2) there is a prior record in audit table. While if you make it direct, then there's only (1). Less conditions → less possibilities that something goes wrong → more stability.
> as soon as the order is voided the SOPNUMBE along with the serial is removed from SOP10201
which is the exact place where it makes the most sense to put writing into audit table:
1. check if serial record exists in SOP10201
2. if it does, then
2.1 remove it
2.2 put audit record into SSG_Audit_SOP10201
ASKER
>The fact that success of your operation will depend on two conditions: (1) order is voided (2) there is a prior record in audit table.
I already have a trigger on SOP10201 that fires and enters a record into the audit table, when the order is fulfilled (Insert), if a serial number is deleted (Delete), and if the order is voided (Delete) so there will always be a record in the audit table because of the first insert.
I already have a trigger on SOP10201 that fires and enters a record into the audit table, when the order is fulfilled (Insert), if a serial number is deleted (Delete), and if the order is voided (Delete) so there will always be a record in the audit table because of the first insert.
There are many ways to do the same thing, what I say is just a suggestion. If it was my solution, I would add to that trigger on SOP10201 that you mentioned the code that would also write to the audit table - but certainly you can do it your way.
With that said, are you still experiencing some problem? it's now quite a long thread, so if you still need help, please re-clarify where we are at and what exactly does not work as expected.
With that said, are you still experiencing some problem? it's now quite a long thread, so if you still need help, please re-clarify where we are at and what exactly does not work as expected.
ASKER
Thanks Vadimr for you suggestions, I will attempt to write the code for what I want to do and will either post any issues I encounter or close this thread.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
No viable solution was provided
IF EXISTS (
SELECT
*
FROM
INSERTED I
JOIN
DELETED D ON D.SerialNumber<> I.SerialNumber
-- and i.SerialNumber = 'deleted value' or is null?
)
-- set your d
)