Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine Old primary key in a SQL Trigger

I've done this before somewhere I'm sure of it!

I have a SQL Server 2000 table that I need to log changes to fields on updates and inserts into a second Logging table. A simplified version of the structure I'm using is below:

MainTable
ID varchar(10) PRIMARY KEY
DESCRIPTION varchar(50)

LogTable
OLDID varchar(10)
NEWID varchar(10)

For any other field something like this would work great:

Select i.DESCRIPTION As New, d.DESCRIPTION As Old 
From Inserted i
LEFT JOIN Deleted d On i.ID=d.ID

...But obviously the join would fail if ID was changed.

I cannot modify the Tables in way, the only power I have in this database is to create a trigger.

Alternatively is there someone who can teach me time travelling and I'll go back into the past and ask myself back then how I did this? Cheers :)


Edit:

I think I need to clarify a few things here. This is not actually my database, it is a pre-existing system that I have almost no control of, other than writing this trigger.

My question is how can I retrieve the old primary key if said primary key was changed. I don't need to be told that I shouldn't change the primary key or about chasing up foreign keys etc. That's not my problem :)

like image 542
keith Avatar asked Mar 04 '09 06:03

keith


People also ask

Can a primary key be dated?

A basic database-design principle is that a primary key must always be unique. And because SQL Server can't differentiate between datetime values that are within a narrow range, you must never use a datetime column as a primary key in SQL Server.

How do you find the primary key constraint?

A primary key constraint depicts a key comprising one or more columns that will help uniquely identify every tuple/record in a table. Properties : No duplicate values are allowed, i.e. Column assigned as primary key should have UNIQUE values only. NO NULL values are present in column with Primary key.

In which trigger both new and old data can be accessed?

Additionally, for row trigger, the statements in a trigger action have access to column values (new and old) of the current row being processed by the trigger.


3 Answers

DECLARE @OldKey int, @NewKey int;

SELECT @Oldkey = [ID] FROM DELETED;
SELECT @NewKey = [ID] FROM INSERTED;

This only works if you have a single row. Otherwise you have no "anchor" to link old and new rows. So check in your trigger for > 1 in INSERTED.

like image 194
gbn Avatar answered Sep 21 '22 00:09

gbn


Is it possible to assume that the INSERTED and DELETED tables presented to you in a trigger are guaranteed to be in the same order?

like image 25
Chris KL Avatar answered Sep 17 '22 00:09

Chris KL


I don't think it's possible. Imagine if you have 4 rows in the table:

1  Val1
2  Val2
3  Val3
4  Val4

Now issue the following update:

UPDATE MainTable SET
ID = CASE ID WHEN 1 THEN 2 WHEN 2 THEN 1 ELSE ID END
Description = CASE ID WHEN 3 THEN 'Val4' WHEN 4 THEN 'Val3' ELSE Description END

Now, how are you going to distinguish between what happened to rows 1 & 2 and what happened to rows 3 & 4. And more importantly, can you describe what's different between them? All of the stuff that tells you which columns have been updated won't help you.

If it's possible in this case that there's an additional key on the table (e.g. Description is UNIQUE), and your update rules allow it, you could write the trigger to prevent simultaneous updates to both keys, and then you can use whichever key hasn't been updated to correlate the two tables.

like image 37
Damien_The_Unbeliever Avatar answered Sep 17 '22 00:09

Damien_The_Unbeliever