我在SQL Server中创建了一个使用两个表tbPOValidation
和tbPOValidationTemp
的存储过程。
如果tbPOValidationTemp
中有tbPOValidation
行,则使用tbPOValidation
中的值更新tbPOValidationTemp
。
如果不存在,则将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 :(得分: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()
子查询,对我来说,更容易阅读。请注意,我假设您要检查完整记录中ShoppingCartNo
,LineItemNo
和PONo
的匹配项,而不只是检查它们是否存在于主表中。