插入视图,代替触发器,身份,多个表?

Posted

技术标签:

【中文标题】插入视图,代替触发器,身份,多个表?【英文标题】: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 插入,但我不知道如何处理它。

【问题讨论】:

phoneNumberemailT_Contact 中的唯一键吗? 出于好奇,你用什么来得到那个数据模型设计图? 这是 Sybase 的 PowerAMC,试用版。 sybase.fr/products/modelingdevelopment/poweramc 【参考方案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,好的,现在我明白了。您可以做的是在这两个(或更多,如果需要)字段上为该表添加一个唯一约束,以便您将知道记录是唯一的。您当然也应该在客户端处理它 - 但这是具体的安全层。

以上是关于插入视图,代替触发器,身份,多个表?的主要内容,如果未能解决你的问题,请参考以下文章

触发器从多个表 MySQL 中插入多个数据

您能否在视图上编写触发器,该视图在更改其基表后利用插入和删除表中的数据?

触发器导致在视图中使用的表上插入后,如何进行 MYSQL 视图更新

如何使用云功能或某些自动触发器将视图中的数据插入表中。

SQL 代替触发器

触发插入多个表