从同一个包更新和插入到 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 个不同的表的主要内容,如果未能解决你的问题,请参考以下文章
从java批量更新的两个不同表中的一个表中插入max + 1