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

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

客户表

变更日志表

我的要求是这样的

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

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

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

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

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

非常感谢任何帮助

【问题讨论】:

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

标签: sql-server ssis


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

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

    3. 或者,您可以在 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更新了吗?
    • 不,它会占用一切。我的情况是,您拥有所有可用的值,因此没关系。
    • 但在我的场景中,更新可能只发生在一列或多列。每条记录可能会有所不同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多