从同一个包更新和插入到 2 个不同的表

Posted

技术标签:

【中文标题】从同一个包更新和插入到 2 个不同的表【英文标题】:Updating and Inserting to 2 different tables from the Same package 【发布时间】:2017-11-08 13:58:56 【问题描述】:

我有 2 个名为 Customer 和 ChangeLog 的表。具有以下结构

客户表

变更日志表

我的要求是这样的

我需要一个 SSIS 包,它可以从另一个与 CustomerTable 结构相同的表中读取记录,然后比较两个表上的行。如果发现任何记录发生更改,它会更新客户表中的记录,并在 ChangeLog 中输入一个条目,说明更新了哪一列。

因此,当在任何列中发现更改时,我需要执行以下操作

    更新客户表中的 Coresposing 记录 在 ChangeLog 中插入新行

不会有插入到客户表中。只会有更新

SSIS 中是否有任何单个任务可以用来更新和插入这些不同的表?或者在 SSIS 中实现这一目标的最快和最有效的方法是什么?

非常感谢任何帮助

【问题讨论】:

其他表是否仅包含来自您的 custtable 的更新行?至少您需要识别一个键,如果您查看该键并且行不同,则更新。使用合并语句来做到这一点 @plaidDK 我可以根据 CustId 匹配记录。而且我知道您可以使用合并连接插入或更新相同的语句。但这是否支持多个表?因为插入和更新是针对不同的表完成的 您更新的值是否总是在另一个表中?然后您可以只使用查找,当它与 ID 匹配时,它会转到更新 sql 命令和插入任务。当它不匹配时,它什么也不做 对客户表进行更新。我有另一个临时表,我将记录与更新匹配 是的,但更改是否来自另一个表? 【参考方案1】:

不,没有单一的 SSIS 任务可以做到这一点。我根本不会为此使用 SSIS。将逻辑放在存储过程或触发器中。如果您出于某种原因必须使用 SSIS,则让 SSIS 调用存储过程,或 UPDATE 表并让触发器触发。

【讨论】:

【参考方案2】:

这比 SSIS 包更好,因为您可以使用触发器来检测行更改,甚至是值。

试试我的例子,你可以直接 C/P 进入管理工作室。当您更新 Sample_Table 时,您将更改表中的行和列。

    所以你能做的就是。将您的查找逻辑保留在 SSIS 中(如果您想要 SSIS 中的某些内容)- 根据查找中的匹配项更新表

    当这些更新发生时,您的触发器将被触发并更新已更改的行。

    或者,您可以在 t-sql 脚本中创建查找并在 custid=custid 时进行普通更新,而不是同样简单。但这取决于你。

已编辑

     -- -------------------- Setup tables and some initial data --------------------
 CREATE TABLE dbo.Sample_Table (ContactID int, Forename varchar(100), Surname varchar(100), Extn varchar(16), Email varchar(100), Age int );
 INSERT INTO Sample_Table VALUES (1,'Bob','Smith','2295','bs@example.com',24);
 INSERT INTO Sample_Table VALUES (2,'Alice','Brown','2255','ab@example.com',32);
 INSERT INTO Sample_Table VALUES (3,'Reg','Jones','2280','rj@example.com',19);
 INSERT INTO Sample_Table VALUES (4,'Mary','Doe','2216','md@example.com',28);
 INSERT INTO Sample_Table VALUES (5,'Peter','Nash','2214','pn@example.com',25);
 
 CREATE TABLE dbo.Sample_Table_Changes (ContactID int, FieldName sysname, FieldValueWas sql_variant, FieldValueIs sql_variant, modified datetime default (GETDATE()));
 
 GO
 
 -- -------------------- Create trigger --------------------
 CREATE TRIGGER TriggerName ON dbo.Sample_Table FOR DELETE, INSERT, UPDATE AS
 BEGIN
     SET NOCOUNT ON;
     --Unpivot deleted
     WITH deleted_unpvt AS (
         SELECT ContactID, FieldName, FieldValue
         FROM 
            (SELECT ContactID
                 , cast(Forename as sql_variant) Forename
                 , cast(Surname as sql_variant) Surname
                 , cast(Extn as sql_variant) Extn
                 , cast(Email as sql_variant) Email
                 , cast(Age as sql_variant) Age
            FROM deleted) p
         UNPIVOT
            (FieldValue FOR FieldName IN 
               (Forename, Surname, Extn, Email, Age)
         ) AS deleted_unpvt
     ),
     --Unpivot inserted
     inserted_unpvt AS (
         SELECT ContactID, FieldName, FieldValue
         FROM 
            (SELECT ContactID
                 , cast(Forename as sql_variant) Forename
                 , cast(Surname as sql_variant) Surname
                 , cast(Extn as sql_variant) Extn
                 , cast(Email as sql_variant) Email
                 , cast(Age as sql_variant) Age
            FROM inserted) p
         UNPIVOT
            (FieldValue FOR FieldName IN 
               (Forename, Surname, Extn, Email, Age)
         ) AS inserted_unpvt
     )
 
     --Join them together and show what's changed
     INSERT INTO Sample_Table_Changes (ContactID, FieldName, FieldValueWas, FieldValueIs)
     SELECT Coalesce (D.ContactID, I.ContactID) ContactID
         , Coalesce (D.FieldName, I.FieldName) FieldName
         , D.FieldValue as FieldValueWas
         , I.FieldValue AS FieldValueIs 
     FROM 
         deleted_unpvt d
 
             FULL OUTER JOIN 
         inserted_unpvt i
             on      D.ContactID = I.ContactID 
                 AND D.FieldName = I.FieldName
     WHERE
          D.FieldValue <> I.FieldValue --Changes
         OR (D.FieldValue IS NOT NULL AND I.FieldValue IS NULL) -- Deletions
         OR (D.FieldValue IS NULL AND I.FieldValue IS NOT NULL) -- Insertions
 END
 GO
 -- -------------------- Try some changes --------------------
 UPDATE Sample_Table SET age = age+1;
 /*UPDATE Sample_Table SET Extn = '5'+Extn where Extn Like '221_';
 
 DELETE FROM Sample_Table WHERE ContactID = 3;
 
 INSERT INTO Sample_Table VALUES (6,'Stephen','Turner','2299','st@example.com',25);
 
 UPDATE Sample_Table SET ContactID = 7 where ContactID = 4; --this will be shown as a delete and an insert
 -- -------------------- See the results --------------------
 SELECT *, SQL_VARIANT_PROPERTY(FieldValueWas, 'BaseType') FieldBaseType, SQL_VARIANT_PROPERTY(FieldValueWas, 'MaxLength') FieldMaxLength from Sample_Table_Changes;
 
 -- -------------------- Cleanup --------------------
 DROP TABLE dbo.Sample_Table; DROP TABLE dbo.Sample_Table_Changes;*/
 
 select * from dbo.sample_table_changes

【讨论】:

但我也已经在某种存储过程中自己制作了它:) 但这是一个基本的 ssis 方式。 因此,如果只更改了记录的名字并且 Lastname 没有更新,那么它将只插入 1 条记录说 First Name Updated(如预期)或一条记录说 Record / Row更新了吗? 不,它会占用一切。我的情况是,您拥有所有可用的值,因此没关系。 但在我的场景中,更新可能只发生在一列或多列。每条记录可能会有所不同 另见***.com/questions/1254787/…

以上是关于从同一个包更新和插入到 2 个不同的表的主要内容,如果未能解决你的问题,请参考以下文章

插入多个文本文件

如何从 3 个不同的表中插入内连接

从java批量更新的两个不同表中的一个表中插入max + 1

将文本框中的值插入 2 个不同的表 ms-access

如何在 php pdo 中使用 1 个表单将数据插入到 2 个不同的表中?

从表单插入到不同的表中