पैटर्न है (त्रुटि प्रबंधन के बिना):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE #TProductSales SET StockQty = @StockQty, ETA1 = @ETA1
WHERE ProductID = @ProductID;
IF @@ROWCOUNT = 0
BEGIN
INSERT #TProductSales(ProductID, StockQTY, ETA1)
VALUES(@ProductID, @StockQTY, @ETA1);
END
COMMIT TRANSACTION;
आपको यहां #temp तालिका का अतिरिक्त पठन करने की आवश्यकता नहीं है। आप अपडेट का प्रयास करके पहले से ही ऐसा कर रहे हैं। दौड़ की स्थिति से बचाने के लिए, आप वही करते हैं जैसे आप दो या दो से अधिक बयानों के किसी भी ब्लॉक की रक्षा करते हैं जिसे आप अलग करना चाहते हैं:आप इसे उचित अलगाव स्तर के साथ लेनदेन में लपेटेंगे (संभावित यहां क्रमबद्ध करने योग्य, हालांकि वह सब केवल समझ में आता है जब हम #temp तालिका के बारे में बात नहीं कर रहे हैं, क्योंकि यह परिभाषा के अनुसार क्रमबद्ध है)।
IF EXISTS
. जोड़कर आप आगे नहीं हैं जांचें (और आपको उस सुरक्षित/क्रमबद्ध करने योग्य बनाने के लिए लॉकिंग संकेत जोड़ने की आवश्यकता होगी), लेकिन आप मौजूदा पंक्तियों को कितनी बार अपडेट करते हैं, इस पर निर्भर करते हुए आप और पीछे हो सकते हैं। नया डालें। यह बहुत सारे अतिरिक्त I/O को जोड़ सकता है।
लोग शायद आपको MERGE
. का उपयोग करने के लिए कहेंगे (जो वास्तव में पर्दे के पीछे कई ऑपरेशन हैं, और इसे धारावाहिक के साथ संरक्षित करने की भी आवश्यकता है), मैं आपसे आग्रह करता हूं कि ऐसा न करें। मैं यहां बताता हूं कि क्यों:
- SQL सर्वर के MERGE स्टेटमेंट के साथ सावधानी बरतें
एक बहु-पंक्ति पैटर्न (एक टीवीपी की तरह) के लिए, मैं इसे उसी तरह से संभालूंगा, लेकिन दूसरे पढ़ने से बचने का कोई व्यावहारिक तरीका नहीं है जैसे आप सिंगल-पंक्ति मामले के साथ कर सकते हैं। और नहीं, MERGE
इससे भी नहीं बचते हैं।
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE t SET t.col = tvp.col
FROM dbo.TargetTable AS t
INNER JOIN @TVP AS tvp
ON t.ProductID = tvp.ProductID;
INSERT dbo.TargetTable(ProductID, othercols)
SELECT ProductID, othercols
FROM @TVP AS tvp
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.TargetTable
WHERE ProductID = tvp.ProductID
);
COMMIT TRANSACTION;
ठीक है, मुझे लगता है कि ऐसा करने का एक तरीका है, लेकिन मैंने इसका पूरी तरह से परीक्षण नहीं किया है:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
DECLARE @exist TABLE(ProductID int PRIMARY KEY);
UPDATE t SET t.col = tvp.col
OUTPUT deleted.ProductID INTO @exist
FROM dbo.TargetTable AS t
INNER JOIN @tvp AS tvp
ON t.ProductID = tvp.ProductID;
INSERT dbo.TargetTable(ProductID, othercols)
SELECT ProductID, othercols
FROM @tvp AS t
WHERE NOT EXISTS
(
SELECT 1 FROM @exist
WHERE ProductID = t.ProductID
);
COMMIT TRANSACTION;
किसी भी मामले में, आप पहले अपडेट करते हैं, अन्यथा आप उन सभी पंक्तियों को अपडेट कर देंगे जो आपने अभी डाली हैं, जो बेकार होगी।