-1

1 つの単純な操作を実行するトリガー (SQL 2008 R2) がありますが、結果は論理的ではありません。概要は次のとおりです。

テキスト ファイルは、「ORDERS_IN_PROCESS」テーブルにロードする 1 行 (1 レコード) の SSIS パッケージに供給されます。トリガーを起動できるように、[OLE DB Destination] で [Data Access Mode] を [Table or view] に設定します。

これが私のORDERSテーブルです:

OrderID        ItemNo
---------    ---------
9813           1
9813           2
9813           3
9817           1

したがって、SSIS が実行され、ORDERS_IN_PROCESS は OrderID 9813 である 1 つのレコードを挿入します。

トリガーが起動されます:

INSERT INTO ORDERS_ARCHIVE SELECT * FROM ORDERS WHERE OrderID=INSERTED.OrderID

ここまではかなり単純...

ORDERS_ARCHIVE (ORDERS と同じレイアウト) テーブルで得られる結果は次のとおりです。

OrderId       ItemNo
---------   ----------
9813          3

残りの 2 つの広告申込情報はどこにありますか?

ORDERS テーブルから読み取った最後の行のみを ORDERS_ARCHIVE に挿入したことに注意してください。

ORDERS_ARCHIVE に 3 つすべてが必要です。

なぜこれが起こるのですか?

SSISが「OLE DB宛先」を使用して処理する方法に関係があると思います.RLFLにレコードを手動で挿入すると、トリガーは本来の処理を正確に実行し、BACKから3つのレコードすべてを挿入するためです.

トリガーはバッチごとに 1 回起動すると主張するかもしれませんが、私も同意しますが、この場合、1 つのレコードのバッチしかありません。

私はspを考えていますが、おそらくそれほど些細なことに別のレベルの複雑さを追加したくありません。

何か案は?

ありがとう。

4

2 に答える 2

5

これはSSISとはまったく関係がないと思いますが、トリガーとは関係ありません。そこにある代わりに、クエリでINa を使用してみてください。JOIN

INSERT INTO ORDERS_ARCHIVE 
SELECT O.* 
FROM ORDERS O
INNER JOIN INSERTED I
     ON O.ORderID = I.OrderID
于 2013-02-14T19:14:43.627 に答える
3

あなたのトリガーの評価が正しくないという点で、意図的なスペルミスであるラマークに同意します。

トリガーに指定したロジックはコンパイルされません。WHERE 句が無効です。Lamak がしたように、あなたの意図は OrderID に基づいて参加することだったと思います。

create table dbo.ORDERS_ARCHIVE
(
    OrderID int
,   ItemNo int
)
GO
create table dbo.ORDERS
(
    OrderID int
,   ItemNo int
)
GO
create trigger 
    trUpdate
ON
    dbo.ORDERS
    AFTER INSERT
AS
BEGIN
    SET NOCOUNT ON;
    -- This doesn't work
    -- Msg 4104, Level 16, State 1, Procedure trUpdate, Line 12
    -- The multi-part identifier "INSERTED.OrderID" could not be bound.
    --INSERT INTO dbo.ORDERS_ARCHIVE 
    --SELECT * 
    --FROM ORDERS 
    --WHERE OrderID=INSERTED.OrderID;

    -- I think you meant
    INSERT INTO dbo.ORDERS_ARCHIVE 
    SELECT * 
    FROM ORDERS 
    WHERE OrderID=(SELECT INSERTED.OrderID FROM INSERTED);
 END
 GO

次に、単純なSSISパッケージを作成しました。指定した4行を提供するデータソースがありdbo.ORDERS.、パッケージを2回実行し、それぞれがORDERS_ARCHIVEテーブルの4行をネットしました。バッチごとに 9813 で 3 行、9817 で 1 行。

そこに正しい行数を取得しているので、トリガーが正しく起動していると思います。代わりに、何が起こっているかというと、ロジックが間違っています。OrderID は ORDERS テーブル内で一意ではないため、データベース エンジンは検索条件を満たす最初の行を選択します。毎回同じ行 (ItemNo = 1) が選択されるのはたまたまですが、ORDER BY句がないと順序が保証されないため、これは単なるランダムまたはエンジンの選択方法のアーティファクトですが、一貫性を保つことに頼る動作はありません。 .

これをどのように修正しますか?

トリガーを修正します。OrderID のみで挿入された仮想テーブルに結合すると、条件を満たす複数の行が発生します。

create trigger 
    trUpdate
ON
    dbo.ORDERS
    AFTER INSERT
AS
BEGIN
    SET NOCOUNT ON;
    -- This trigger will add all the rows from the ORDERS table
    -- that match what was just inserted based on OrderID and ItemNo
    INSERT INTO dbo.ORDERS_ARCHIVE 
    SELECT O.* 
    FROM dbo.ORDERS O
    INNER JOIN INSERTED I
         ON O.OrderID = I.OrderID
         AND O.ItemNo = I.ItemNo;
END

ETL を実行すると、ORDERS_ARCHIVE に正しいItemNo値を持つ 4 つの行が表示されます。

于 2013-02-15T04:11:28.373 に答える