【问题标题】:INSERT INTO View, INSTEAD OF Trigger, Identity, multiple tables?插入视图,代替触发器,身份,多个表?
【发布时间】:2013-03-01 15:35:10
【问题描述】:

这里是我的表(Entier = Integer // Caractère long variable = Varchar):

http://i.stack.imgur.com/lNjyy.jpg

我创建了一个视图 V_Enterprise(idContact, phoneNumber, email, name, city, adress)

我尝试在该视图上创建一个触发器以允许用户更新视图:

CREATE TRIGGER test
ON V_Entreprise
INSTEAD OF INSERT
AS 
DECLARE @T_ContactId INT
BEGIN
    INSERT INTO T_Contact 
    SELECT i.phoneNumber, i.email
    FROM Inserted i 

    SELECT @T_ContactId = @@IDENTITY

    INSERT INTO T_Entreprise
    SELECT @T_ContactId, i.name, i.city, i.adress
    FROM Inserted i 
END ;

正如我所料,它适用于简单的插入,但是当我一次添加几行时,它会失败,因为@T_ContactId 只包含第一个 id。有人可以帮我解决吗?我觉得我应该使用 INNER JOIN 插入,但我不知道如何处理它。

【问题讨论】:

标签: sql-server view triggers


【解决方案1】:

好的,您永远不应该将标量变量设置为触发器中插入或删除的值。

使用 OUTPUT 子句取回您的 id 值。

【讨论】:

    【解决方案2】:

    此触发器在游标上使用循环,并且不需要表中有任何特定的唯一性;

    CREATE TRIGGER test
    ON V_Enterprise
    INSTEAD OF INSERT
    AS 
    BEGIN
       DECLARE @name    VARCHAR(32)
       DECLARE @city    VARCHAR(32)
       DECLARE @address VARCHAR(32)
       DECLARE @pn      VARCHAR(32)
       DECLARE @email   VARCHAR(32)
    
       DECLARE cursor1 CURSOR FOR
          SELECT name,city,address,phoneNumber,email FROM inserted;
    
        OPEN cursor1;
        FETCH NEXT FROM cursor1 INTO @name, @city, @address, @pn, @email;
        WHILE @@FETCH_STATUS = 0
        BEGIN
          INSERT INTO T_Contact (phoneNumber,email) VALUES (@pn, @email);
          INSERT INTO T_Enterprise (idcontact,name,city,address) VALUES
             (@@IDENTITY,@name,@city,@address);
          FETCH NEXT FROM cursor1 INTO @name, @city, @address, @pn, @email;
        END
        CLOSE cursor1;
        DEALLOCATE cursor1;
    END
    GO
    

    【讨论】:

      【解决方案3】:

      我不知道这是否是一种的方法,但您可以做到这一点,而无需依赖唯一列或使用游标使用 OUTPUT 子句进行 INSERT。这种方法确实利用了内存中的临时表,该表可能会因大量插入而变大。

      DECLARE @Table table( NewID BIGINT);
      
      
      INSERT INTO T_Contact (PhoneNumber) 
          OUTPUT Inserted.ID
          INTO @Table
      SELECT PhoneNumber FROM inserted WHERE 
      ;
      
      INSERT INTO T_Enterprise (Contact_ID)
      SELECT NewID FROM @Table;
      

      【讨论】:

        【解决方案4】:

        如果phoneNumberemailT_Contact 中的唯一键,那么您可以这样做:

        CREATE TRIGGER test
        ON V_Entreprise
        INSTEAD OF INSERT
        AS 
        DECLARE @T_ContactId INT
        BEGIN
            INSERT INTO T_Contact 
            SELECT i.phoneNumber, i.email
            FROM Inserted i 
        
            SELECT @T_ContactId = @@IDENTITY
        
            INSERT INTO T_Entreprise
            SELECT
                (SELECT idContact FROM T_Contact
                    WHERE phoneNumber = i.phoneNumber AND email = i.email),
                i.name, i.city, i.adress
            FROM Inserted i 
        END ;
        

        【讨论】:

        • 嗯,它应该可以解决问题(我在示例中跳过了一些列。在我的真实数据库中,我可以放置十几个参数)。但我期待的东西更...强大:-)
        • @FlorianC: But I expected something more... robust,你到底是什么意思?
        • 首先,对不起我糟糕的英语。我的意思是:没关系,它会起作用,因为用户不应该添加两次相同的联系人。但是用户总是表现得很奇怪,所以我试图想办法避免在这种特殊情况下出现故障。我显然可以在“客户端”管理它,但我认为在数据库中有更好的方法来处理它,我真的很想找到它!
        • @FlorianC,好的,现在我明白了。您可以做的是在这两个(或更多,如果需要)字段上为该表添加一个唯一约束,以便您将知道记录是唯一的。您当然也应该在客户端处理它 - 但这是具体的安全层。
        猜你喜欢
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多