2017-09-07 10 views
0

2つのテーブルtbPOValidationtbPOValidationTempを使用するストアドプロシージャをSQL Serverに作成しました。SQLコードより下ではどのように最適化できますか?

tbPOValidationTempの行がtbPOValidationにある場合は、tbPOValidationTempの値でtbPOValidationを更新します。

が存在しない場合は、tbPOValidationTempの行をtbPOValidationに挿入します。

このSQLはこのジョブを実行しますが、私がやっていることは安全ではないと思います。どのようにすれば、コードを最適化して、安全に機能させることができますか?

CREATE PROCEDURE spPOValidation 
AS 
BEGIN 
    SET NOCOUNT ON; 

    IF NOT EXISTS(SELECT * 
        FROM tbPOValidation 
        WHERE ShoppingCartNo IN (SELECT ShoppingCartNo 
              FROM tbPOValidationTemp) 
        AND LineItemNo IN (SELECT LineItemNo 
             FROM tbPOValidationTemp) 
        AND PONo IN (SELECT PONo FROM tbPOValidationTemp)) 
    BEGIN 
     INSERT INTO tbPOValidation (SupplierName, DUNS, PONo, LineItemNo, PurchDocItemDesc, POIssueDate, DeliveryDate, PurchDocType, MtrNo, 
     Location, PayTerms, BlanketNo, BlanketLineItemNo, ShoppingCartNo, SHCItmNo, ItemPricing, ItmPrcCurrency, Per, POValue, POValueCurrency, 
     Qty, UOM, MFGName, MFGPartNO, Description, Remarks, Accept, AcceptedBy, AcceptedOn, RejectionReason) 
      SELECT 
       SupplierName, DUNS, PONo, LineItemNo, PurchDocItemDesc, 
       POIssueDate, DeliveryDate, PurchDocType, MtrNo, 
       Location, PayTerms, BlanketNo, BlanketLineItemNo, 
       ShoppingCartNo, SHCItmNo, ItemPricing, ItmPrcCurrency, Per, 
       POValue, POValueCurrency, Qty, UOM, MFGName, MFGPartNO, 
       Description, Remarks, Accept, AcceptedBy, AcceptedOn, RejectionReason 
      FROM 
       tbPOValidationTemp 
    END 
    ELSE 
    BEGIN 
     UPDATE t 
     SET t.SupplierName = v.SupplierName, t.DUNS = v.DUNS, 
      t.PONo = v.PONo, t.LineItemNo = v.LineItemNo, 
      t.PurchDocItemDesc = v.PurchDocItemDesc, 
      t.POIssueDate = v.POIssueDate, t.DeliveryDate = v.DeliveryDate, 
      t.PurchDocType = v.PurchDocType, t.MtrNo = v.MtrNo, 
      t.Location = v.Location, t.PayTerms = v.PayTerms, 
      t.BlanketNo = v.BlanketNo, 
      t.BlanketLineItemNo = v.BlanketLineItemNo, 
      t.ShoppingCartNo = v.ShoppingCartNo, 
      t.SHCItmNo = v.SHCItmNo, t.ItemPricing = v.ItemPricing, 
      t.ItmPrcCurrency = v.ItmPrcCurrency, t.Per = v.Per, 
      t.POValue = v.POValue, t.POValueCurrency = v.POValueCurrency, 
      t.Qty = v.Qty, t.UOM = v.UOM, t.MFGName = v.MFGName, 
      t.MFGPartNO = v.MFGPartNO, t.Description = v.Description, 
      t.Remarks = v.Remarks, t.Accept = v.Accept, 
      t.AcceptedBy = v.AcceptedBy, t.AcceptedOn = v.AcceptedOn, 
      t.RejectionReason = v.RejectionReason 
     FROM 
      tbPOValidation t 
     JOIN 
      tbpovalidationtemp v ON t.ShoppingCartNo = v.ShoppingCartNo 
           AND t.LineItemNo = v.LineItemNo 
           AND t.PONo = v.PONo 
    END 

    TRUNCATE TABLE tbPOValidationTemp 
END 
+0

あなたの「存在しない場合は(...)」チェックでShoppingCartNo/LineItemNo/PONoの組み合わせを探しているのではなく、値が個別に存在しているようです。 LineItemNoが特定のショッピングカート(たとえば1〜X)の一意でないラインアイテム番号である場合、LineItemNo = 1に欠けている行を挿入しないでください。MERGEステートメント[link](https: //docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql) – Forty3

+0

「Not Safe」とはどういう意味ですか? – Missy

+2

SQL Server 2008のMERGE機能を使用することができます。以下のリンクを参照してください - https://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx –

答えて

0

あなたの更新部分は、自然に結果をあなたのINNER JOIN述語のおかげで制限します。あなたは存在しないレコードのLEFT JOINと再書き込みあなたの挿入部にこれと同じロジックを使用することができます。

INSERT INTO tbPOValidation (SupplierName, DUNS, PONo, LineItemNo, PurchDocItemDesc, POIssueDate, DeliveryDate, PurchDocType, MtrNo, 
       Location, PayTerms, BlanketNo, BlanketLineItemNo, ShoppingCartNo, SHCItmNo, ItemPricing, ItmPrcCurrency, Per, POValue, POValueCurrency, 
       Qty, UOM, MFGName, MFGPartNO, Description, Remarks, Accept, AcceptedBy, AcceptedOn, RejectionReason) 
SELECT SupplierName, DUNS, PONo, LineItemNo, PurchDocItemDesc, POIssueDate, DeliveryDate, PurchDocType, MtrNo, 
      Location, PayTerms, BlanketNo, BlanketLineItemNo, ShoppingCartNo, SHCItmNo, ItemPricing, ItmPrcCurrency, Per, POValue, POValueCurrency, 
      Qty, UOM, MFGName, MFGPartNO, Description, Remarks, Accept, AcceptedBy, AcceptedOn, RejectionReason 
FROM tbPOValidationTemp T 
LEFT JOIN tbPOValidation T2 on T.ShoppingCartNo = T2.ShoppingCartNo 
           and T.LineItemNo = T2.LineItemNo 
           and T.PONo = T2.PONo 
WHERE T2.ShoppingCartNo IS NULL --NULL filter to complete anti-join and only 
           --insert records that do not exist 

そして、単に後にアップデートを行います。これにより、すべての混乱しているifロジックとin()サブクエリが削除され、私にとっては読みやすくなります。私はあなたがShoppingCartNoLineItemNo、およびPONoの一致を完全なレコードの中でチェックし、メインテーブルにそれらの存在をチェックするだけでなく、確認したいと仮定しています。

関連する問題