SQL में, लेन-देन का उपयोग डेटा अखंडता को बनाए रखने के लिए किया जाता है, यह सुनिश्चित करके कि SQL कथनों का एक क्रम पूरी तरह से निष्पादित होता है या बिल्कुल नहीं।
लेन-देन SQL कथनों के अनुक्रमों का प्रबंधन करते हैं जिन्हें कार्य की एक इकाई के रूप में निष्पादित किया जाना चाहिए, ताकि डेटाबेस में आंशिक संचालन के परिणाम कभी भी शामिल न हों।
जब कोई लेन-देन डेटाबेस में कई परिवर्तन करता है, या तो लेन-देन के प्रतिबद्ध होने पर सभी परिवर्तन सफल हो जाते हैं, या लेन-देन के वापस आने पर सभी परिवर्तन पूर्ववत हो जाते हैं।
लेन-देन का उपयोग कब करें?
लेन-देन उन स्थितियों में सर्वोपरि हैं जहां डेटा अखंडता जोखिम में होगी, यदि SQL कथनों का कोई एक क्रम विफल हो जाता है।
उदाहरण के लिए, यदि आप एक बैंक खाते से दूसरे बैंक खाते में पैसे ले जा रहे थे, तो आपको एक खाते से पैसे काटकर दूसरे खाते में जोड़ना होगा। आप नहीं चाहते कि यह आधे रास्ते में विफल हो जाए, अन्यथा, एक खाते से पैसा डेबिट किया जा सकता है लेकिन दूसरे में जमा नहीं किया जा सकता है।
विफलता के संभावित कारणों में अपर्याप्त धन, अमान्य खाता संख्या, हार्डवेयर विफलता आदि शामिल हो सकते हैं।
तो आप नहीं करते हैं ऐसी स्थिति में रहना चाहते हैं जहां यह इस तरह रहे:
Debit account 1 (Done)
Credit account 2 (Not Done)
Record transaction in transaction journal (Not Done)
यह वास्तव में होगा बुरा। डेटाबेस में असंगत डेटा होगा और पैसा पतली हवा में गायब हो जाएगा। तब बैंक एक ग्राहक खो देगा (यदि ऐसा होता रहा तो बैंक शायद अपने सभी ग्राहकों को खो देगा), और आप अपनी नौकरी खो देंगे।
अपनी नौकरी बचाने के लिए, आप एक लेन-देन का उपयोग कर सकते हैं जो कुछ इस तरह होगा:
START TRANSACTION
Debit account 1
Credit account 2
Record transaction in transaction journal
END TRANSACTION
आप उस लेन-देन के अंदर सशर्त तर्क लिख सकते हैं जो कुछ भी गलत होने पर लेन-देन को वापस ले लेता है।
उदाहरण के लिए, अगर खाता 1 डेबिट करने और खाता 2 क्रेडिट करने के बीच कुछ गलत हो जाता है, तो पूरा लेन-देन वापस ले लिया जाता है।
इसलिए, केवल दो संभावित परिणाम होंगे:
Debit account 1 (Not Done)
Credit account 2 (Not Done)
Record transaction in transaction journal (Not Done)
या:
Debit account 1 (Done)
Credit account 2 (Done)
Record transaction in transaction journal (Done)
यह एक सरलीकृत चित्रण है, लेकिन यह एक उत्कृष्ट उदाहरण है कि SQL लेनदेन कैसे काम करता है। SQL लेनदेन में ACID होता है।
लेन-देन के प्रकार
SQL लेनदेन निम्नलिखित मोड में चलाया जा सकता है।
लेन-देन मोड | <थ>विवरण|
---|---|
अपने आप लेन-देन करें | प्रत्येक व्यक्तिगत विवरण एक लेन-देन है। |
अंतर्निहित लेनदेन | एक नया लेन-देन परोक्ष रूप से तब शुरू होता है जब पिछला लेन-देन पूरा हो जाता है, लेकिन प्रत्येक लेन-देन स्पष्ट रूप से पूरा हो जाता है, आमतौर पर COMMIT के साथ या ROLLBACK डीबीएमएस के आधार पर बयान। |
स्पष्ट लेन-देन | स्पष्ट रूप से एक पंक्ति के साथ प्रारंभ किया गया जैसे START TRANSACTION , BEGIN TRANSACTION या इसी तरह, डीबीएमएस के आधार पर, और स्पष्ट रूप से प्रतिबद्ध या प्रासंगिक बयानों के साथ वापस ले लिया। |
बैच के दायरे वाला लेन-देन | केवल एकाधिक सक्रिय परिणाम सेट (MARS) पर लागू। MARS सत्र के तहत शुरू होने वाला एक स्पष्ट या निहित लेन-देन एक बैच-स्कोप्ड लेनदेन बन जाता है। |
उपलब्ध सटीक मोड और विकल्प डीबीएमएस पर निर्भर हो सकते हैं। यह तालिका SQL सर्वर में उपलब्ध लेन-देन मोड की रूपरेखा तैयार करती है।
इस लेख में, हम मुख्य रूप से स्पष्ट लेनदेन पर ध्यान केंद्रित कर रहे हैं।
अंतर्निहित लेनदेन और ऑटोकॉमिट के बीच अंतर की चर्चा के लिए SQL सर्वर में अंतर्निहित लेनदेन कैसे काम करते हैं देखें।
Sytnax
निम्न तालिका कुछ अधिक लोकप्रिय डीबीएमएस में एक स्पष्ट लेनदेन शुरू करने और समाप्त करने के लिए मूल सिंटैक्स की रूपरेखा तैयार करती है।
डीबीएमएस | स्पष्ट लेनदेन सिंटैक्स |
---|---|
MySQL, MariaDB, PostgreSQL | स्पष्ट लेनदेन START TRANSACTION . से शुरू होते हैं या BEGIN बयान। COMMIT वर्तमान लेनदेन करता है, जिससे उसके परिवर्तन स्थायी हो जाते हैं। ROLLBACK वर्तमान लेन-देन को वापस लेता है, इसके परिवर्तनों को रद्द करता है। |
SQLite | स्पष्ट लेनदेन BEGIN TRANSACTION . से शुरू होते हैं कथन और अंत COMMIT . के साथ या ROLLBACK बयान। END . के साथ भी समाप्त हो सकता है बयान। |
एसक्यूएल सर्वर | स्पष्ट लेनदेन BEGIN TRANSACTION . से शुरू होते हैं कथन और अंत COMMIT . के साथ या ROLLBACK बयान। |
ओरेकल | स्पष्ट लेन-देन SET TRANSACTION . से शुरू होते हैं कथन और अंत COMMIT . के साथ या ROLLBACK बयान। |
कई मामलों में, स्पष्ट लेनदेन का उपयोग करते समय कुछ कीवर्ड वैकल्पिक होते हैं। उदाहरण के लिए SQL सर्वर और SQLite में, आप बस BEGIN
. का उपयोग कर सकते हैं (BEGIN TRANSACTION
. के बजाय) ) और/या आप COMMIT TRANSACTION
. के साथ समाप्त कर सकते हैं (केवल COMMIT
. के विपरीत )।
कई अन्य कीवर्ड और विकल्प भी हैं जिन्हें आप लेन-देन बनाते समय निर्दिष्ट कर सकते हैं, इसलिए पूर्ण सिंटैक्स के लिए अपने DBMS के दस्तावेज़ देखें।
एसक्यूएल ट्रांजेक्शन उदाहरण
यहाँ SQL सर्वर में एक साधारण लेन-देन का एक उदाहरण दिया गया है:
BEGIN TRANSACTION
DELETE OrderItems WHERE OrderId = 5006;
DELETE Orders WHERE OrderId = 5006;
COMMIT TRANSACTION;
इस मामले में, आदेश जानकारी दो तालिकाओं से हटा दी जाती है। दोनों कथनों को कार्य की एक इकाई के रूप में माना जाता है।
त्रुटि की स्थिति में इसे रोलबैक करने के लिए हम अपने लेनदेन में सशर्त तर्क लिख सकते हैं।
लेनदेन का नामकरण
कुछ DBMS आपको अपने लेनदेन के लिए एक नाम प्रदान करने की अनुमति देते हैं। SQL सर्वर में, आप BEGIN
. के बाद अपना चुना हुआ नाम जोड़ सकते हैं और COMMIT
बयान।
BEGIN TRANSACTION MyTransaction
DELETE OrderItems WHERE OrderId = 5006;
DELETE Orders WHERE OrderId = 5006;
COMMIT TRANSACTION MyTransaction;
SQL ट्रांजैक्शन रोलबैक उदाहरण 1
यहां पिछला उदाहरण फिर से है, लेकिन कुछ अतिरिक्त कोड के साथ। त्रुटि की स्थिति में लेनदेन को रोलबैक करने के लिए अतिरिक्त कोड का उपयोग किया जाता है।:
BEGIN TRANSACTION MyTransaction
BEGIN TRY
DELETE OrderItems WHERE OrderId = 5006;
DELETE Orders WHERE OrderId = 5006;
COMMIT TRANSACTION MyTransaction
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION MyTransaction
END CATCH
TRY...CATCH
कथन SQL सर्वर में त्रुटि प्रबंधन को लागू करता है। आप T-SQL कथनों के किसी भी समूह को TRY
. में संलग्न कर सकते हैं खंड मैथा। फिर, यदि TRY
. में कोई त्रुटि होती है ब्लॉक, नियंत्रण बयानों के दूसरे समूह को दिया जाता है जो CATCH
. में संलग्न होता है ब्लॉक करें।
इस मामले में, हम CATCH
. का उपयोग करते हैं लेन-देन को रोलबैक करने के लिए ब्लॉक करें। यह CATCH
. में दिया गया है ब्लॉक करें, रोलबैक केवल तभी होता है जब कोई त्रुटि हो।
SQL ट्रांजैक्शन रोलबैक उदाहरण 2
आइए उस डेटाबेस पर करीब से नज़र डालें जिससे हमने अभी-अभी पंक्तियाँ हटाई हैं।
पिछले उदाहरण में, हमने Orders
. से पंक्तियों को हटा दिया था और OrderItems
निम्नलिखित डेटाबेस में टेबल:
इस डेटाबेस में, जब भी कोई ग्राहक कोई ऑर्डर देता है, तो Orders
. में एक पंक्ति डाली जाती है तालिका, और एक या अधिक पंक्तियाँ OrderItems
. में टेबल। OrderItems
. में डाली गई पंक्तियों की संख्या इस पर निर्भर करता है कि ग्राहक कितने अलग-अलग उत्पादों का ऑर्डर देता है।
साथ ही, यदि यह एक नया ग्राहक है, तो Customers
. में एक नई पंक्ति डाली जाती है टेबल।
उस स्थिति में, पंक्तियों को तीन तालिकाओं में सम्मिलित करने की आवश्यकता होती है।
विफलता की स्थिति में, हम Orders
में एक पंक्ति सम्मिलित नहीं करना चाहेंगे तालिका लेकिन OrderItems
में कोई संगत पंक्तियाँ नहीं हैं टेबल। इसका परिणाम बिना किसी ऑर्डर आइटम के ऑर्डर में होगा। मूल रूप से, हम चाहते हैं कि दोनों टेबल पूरी तरह से अपडेट हों या कुछ भी नहीं।
यह वही था जब हमने पंक्तियों को हटा दिया था। हम चाहते थे कि सभी पंक्तियों को हटा दिया जाए या कोई भी नहीं।
SQL सर्वर में, हम INSERT
. के लिए निम्नलिखित लेनदेन लिख सकते हैं बयान।
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Customers ( CustomerId, CustomerName, PostalAddress, City, StateProvince, ZipCode, Country, Phone )
VALUES (1006, 'Hi-Five Solutionists', '5 High Street', 'Highlands', 'HI', '1254', 'AUS', '(415) 413-5182');
INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
VALUES ( 5006, SYSDATETIME(), 1006 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 1, 1, 20, 25.99 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 2, 7, 120, 9.99 );
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
यह उदाहरण मानता है कि कहीं और तर्क है जो यह निर्धारित करता है कि ग्राहक पहले से डेटाबेस में मौजूद है या नहीं।
ग्राहक को इस लेन-देन के बाहर सम्मिलित किया जा सकता था:
INSERT INTO Customers ( CustomerId, CustomerName, PostalAddress, City, StateProvince, ZipCode, Country, Phone )
VALUES (1006, 'Hi-Five Solutionists', '5 High Street', 'Highlands', 'HI', '1254', 'AUS', '(415) 413-5182');
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
VALUES ( 5006, SYSDATETIME(), 1006 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 1, 1, 20, 25.99 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 2, 7, 120, 9.99 );
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
यदि लेन-देन विफल हो जाता है, तो ग्राहक अभी भी डेटाबेस में रहेगा (लेकिन बिना किसी आदेश के)। एप्लिकेशन को यह जांचना होगा कि लेनदेन करने से पहले ग्राहक पहले से मौजूद है या नहीं।
सेवपॉइंट के साथ SQL लेनदेन
एक सेवपॉइंट उस स्थान को परिभाषित करता है जहां लेनदेन का हिस्सा सशर्त रूप से रद्द होने पर लेनदेन वापस आ सकता है। SQL सर्वर में, हम SAVE TRANSACTION savepoint_name
(जहां savepoint_name वह नाम है जिसे हम सेवपॉइंट को देते हैं)।
सेवपॉइंट को शामिल करने के लिए पिछले उदाहरण को फिर से लिखें:
BEGIN TRANSACTION
INSERT INTO Customers ( CustomerId, CustomerName, PostalAddress, City, StateProvince, ZipCode, Country, Phone )
VALUES (1006, 'Hi-Five Solutionists', '5 High Street', 'Highlands', 'HI', '1254', 'AUS', '(415) 413-5182');
SAVE TRANSACTION StartOrder;
INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
VALUES ( 5006, SYSDATETIME(), 1006 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 1, 1, 20, 25.99 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 2, 7, 120, 9.99 );
ROLLBACK TRANSACTION StartOrder;
COMMIT TRANSACTION;
SELECT @@TRANCOUNT;
यहां, हमने ग्राहक के ठीक बाद एक बचत बिंदु सेट किया है INSERT
बयान। बाद में लेन-देन में, मैं ROLLBACK
. का उपयोग करता हूं लेन-देन को उस सेवपॉइंट पर रोलबैक करने का निर्देश देने के लिए कथन।
जब मैं उस कथन को चलाता हूं, तो ग्राहक सम्मिलित हो जाता है, लेकिन कोई भी आदेश जानकारी सम्मिलित नहीं की जाती है।
यदि कोई लेन-देन एक सेवपॉइंट पर वापस ले जाया जाता है, तो इसे जरूरत पड़ने पर अधिक SQL कथनों और COMMIT TRANSACTION
के साथ पूरा करने के लिए आगे बढ़ना चाहिए। बयान, या पूरे लेनदेन को वापस लेकर इसे पूरी तरह से रद्द कर दिया जाना चाहिए।
अगर मैं ROLLBACK
को स्थानांतरित करता/करती हूं पिछले INSERT
पर वापस विवरण बयान, इस तरह:
BEGIN TRANSACTION
INSERT INTO Customers ( CustomerId, CustomerName, PostalAddress, City, StateProvince, ZipCode, Country, Phone )
VALUES (1006, 'Hi-Five Solutionists', '5 High Street', 'Highlands', 'HI', '1254', 'AUS', '(415) 413-5182');
SAVE TRANSACTION StartOrder;
INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
VALUES ( 5006, SYSDATETIME(), 1006 );
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 1, 1, 20, 25.99 );
ROLLBACK TRANSACTION StartOrder;
INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
VALUES ( 5006, 2, 7, 120, 9.99 );
COMMIT TRANSACTION;
SELECT @@TRANCOUNT;
यह एक विदेशी कुंजी संघर्ष त्रुटि उत्पन्न करता है। विशेष रूप से, मुझे निम्न त्रुटि मिलती है:
(1 row affected) (1 row affected) (1 row affected) Msg 547, Level 16, State 0, Line 13 The INSERT statement conflicted with the FOREIGN KEY constraint "FK_OrderItems_Orders". The conflict occurred in database "KrankyKranes", table "dbo.Orders", column 'OrderId'. The statement has been terminated. (1 row affected)
ऐसा इसलिए हुआ क्योंकि, भले ही ऑर्डर पहले ही डाला जा चुका था, लेकिन जब हम सेवपॉइंट पर वापस आ गए तो वह ऑपरेशन पूर्ववत हो गया था। फिर लेनदेन पूरा होने के लिए आगे बढ़ा। लेकिन जब उसे अंतिम ऑर्डर आइटम का सामना करना पड़ा, तो कोई संबंधित ऑर्डर नहीं था (क्योंकि वह पूर्ववत किया गया था), और हमें त्रुटि मिली।
जब मैं डेटाबेस की जांच करता हूं, तो ग्राहक डाला गया था, लेकिन फिर से, कोई भी आदेश जानकारी नहीं डाली गई थी।
यदि आवश्यक हो तो आप लेन-देन में एक ही सेवपॉइंट को कई स्थानों से संदर्भित कर सकते हैं।
व्यवहार में, आप लेन-देन को एक सेवपोंट में वापस करने के लिए सशर्त प्रोग्रामिंग का उपयोग करेंगे।
नेस्टेड लेनदेन
यदि आवश्यक हो तो आप अन्य लेनदेन के अंदर लेनदेन को भी घोंसला बना सकते हैं।
इस तरह:
BEGIN TRANSACTION Transaction1;
UPDATE table1 ...;
BEGIN TRANSACTION Transaction2;
UPDATE table2 ...;
SELECT * from table1;
COMMIT TRANSACTION Transaction2;
UPDATE table3 ...;
COMMIT TRANSACTION Transaction1;
जैसा कि उल्लेख किया गया है, लेन-देन बनाने के लिए आप जिस सटीक सिंटैक्स का उपयोग करते हैं, वह आपके DBMS पर निर्भर करेगा, इसलिए SQL में लेनदेन बनाते समय अपने विकल्पों की पूरी तस्वीर के लिए अपने DBMS के दस्तावेज़ीकरण की जाँच करें।