3

SQL Server triggers allow access to two special tables. INSERTED - with the "after" values and DELETED with the "before" values.

Where are these stored?. Are they present in tempdb or in the same database as the table being acted upon?

Martin Smith
  • 438,706
  • 87
  • 741
  • 845
Navin
  • 31
  • 1
  • There isn't a whole lot of information available on the technical details of magic tables in SQL Server. [This page](https://technet.microsoft.com/en-us/library/ms366343(v=sql.105).aspx) talks about Internal Tables though, which all of the magic table documentation suggests they are stored. @Barmar, I believe OP is talking about [this feature](https://stackoverflow.com/questions/851189/what-are-the-magic-tables-available-in-sql-server-2000) in sql server 2000+ – JNevill Dec 05 '17 at 18:11
  • 1
    Why do you think you need to know these implementation details? They are available in that statement but not outside that – Hans Kesting Dec 05 '17 at 18:20

2 Answers2

5

In versions prior to SQL Server 2005 these tables were read from the transaction log when needed.

Since SQL Server 2005 the rows making up the inserted and deleted pseudo tables for after triggers are both stored in the version store (always in pages in tempdb- these pages may or may not exist in memory).

You can see this quite clearly from the below (ran in a DB with both snapshot isolation and RCSI off)

CREATE TABLE T1 (X BINARY(10));

GO

--B = Before
INSERT INTO T1
VALUES     (0xBBBBBBBBBBBBBBBBBBBB); 

GO

CREATE TRIGGER TR ON T1 AFTER UPDATE
AS
    PRINT 'Trigger called'

GO

DECLARE @mtsn INT 

SELECT @mtsn = ISNULL(MAX(transaction_sequence_num), 0)
FROM   sys.dm_tran_version_store
WHERE  database_id = DB_ID();    

UPDATE T1
SET    X = 0xAAAAAAAAAAAAAAAAAAAA;    --A = After

SELECT transaction_sequence_num,
       version_sequence_num,
       record_image_first_part,
       CASE
         WHEN CHARINDEX(0xBBBBBBBBBBBBBBBBBBBB, record_image_first_part) > 0
           THEN 'Before'
         WHEN CHARINDEX(0xAAAAAAAAAAAAAAAAAAAA, record_image_first_part) > 0
           THEN 'After'
       END
FROM   sys.dm_tran_version_store
WHERE  database_id = DB_ID()
       AND transaction_sequence_num > @mtsn;


DROP TABLE T1 

Which returns something like

enter image description here

Martin Smith
  • 438,706
  • 87
  • 741
  • 845
0

It's crazy talk. Those tables exists in memory* for the scope of the transaction.

Using triggers is just bad enough don't try to mess with the INSERTED and DELETED tables. If you want to it badly you can, inside the trigger, fill another (temporary?) table with it's data.

Triggers are considered anti-pattern in almost any case it's just not a plain log. In general you can use the data fired the trigger in first place and keep a concise and easy to maintain business logic.

*in memory: Most of times SQL Engine will try to let everything in RAM memory, if for any reason it needs more memory there are avaiable pages it will start to use the disk by the mean of the tempBD but it's entirely transparent and out of your control.

Edit

Martin Smith answer is an excellent one. I know something similar can be done for temp tables but never tried it for triggers tables. I just want to point implementing anything requires direct manipulation of objects like that can raise suspicious of implementantion going in the wrong direction.

Here some sources for my "rant" against (bad use of) triggers

Are database triggers evil?

When are database triggers bad?

jean
  • 4,159
  • 4
  • 31
  • 52
  • Nothing wrong with triggers if you don't put to much logic in the trigger. I usually stick to using it to log or quickly cancel a transaction based on business logic. I avoid having one trigger kick off another and its very useful. – benjamin moskovits Dec 05 '17 at 19:36
  • SQL Server triggers are not anti-pattern. Its like calling a seat belt anti-pattern. Otherwise the answer is correct. – benjamin moskovits Dec 05 '17 at 19:37
  • @benjaminmoskovits putting business logic in the DB is very anti-pattern, using triggers are a (probably) signal of anti-pattern. There are ok uses for triggers like logs and somethimes you do need to put BL in the DB side for performance but it must handled with caution and cannot become a project pattern, never. – jean Dec 06 '17 at 09:42
  • @benjaminmoskovits Note SQL world is full of deprecated, anti-pattern, bad uses like triggers, cursors, use of imperative/procedural paradigma instead of functional/data set and implicit joins – jean Dec 06 '17 at 09:46
  • I really don't want to get into a debate but please do not put triggers in the same category as cursors. While SQL Server Audit has mostly replaced the use of triggers as a audit feature I found that sometimes there is no better way to prevent 'bad' things from happening then by using triggers. Of course if developers wrote perfect code and uses did not make mistakes (like dropping prices by 99 percent instead of 9 percent) triggers would be unnecessary. – benjamin moskovits Dec 06 '17 at 23:59