SQLエージェント(または同様のスケジューラー)を使用していると仮定します
要件1/4)FTPやファイルのコピーステップを処理する先行ステップがあります。回避できるのであれば、ファイル操作でパッケージを乱雑にするのは好きではありません。
要件2/3)制御フローレベルでは、パッケージデザインは、別のSQL実行タスクに接続されたデータフローに接続されたSQL実行タスクのように見えます。 @AllenGが示しているように、データフロータスクを介してステージングテーブルにロードするのが最適です。最初のSQL実行タスクは、ステージングテーブル(TRUNCATE TABLE dbo.DAILY_STAGE)からすべての行を削除します
おおよそのテーブルデザインはこんな感じ。 MICHAEL_BORNテーブルは既存のテーブルであり、DAILY_STAGEはデータフローが到達する場所です。
CREATE TABLE DBO.MICHAEL_BORN
(
ID int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED
, ItemID int NOT NULL
, ItemName varchar(20) NOT NULL
, ItemType varchar(20) NOT NULL
)
CREATE TABLE dbo.DAILY_STAGE
(
ItemID int NOT NULL PRIMARY KEY CLUSTERED
, ItemName varchar(20) NOT NULL
, ItemType varchar(20) NOT NULL
)
デモンストレーションの目的で、TSQLを介して上記のテーブルにサンプルデータをロードします
-- Original data
INSERT INTO
dbo.MICHAEL_BORN
VALUES
(2345,'Apple','Fruit')
, (4578, 'Bannana','Fruit')
-- Daily load runs
-- Adds a new fruit (pear), corrects misspelling of banana, eliminates apple
INSERT INTO
dbo.DAILY_STAGE
VALUES
(7721,'Pear','Fruit')
, (4578, 'Banana','Fruit')
SQLの実行タスクは、MERGE を利用します。 SQLServerの2008以降のエディションで使用可能なステートメント。末尾のセミコロンはMERGEステートメントの一部であることに注意してください。これを含めないと、「MERGEステートメントはセミコロン(;)で終了する必要があります」というエラーが発生します。
-- MERGE statement
-- http://technet.microsoft.com/en-us/library/bb510625.aspx
-- Given the above scenario, this script will
-- 1) Update the matched (4578 bannana/banana) row
-- 2) Add the new (pear) row
-- 3) Remove the unmatched (apple) row
MERGE
dbo.[MICHAEL_BORN] AS T
USING
(
SELECT
ItemID
, ItemName
, ItemType
FROM
dbo.DAILY_STAGE
) AS S
ON T.ItemID = S.ItemID
WHEN
MATCHED THEN
UPDATE
SET
T.ItemName = S.ItemName
, T.ItemType = S.ItemType
WHEN
NOT MATCHED THEN
INSERT
(
ItemID
, ItemName
, ItemType
)
VALUES
(
ItemID
, ItemName
, ItemType
)
WHEN
NOT MATCHED BY SOURCE THEN
DELETE
;
必要条件5)効率は完全にデータと行の幅に基づいていますが、ひどいものであってはなりません。
-- Performance testing
-- Assumes you have a similar fast row number generator function
-- http://billfellows.blogspot.com/2009/11/fast-number-generator.html
TRUNCATE TABLE dbo.MICHAEL_BORN
TRUNCATE TABLE dbo.DAILY_STAGE
-- load initial rows
-- 20ish seconds
INSERT INTO
dbo.MICHAEL_BORN
SELECT
N.number AS ItemID
, 'Spam & eggs ' + CAST(N.number AS varchar(10)) AS ItemName
, 'SPAM' AS ItemType
--, CASE N.number % 2 WHEN 0 THEN N.number + 1000000 ELSE N.number END AS UpTheEvens
FROM
dbo.GenerateNumbers(1000000) N
-- Load staging table
-- Odds get item type switched out
-- Evens get delete and new ones created
-- 20ish seconds
INSERT INTO
dbo.DAILY_STAGE
SELECT
CASE N.number % 2 WHEN 0 THEN N.number + 1000000 ELSE N.number END AS ItemID
, 'Spam & eggs ' + CAST(N.number AS varchar(10)) AS ItemName
, CASE N.number % 2 WHEN 0 THEN 'SPAM' ELSE 'Not much spam' END AS ItemType
FROM
dbo.GenerateNumbers(1000000) N
-- Run MERGE statement, 32 seconds 1.5M rows upserted
-- Probably fast enough for you