Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

एक सम्मिलित SQL सर्वर में यदि स्थिति का उपयोग करना

पैटर्न है (त्रुटि प्रबंधन के बिना):

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;

किसी भी मामले में, आप पहले अपडेट करते हैं, अन्यथा आप उन सभी पंक्तियों को अपडेट कर देंगे जो आपने अभी डाली हैं, जो बेकार होगी।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Windows सेवा और SQL सर्वर का उपयोग करके OneWay WCF संदेशों में कतारबद्ध करना

  2. STRING_AGG में DISTINCT मान उत्पन्न करें

  3. T-SQL कथनों में उपसर्ग N का क्या अर्थ है और मुझे इसका उपयोग कब करना चाहिए?

  4. SQL सर्वर 2005 में गतिरोध का निदान

  5. SQL सर्वर में एकाधिक कॉलम पर अद्वितीय बाधा कैसे बनाएं - SQL सर्वर / TSQL ट्यूटोरियल भाग 96