2015-07-03 3 views
0

Я новичок в написании триггеров SQL Server. У меня есть таблица под названием USERS, а также еще одна сделанная мной запись: USERS_DELTA. Разница между двумя: USERS_DELTA имеет один дополнительный столбец под названием change_type.Триггер INSERT, вызывающий проблемы

Вот схема таблицы:

USERS стол:

CREATE TABLE [dbo].[TDR_Users] 
(
    [objectGUID] [varbinary](50) NOT NULL, 
    [distinguishedName] [nvarchar](255) NOT NULL, 
    [adForest] [nvarchar](50) NULL, 
    [adDomain] [nvarchar](50) NULL, 
    [accountExpires] [datetime] NULL, 
    [adminCount] [int] NULL, 
    [cn] [nvarchar](64) NULL, 
    [company] [nvarchar](64) NULL, 
    [description] [nvarchar](448) NULL, 
    [displayName] [nvarchar](256) NULL, 
    [division] [nvarchar](256) NULL, 
    [employeeID] [nvarchar](16) NULL 
) 

И USERS_DELTA стол:

CREATE TABLE [dbo].[TDR_Users] 
(
    [objectGUID] [varbinary](50) NOT NULL, 
    [distinguishedName] [nvarchar](255) NOT NULL, 
    [adForest] [nvarchar](50) NULL, 
    [adDomain] [nvarchar](50) NULL, 
    [accountExpires] [datetime] NULL, 
    [adminCount] [int] NULL, 
    [cn] [nvarchar](64) NULL, 
    [company] [nvarchar](64) NULL, 
    [description] [nvarchar](448) NULL, 
    [displayName] [nvarchar](256) NULL, 
    [division] [nvarchar](256) NULL, 
    [employeeID] [nvarchar](16) NULL, 
    [change_Type] [nvarchar](10) NULL 
) 

У меня есть приложение, которое будет создавать записи в таблице USERS. Но то, что я пытаюсь сделать, это захватить вставки в USERS_DELTA. Я написал триггер на USERS таблице:

CREATE TRIGGER [dbo].[TR_INSERTS_DELTAS] 
    ON [dbo].[Users] 
    FOR INSERT 
AS 
    DECLARE @ObjectGUID varbinary(50), @DN varchar(255), @memcount int; 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Get the primary and unique keys from the inserted rows. 
    SELECT @DN=i.distinguishedName FROM inserted i; 
    SELECT @ObjectGUID = i.objectGUID FROM inserted i; 

    -- Check if a row already exists in the TDR_Users_Delta table with those values. 
    SELECT @memcount=COUNT(*) FROM Users 
    WHERE Users.distinguishedName = @DN 
    AND Users.objectGUID = @ObjectGUID ; 
    if(@memcount = 0) 
    BEGIN 
     INSERT INTO [dbo].[Users_Delta] 
     (
      [objectGUID], 
      [distinguishedName], 
      [adForest], 
      [adDomain], 
      [accountExpires], 
      [adminCount], 
      [cn] , 
      [company], 
      [description], 
      [displayName], 
      [division], 
      [employeeID], 
      [change_type] 
     ) 

     VALUES 
     (
      INSERTED.[objectGUID], 
      INSERTED.[distinguishedName], 
      INSERTED.[adForest], 
      INSERTED.[adDomain], 
      INSERTED.[accountExpires], 
      INSERTED.[adminCount], 
      INSERTED.[cn] , 
      INSERTED.[company], 
      INSERTED.[description], 
      INSERTED.[displayName], 
      INSERTED.[division], 
      INSERTED.[employeeID], 
      'Add'   
     ); 

    END 
END 
GO 

Когда я выполняю этот триггер, я получаю следующее сообщение об ошибке:

Msg 4104, Level 16, State 1, Procedure TR_INSERTS_DELTAS, Line 94
The multi-part identifier "Inserted.objectGUID" could not be bound.

Msg 4104, Level 16, State 1, Procedure TR_INSERTS_DELTAS, Line 95
The multi-part identifier "INSERTED.distinguishedName" could not be bound.

Msg 4104, Level 16, State 1, Procedure TR_INSERTS_DELTAS, Line 96
The multi-part identifier "INSERTED.adForest" could not be bound.

Msg 4104, Level 16, State 1, Procedure TR_INSERTS_DELTAS, Line 97
The multi-part identifier "INSERTED.adDomain" could not be bound.

Msg 4104, Level 16, State 1, Procedure TR_INSERTS_DELTAS, Line 98
...

Что я делаю неправильно? :(

+0

Просьба игнорировать имя в схеме таблицы. Я знаю, что говорит TDR_USERS Я уже исправил его на своем конце, но ошибка все еще сохраняется. Подумайте о чем-то в коде триггера. – user5078178

+1

У вашего триггера есть ** ОСНОВНАЯ ** ошибка в том, что вы, кажется, предполагаете, что она будет называться ** один раз за строка ** - это ** не ** случай. Триггер будет срабатывать ** один раз за оператор **, поэтому, если ваши инструкции 'INSERT' влияют на 25 строк, вы получите триггер, запускаемый ** один раз **, но тогда 'Inserted' будет содержать 25 строк. Какая из этих 25 строк выберете здесь ваш код? SELECT @ DN = i.distinguish edName FROM вставил i; '- он не детерминирован - вы получите одну строку и проигнорируете все 24 других! Для этого нужно переписать триггер! –

+0

Сделать комментарий marc_s другим способом. Подумайте, что таблица истории не является дельта-таблицей. Поэтому всегда добавляйте строку при каждом изменении. Это означает, что для таблицы истории потребуется другой первичный ключ, такой как идентификатор сотрудника и дата изменения GetDate(). Вам никогда не понадобится знать первичный ключ заранее в концепции таблицы истории. Все мои самые лучшие и самые длительные и самые стабильные проекты с базой данных с самым высоким уровнем имеют нулевые триггеры в них. –

ответ

1

Я думаю, вам просто нужно положить отборное с таблицей в вместо использования inserted.x для обозначения вставки.

CREATE TRIGGER [dbo].[TR_INSERTS_DELTAS] 
    ON [dbo].[Users] 
    FOR INSERT 
AS 
DECLARE @ObjectGUID varbinary(50), @DN varchar(255), @memcount int; 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 

    SET NOCOUNT ON; 

    -- Get the primary and unique keys from the inserted rows. 
    SELECT @DN=i.distinguishedName FROM inserted i; 
    SELECT @ObjectGUID = i.objectGUID FROM inserted i; 

    -- Check if a row already exists in the TDR_Users_Delta table with those values. 
    SELECT @memcount=COUNT(*) FROM Users 
    WHERE Users.distinguishedName = @DN 
    AND Users.objectGUID = @ObjectGUID ; 
    if(@memcount = 0) 
    BEGIN 
     INSERT INTO [dbo].[Users_Delta] 
     (
      [objectGUID], 
      [distinguishedName], 
      [adForest], 
      [adDomain], 
      [accountExpires], 
      [adminCount], 
      [cn] , 
      [company], 
      [description], 
      [displayName], 
      [division], 
      [employeeID], 
      [change_type] 
     ) 

     select 
      INSERTED.[objectGUID], 
      INSERTED.[distinguishedName], 
      INSERTED.[adForest], 
      INSERTED.[adDomain], 
      INSERTED.[accountExpires], 
      INSERTED.[adminCount], 
      INSERTED.[cn] , 
      INSERTED.[company], 
      INSERTED.[description], 
      INSERTED.[displayName], 
      INSERTED.[division], 
      INSERTED.[employeeID], 
      'Add' 
From inserted 
    END 
END 
GO 
+0

Вы должны удалить эти две строки: 'SELECT @ DN = i.distinguishedName FROM insert i; SELECT @ObjectGUID = i.objectGUID FROM вставлен i; 'поскольку они действительно ничего не делают, и они ** терпят неудачу **, если' вставленный' имеет более одной строки .... –