-- 1. INSERT and UPDATE trigger on referencing table.
-- Disallow any insert or update if the foreign key title_id 
-- here in the referencing table titleauthor does not match
-- the primary key title_id in the referenced table titles.
CREATE TRIGGER INS_UPD_titleauthor
    ON titleauthor
    FOR INSERT, UPDATE
AS
-- Do any rows exist in the inserted table that do not have 
-- a matching ID in titles?
IF EXISTS
    (SELECT * FROM inserted WHERE inserted.title_id NOT IN
        (SELECT titles.title_id FROM titles) )
    BEGIN
    RAISERROR('No matching title found. Statement will be
aborted.', 16, 1)
    ROLLBACK TRAN
    END
GO

-- 2. If primary key in referenced table titles is changed,
-- update any rows in titleauthor to the DEFAULT value.
-- This implements ON UPDATE SET DEFAULT. Notice this trigger could
-- be easily changed to set the column to NULL instead of DEFAULT,
-- which would implement ON UPDATE SET NULL.
CREATE TRIGGER UPD_titles
    ON titles 
    FOR UPDATE 
AS
    DECLARE @counter int
    IF UPDATE(title_id)
        BEGIN
        UPDATE titleauthor
        SET titleauthor.title_id=DEFAULT
        FROM titleauthor, deleted
        WHERE titleauthor.title_id=deleted.title_id
    
        SET @COUNTER=@@ROWCOUNT
        -- If the trigger resulted in modifying rows of
         -- titleauthor, raise an informational message
        IF (@counter > 0)
            RAISERROR('%d rows of titleauthor were updated to
DEFAULT title_id as a result of an update to titles table',
10, 1, @counter)
        END
GO

-- 3. DELETE of referenced table titles will set to NULL referencing
--  titleauthor rows  a
CREATE TRIGGER DelCascadeTrig
    ON titles
    FOR DELETE
AS
    DECLARE @counter int
    UPDATE titleauthor
    SET title_id = NULL
    FROM titleauthor, deleted
    WHERE titleauthor.title_id=deleted.title_id
    SET @counter=@@ROWCOUNT
    
    IF (@counter > 0)
        RAISERROR('%d rows of titleauthor were were set to a
NULL title_id as a result
of a delete to the titles table', 10, 1, @counter)
GO

/* Make changes to structure of titles and titleauthor tables */


ALTER TABLE titles NOCHECK CONSTRAINT ALL
go
ALTER TABLE sales NOCHECK CONSTRAINT ALL
go
ALTER TABLE titleauthor NOCHECK CONSTRAINT ALL
go
ALTER TABLE titleauthor DROP CONSTRAINT UPKCL_taind
go
ALTER TABLE titleauthor ALTER COLUMN title_id tid NULL
go
ALTER TABLE titleauthor ADD CONSTRAINT UPKCL_taind UNIQUE (au_id, title_id)
go
ALTER TABLE roysched NOCHECK CONSTRAINT ALL
go
ALTER TABLE publishers NOCHECK CONSTRAINT ALL
go

-- Add one dummy row to titles
INSERT titles VALUES ('AA0000','No Such Title','unknown','0',0,0,0,0,'No notes','Jun 12 1996 12:00AM')
go
-- Make that dummy row the default title_id in titleauthor
ALTER TABLE titleauthor ADD CONSTRAINT Def_title DEFAULT 'AA0000' FOR title_id
go

/* Now test out the triggers */

-- Invalid insert to titleauthor
INSERT titleauthor (au_id,title_id,au_ord,royaltyper) VALUES ('172-32-1176','XXXXXX',1,100)
go
select @@rowcount
go

-- Valid insert to titleauthor
INSERT titleauthor (au_id,title_id,au_ord,royaltyper) VALUES ('172-32-1176','BU1032',1,100)
go
select @@rowcount
go


-- Invalid multirow update to titleauthor
UPDATE titleauthor SET title_id = substring(title_id,1,4)+convert(char(1),au_ord)
go

-- Valid multirow update to titleauthor
UPDATE titleauthor SET title_id = title_id
go

-- Show that delete will set  to NULL.   Find titleauthor rows for title TC7777.
-- Update the title_id in those rows to NULL
SELECT * FROM titleauthor where title_id='PS2091'
  OR title_id IS  NULL
DELETE titles where title_id='PS2091'
SELECT * FROM titleauthor where title_id='PS2091'
  OR title_id IS  NULL
go

-- Show that an update to the Primary Key of the 
-- referenced table will cause all of the Foreign Keys 
-- that had previously referenced it to be 
-- set to the DEFAULT title_id, which is 'AA0000'
DECLARE @au_id varchar(11)
SELECT @au_id=au_id FROM titleauthor where title_id='TC4203'
SELECT au_id,title_id FROM titleauthor where au_id=@au_id
UPDATE titles set title_id='WW9999' where title_id='TC4203'
SELECT au_id,title_id FROM titleauthor where au_id=@au_id
go


CREATE TRIGGER UpdCascadeTrig1
    ON titles
    AFTER UPDATE
AS
    DECLARE @num_affected int, @title_id varchar(11),
        @old_title_id varchar(11)
    SET @num_affected=@@ROWCOUNT
    IF (@num_affected=0)    -- No rows affected, so nothing to do
        RETURN

    IF UPDATE(title_id)
        BEGIN
        IF (@num_affected=1)
            BEGIN
            SELECT @title_id=title_id FROM inserted
            SELECT @old_title_id=title_id FROM deleted
            UPDATE titleauthor
            SET title_id=@title_id
            FROM titleauthor
            WHERE titleauthor.title_id=@old_title_id
            SELECT @num_affected=@@ROWCOUNT
            RAISERROR ('Cascaded update in titles of Primary Key
                from %s to %s to %d rows in titleauthor', 10, 1,
                @old_title_id, @title_id, @num_affected)
            END
        ELSE
            BEGIN
            RAISERROR ('Cannot update multiple Primary Key values
                in a single statement due to Cascading Update
                trigger in existence.', 16, 1)
            ROLLBACK TRANSACTION
            END
        END
GO
CREATE TRIGGER UpdCascadeTrig2
    ON titles
    FOR UPDATE
AS
    DECLARE @num_distinct int, @num_affected int,
        @title_id varchar(11)
    SET @num_affected=@@ROWCOUNT
    IF (@num_affected=0)    -- No rows affected, so nothing to do
        RETURN

    IF UPDATE(title_id)
        BEGIN
        SELECT @num_distinct=COUNT(DISTINCT title_id) FROM inserted
        IF (@num_distinct=1)
            BEGIN
            -- Temporarily make it return just one row
            SET ROWCOUNT 1 
            SELECT @title_id=title_id FROM inserted
            SET ROWCOUNT 0     -- Revert ROWCOUNT back
            UPDATE titleauthor
            SET titleauthor.title_id=@title_id
            FROM titleauthor, deleted
            WHERE titleauthor.title_id=deleted.title_id
            SELECT @num_affected=@@ROWCOUNT
            RAISERROR ('Cascaded update of Primary Key to value in
                titles to %d rows in titleauthor', 10, 1,
                @title_id, @num_affected)
            END
        ELSE
            BEGIN
            RAISERROR ('Cannot cascade a multirow update that
                changes title_id to multiple different values.', 16, 1)
            ROLLBACK TRANSACTION
            END
        END

Published in: SQL
Download

Related snippets