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

जॉइन के साथ एसक्यूएल अपडेट स्टेटमेंट का उपयोग करने के लिए 5 नो-परेशानी युक्तियाँ

"उफ़! मेरा बुरा।" SQL अद्यतन के गलत होने के बाद आपने इसे कितनी बार कहा? बात यह है कि, यदि आप सावधान नहीं हैं, तो तालिका अद्यतन के DELETE कथन के रूप में गंभीर परिणाम हो सकते हैं। यदि आप जॉइन के साथ अद्यतन का उपयोग करके इसे जटिल बनाते हैं तो यह और भी खराब हो सकता है। इसलिए आपको Execute दबाने या CTRL-E दबाने से पहले इस पर विचार करने की आवश्यकता है।

तो, आज आप सीखेंगे कि बिना किसी झंझट के अपने SQL UPDATE को JOIN के साथ कैसे कोडित किया जाए और कभी भी "ओह! मेरा बुरा" फिर से।

लेकिन इससे पहले कि हम अभ्यास करें, हम वाक्य रचना से शुरू करते हैं। यह जॉइन के साथ SQL सर्वर अद्यतन के बारे में हमारे नए शौक को भी घर जैसा महसूस कराएगा। फिर, हम कुछ डेटा और कुछ उदाहरण तैयार करेंगे। और अंत में, सुरक्षा युक्तियों की जांच करें।

[sendpulse-form id="12968″]

एसक्यूएल जॉइन सिंटेक्स अपडेट करें

UPDATE table1
SET column1 = <expression1 | value1> [, column2 = <expression2 | value2>, <columnN = expression3 | value3>]
FROM table1
[INNER | OUTER LEFT | OUTER RIGHT] JOIN table2 on table1.keycolumn = table2.keycolumn
[WHERE condition]

हमें इसमें से कुछ बिंदुओं पर ध्यान देने की जरूरत है।

  1. हम कम से कम 1 कॉलम या कुछ कॉलम के लिए एक बार में एक टेबल अपडेट कर सकते हैं।
  2. जॉइन जोड़ने के लिए हमें FROM क्लॉज की जरूरत है। FROM क्लॉज में ऑब्जेक्ट अपडेट किए जा रहे ऑब्जेक्ट के समान हो भी सकता है और नहीं भी।
  3. हम इनर या आउटर जॉइन का उपयोग कर सकते हैं (उदाहरण बाद में देखें)।
  4. हम WHERE क्लॉज का उपयोग करके डेटा का केवल एक सबसेट अपडेट कर सकते हैं।

इससे पहले कि हमारे पास हमारे उदाहरण हों, आइए डेटा तैयार करें।

हमारा परीक्षण डेटा

चलचित्रों के प्रति प्रेम के लिए, आइए उपयोगकर्ता रेटिंग के साथ मूवी शीर्षकों का एक डेटाबेस बनाएँ।

CREATE DATABASE [Movies]
GO

USE [Movies]
GO

CREATE TABLE [dbo].[Titles](
	[TitleID] [int] IDENTITY(1,1) NOT NULL,
	[Title] [varchar](50) NOT NULL,
	[ReleaseDate] [date] NOT NULL,
	[OverallUserRating] [varchar](10) NULL,
 CONSTRAINT [PK_Titles] PRIMARY KEY CLUSTERED 
(
	[TitleID] ASC
))
GO

CREATE TABLE [dbo].[UserRatings](
	[UserRatingID] [int] IDENTITY(1,1) NOT NULL,
	[TitleID] [int] NOT NULL,
	[User] [varchar](50) NOT NULL,
	[Rating] [tinyint] NOT NULL,
 CONSTRAINT [PK_UserRatings] PRIMARY KEY CLUSTERED 
(
	[UserRatingID] ASC
))
GO

ALTER TABLE [dbo].[UserRatings]  WITH CHECK ADD  CONSTRAINT [FK_UserRatings_Titles] FOREIGN KEY([TitleID])
REFERENCES [dbo].[Titles] ([TitleID])
GO

ALTER TABLE [dbo].[UserRatings] CHECK CONSTRAINT [FK_UserRatings_Titles]
GO

ALTER TABLE [dbo].[UserRatings]  WITH CHECK ADD  CONSTRAINT [CK_UserRatings_Rating] CHECK  (([Rating]>=(1) AND [Rating]<=(5)))
GO

ALTER TABLE [dbo].[UserRatings] CHECK CONSTRAINT [CK_UserRatings_Rating]
GO

अब जबकि हमारे पास डेटाबेस और टेबल हैं, आइए कुछ डेटा डालें:

INSERT INTO Titles
(Title, ReleaseDate)
VALUES 
('The Avengers', '05/04/2012'),
('Avengers: Age of Ultron','5/1/2015'),
('Avengers: Infinity War','4/27/2018'),
('Avengers: Endgame','4/26/2019'),
('Captain America: Civil War','5/6/2016')
GO

INSERT INTO UserRatings(TitleID, [User], Rating) 
VALUES 
(1,'Natasha',5),
(1,'Bruce',3),
(1,'Tony',4),
(1,'Bucky',5),
(2,'Steve',4),
(2,'Wanda',3),
(2,'Pietro',2),
(2,'Clint',5),
(3,'Hope',5),
(3,'Sam',5),
(3,'Nick',3),
(3,'James',5),
(4,'Scott',5),
(4,'Wong',5),
(4,'Peter',5),
(4,'Carol',4),
(4,'Shuri',5)
GO

एसक्यूएल सर्वर अपडेट के साथ शामिल हों उदाहरण

हम OverallUserRating . को अपडेट करने के समान लक्ष्य वाले विभिन्न उदाहरणों की जांच करेंगे शीर्षकों . में टेबल। रेटिंग 1 से 5 तक हो सकती है। समग्र उपयोगकर्ता रेटिंग मूवी शीर्षक के लिए सभी रेटिंग का औसत है।

यहाँ तालिका की प्रारंभिक स्थिति है:

बाएं शामिल होने का उदाहरण अपडेट करें

-- SQL UPDATE with LEFT OUTER JOIN
SELECT
 a.TitleID
,CAST(CAST(AVG(CAST(b.Rating AS DECIMAL(3,2))) AS DECIMAL(3,2)) AS varchar(9)) AS AverageRating
INTO #ComputedRatings
FROM titles a
INNER JOIN UserRatings b ON a.TitleID = b.TitleID
GROUP BY a.TitleID

-- mark 'No Rating' if there are no existing ratings
UPDATE Titles
SET OverallUserRating = ISNULL(b.AverageRating,'No Rating') 
FROM Titles a
LEFT JOIN #ComputedRatings b ON a.TitleID = b.TitleID

पहला SELECT स्टेटमेंट UserRatings . के आधार पर प्रति मूवी शीर्षक औसत रेटिंग की गणना करता है टेबल। परिणाम #ComputedRatings . नामक एक अस्थायी तालिका में डाल दिया जाता है . जैसा कि हम इनर जॉइन का उपयोग करते हैं, बिना रेटिंग के मूवी शीर्षक छोड़ दिए जाते हैं।

अद्यतन विवरण में, शीर्षक #ComputedRatings . से LEFT JOIN का उपयोग करके तालिका को अपडेट किया गया था अस्थायी तालिका। यदि औसत रेटिंग शून्य है , मान कोई रेटिंग नहीं . बन जाता है . हमारे नमूने में, कप्तान अमेरिका:गृहयुद्ध अभी तक कोई उपयोगकर्ता रेटिंग नहीं है - चित्र 2 देखें।

एसक्यूएल अपडेट इनर जॉइन उदाहरण

यहां बताया गया है कि यह कैसे होता है:

-- SQL UPDATE with INNER JOIN
SELECT
 a.TitleID
,ISNULL(CAST(CAST(AVG(CAST(b.Rating AS DECIMAL(3,2))) AS DECIMAL(3,2)) AS varchar(9)),'No Rating')  AS AverageRating
INTO #ComputedRatings
FROM titles a
LEFT JOIN UserRatings b ON a.TitleID = b.TitleID
GROUP BY a.TitleID


UPDATE Titles
SET OverallUserRating = b.AverageRating
FROM Titles a
INNER JOIN #ComputedRatings b ON a.TitleID = b.TitleID

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

  • पहला SELECT स्टेटमेंट हमारे LEFT JOIN उदाहरण के विपरीत NULL यूजर रेटिंग पर विचार करता है। यह बिना उपयोगकर्ता रेटिंग के फिल्म के शीर्षक को नहीं छोड़ता है। तो, इस बार, कोई रेटिंग नहीं कप्तान अमेरिका:गृहयुद्ध . के लिए मूल्य पहले से ही माना जाता है।
  • एक इनर जॉइन औसत रेटिंग . के सीधे असाइनमेंट के साथ मान अधिक उपयुक्त है क्योंकि सभी TitleIDs के लिए जिम्मेदार हैं।

अब, एक अस्थायी तालिका के बजाय, सामान्य तालिका अभिव्यक्ति (CTE) का भी उपयोग किया जा सकता है। ये रहा संशोधित कोड:

-- SQL UPDATE with JOIN using INNER JOIN from a CTE
;WITH ComputedRatings AS
(SELECT
 a.TitleID
,ISNULL(CAST(CAST(AVG(CAST(b.Rating AS DECIMAL(3,2))) AS DECIMAL(3,2)) AS varchar(9)),'No Rating')  AS AverageRating
FROM Titles a
LEFT JOIN UserRatings b ON a.TitleID = b.TitleID
GROUP BY a.TitleID)
UPDATE Titles
SET OverallUserRating = b.AverageRating
FROM Titles t
INNER JOIN ComputedRatings cr ON t.TitleID = cr.TitleID

अधिक जानकारी

  • एसक्यूएल जॉइन के लिए आपकी अंतिम गाइड:इनर जॉइन - भाग 1
  • एसक्यूएल जॉइन के लिए आपकी अंतिम गाइड:बाहरी जॉइन - भाग 2

अपडेट का उपयोग करना कमांड शामिल होने के साथ सुरक्षित रूप से (5 टिप्स)

सुरक्षा का तात्पर्य इच्छित अभिलेखों को अद्यतन करना है। साथ ही, यह उन रिकॉर्ड्स को नहीं छूने के बारे में है जिन्हें हम अपडेट करने का इरादा नहीं रखते हैं। यहां, हम 5 परिदृश्यों से निपटेंगे:

सेलेक्ट स्टेटमेंट के साथ पहले रिकॉर्ड देखें

यह टिप कुछ रिकॉर्ड के लिए एकदम सही है। इसलिए, इससे पहले कि आप अद्यतन करने के लिए रिकॉर्ड्स को प्रभावित करें, यह प्रयास करें:

ऐसा करना आसान है. और अगर यह अच्छा लगता है, तो UPDATE और SET क्लॉज को अनकम्मेंट करें। एक टिप्पणी के रूप में चयन खंड को चिह्नित करें। फिर, आप जाने के लिए अच्छे हैं। इस तरह आप सक्रिय होने के कारण क्षति नियंत्रण को कम करते हैं।

अस्थायी तालिकाओं का उपयोग करके परीक्षण चलाएं

यदि कोई त्रुटि हो सकती है तो अनिश्चित महसूस कर रहे हैं? फिर उस तालिका रिकॉर्ड को डंप करने का प्रयास करें जिसे आप अस्थायी तालिका में अपडेट करना चाहते हैं। उसके बाद, वहां से ट्रायल रन करें।

क्या कोई रनटाइम त्रुटि नहीं है? क्या परिणाम अच्छे दिखते हैं? फिर, अस्थायी तालिका को मूल तालिका से बदलें। इस तरह, आप जानते हैं कि रास्ते में कोई रनटाइम त्रुटि नहीं होगी।

साथ ही, ध्यान दें कि अस्थायी तालिकाएँ मूल तालिकाओं की प्रतियों को संग्रहीत करने के तरीकों में से एक हैं। आप स्मृति-अनुकूलित तालिकाओं या डेटाबेस बैकअप का भी उपयोग कर सकते हैं। डेटाबेस बैकअप के साथ, आपको उन रिकॉर्ड्स के साथ खेलने की अधिक स्वतंत्रता है जिन्हें आपको अपडेट करने की आवश्यकता है। लेकिन इसका नकारात्मक पक्ष स्टोरेज स्पेस है।

अधिक जानकारी

  • तालिका बनाएं (लेनदेन-एसक्यूएल) - अस्थायी तालिकाएं

आउटपुट खंड को अद्यतन में जोड़ने का प्रयास करें

क्या आप अपडेट चलाने से पहले समय पर वापस जाना चाहते हैं? यदि आप उस संशयवादी हैं, तो आप OUTPUT क्लॉज का उपयोग कर सकते हैं और अतीत और वर्तमान को देख सकते हैं। नीचे दिए गए उदाहरण में, एक तालिका चर अद्यतन के बाद पिछले और वर्तमान मानों को डंप करने का कार्य करता है। फिर आप परिणाम देखने के लिए तालिका चर का चयन कर सकते हैं:

DECLARE @tvTitles AS TABLE(TitleID INT NOT NULL,
                           OldOverallRatings VARCHAR(10) NULL,
			    NewOverAllRatings varchar(10) NOT NULL)

;WITH ComputedRatings AS
(
	SELECT
	a.TitleID
	,ISNULL(CAST(CAST(AVG(CAST(b.Rating AS DECIMAL(3,2))) AS DECIMAL(3,2)) AS varchar(9)),'No Rating')  AS AverageRating
	FROM titles a
	LEFT JOIN UserRatings b ON a.TitleID = b.TitleID
	GROUP BY a.TitleID
)
UPDATE #tmpTitles
SET OverallUserRating = cr.AverageRating
OUTPUT INSERTED.TitleID, DELETED.OverallUserRating, INSERTED.OverallUserRating
INTO @tvTitles
FROM #tmpTitles t
INNER JOIN ComputedRatings cr ON t.TitleID = cr.TitleID

इस कोड के बारे में ध्यान देने योग्य कुछ बिंदु:

  • तालिका चर पिछले और वर्तमान मूल्यों के एक कंटेनर के रूप में काम करता है।
  • CTE के साथ सामान्य अपडेट क्रम में है। हम अभी भी सुरक्षित खेलने के लिए अस्थायी तालिका का उपयोग करते हैं।
  • आउटपुट क्लॉज पिछले और वर्तमान मानों को टेबल वेरिएबल में डंप करने के लिए लागू होता है। INSERTED में नए मान होते हैं, जबकि DELETED में पुराने मान होते हैं।

यदि आप तालिका चर से एक चयन जारी करते हैं, तो आप इसकी अपेक्षा कर सकते हैं:

परिणाम चित्र 3 जैसा है, लेकिन यह भविष्य को देखता है। यह अतीत में देखता है। अगर यह अलग है, तो बीच में कुछ गलत हो गया है।

अच्छी खबर यह है कि आप तालिका चर में पुराने मानों का उपयोग करके इसे अपनी पिछली स्थिति में पुनर्स्थापित कर सकते हैं। लेकिन अगर यह वही है, तो फिर, आप जाने के लिए अच्छे हैं। आप OUTPUT खंड को एक टिप्पणी के रूप में चिह्नित कर सकते हैं या इसे हटा सकते हैं, और फिर अस्थायी तालिका को मूल तालिका से बदल सकते हैं।

अधिक जानकारी

  • आउटपुट क्लॉज (ट्रांजैक्ट-एसक्यूएल)

TRY…CATCH का उपयोग भविष्य की त्रुटियों को संभालने के लिए करें

जब आप क्राफ्टिंग कर रहे हों और फिर अपने कोड का परीक्षण कर रहे हों तो पिछली 3 युक्तियाँ सहायक होती हैं। लेकिन हम सभी जानते हैं कि हम हर चीज का अनुमान नहीं लगा सकते। इस प्रकार, हमें कोड में और अधिक सुरक्षा जाल जोड़ने की आवश्यकता है।

सुरक्षा जाल की बात करें तो, T-SQL में TRY… CATCH एरर-हैंडलिंग ब्लॉक जैसे C# और C++ हैं।

आइए पिछले उदाहरण से संशोधित कोड देखें:

BEGIN TRY						  
  ;WITH ComputedRatings AS
  (
    SELECT
     a.TitleID
    ,ISNULL(CAST(CAST(AVG(CAST(b.Rating AS DECIMAL(3,2))) AS DECIMAL(3,2)) AS varchar(20)),
            'No User Ratings Yet') AS AverageRating
    FROM titles a
    LEFT JOIN UserRatings b ON a.TitleID = b.TitleID
    GROUP BY a.TitleID
  )
  UPDATE Titles
  SET OverallUserRating = cr.AverageRating
  FROM Titles t
  INNER JOIN ComputedRatings cr ON t.TitleID = cr.TitleID

END TRY
BEGIN CATCH
 SELECT  
  ERROR_NUMBER() AS ErrorNumber  
 ,ERROR_SEVERITY() AS ErrorSeverity  
 ,ERROR_STATE() AS ErrorState  
 ,ERROR_PROCEDURE() AS ErrorProcedure  
 ,ERROR_LINE() AS ErrorLine  
 ,ERROR_MESSAGE() AS ErrorMessage;  

END CATCH

मैंने स्ट्रिंग ट्रंकेशन त्रुटि को बाध्य करने के लिए उपरोक्त कोड बदल दिया है। समग्र उपयोगकर्ता रेटिंग शीर्षक . में कॉलम तालिका में केवल 10 वर्ण हो सकते हैं। सीटीई में, हमने इसे 20 अक्षरों में बदल दिया। यह फिट नहीं होगा। CATCH ब्लॉक त्रुटि के क्षण को अपने हाथ में ले लेगा और त्रुटि की जानकारी प्रदान करेगा।

ये रहा परिणाम:

हमने त्रुटि ट्रिगर की। यदि आपको रनटाइम के दौरान अप्रत्याशित त्रुटियों को पकड़ने की आवश्यकता है, तो इसे संभालने का यह एक तरीका है।

अधिक जानकारी

  • कोशिश करें…कैच (ट्रांजैक्ट-एसक्यूएल)

लेन-देन प्रबंधन का उपयोग करें

अंत में, लेनदेन। यह त्रुटि होने से पहले अपनी पिछली स्थिति में सब कुछ बहाल करना सुनिश्चित करता है, जिसमें UPDATE with JOIN और कोई अन्य DML स्टेटमेंट शामिल हैं। यह ऊपर दिए गए टिप #4 के लिए एक अच्छा अतिरिक्त है।

आइए लेन-देन को शामिल करने के लिए कोड को फिर से बदलें:

BEGIN TRANSACTION

BEGIN TRY						  
  ;WITH ComputedRatings AS
  (
    SELECT
     a.TitleID
    ,ISNULL(CAST(CAST(AVG(CAST(b.Rating AS DECIMAL(3,2))) AS DECIMAL(3,2)) AS varchar(20)),
            'No User Ratings Yet') AS AverageRating
    FROM titles a
    LEFT JOIN UserRatings b ON a.TitleID = b.TitleID
    GROUP BY a.TitleID
  )
  UPDATE Titles
  SET OverallUserRating = cr.AverageRating
  FROM Titles t
  INNER JOIN ComputedRatings cr ON t.TitleID = cr.TitleID

  COMMIT TRANSACTION
END TRY
BEGIN CATCH
 SELECT  
  ERROR_NUMBER() AS ErrorNumber  
 ,ERROR_SEVERITY() AS ErrorSeverity  
 ,ERROR_STATE() AS ErrorState  
 ,ERROR_PROCEDURE() AS ErrorProcedure  
 ,ERROR_LINE() AS ErrorLine  
 ,ERROR_MESSAGE() AS ErrorMessage;  

 ROLLBACK TRANSACTION
END CATCH

यह लेन-देन को छोड़कर पिछले उदाहरण जैसा ही है। इस प्रकार, यह एक स्ट्रिंग ट्रंकेशन त्रुटि को बाध्य करेगा। यह COMMIT TRANSACTION से आगे नहीं जाएगा, बल्कि CATCH ब्लॉक में ROLLBACK TRANSACTION के साथ मानों को उनके पिछले राज्यों में वापस लाने के लिए होगा।

अगर हम अपडेट, इंसर्ट और डिलीट के साथ सुरक्षित खेलना चाहते हैं तो यही तरीका है।

नोट :आप SQL सर्वर के लिए dbForge Studio की क्वेरी बिल्डर सुविधा का उपयोग करके आरेख में किसी भी क्वेरी को विज़ुअल रूप से डिज़ाइन कर सकते हैं।

अधिक जानकारी

  • टी-एसक्यूएल सर्वोत्तम अभ्यास
  • प्रो की तरह टी-एसक्यूएल क्वेरी कैसे लिखें

निष्कर्ष

आपने जॉइन के साथ SQL UPDATE का सिंटैक्स देखा है। उदाहरण और बिना किसी परेशानी के 5 सुझावों ने आपको और अधिक प्रबुद्ध किया। उदाहरण मौजूद उदाहरणों से आवश्यकताएं भिन्न हो सकती हैं, लेकिन आपको बात मिल गई है। आप अभी भी गलतियाँ कर सकते हैं। हालांकि, उन्हें शून्य के करीब कम करना संभव है।

क्यों न इन विचारों को अपनी स्थिति पर लागू करें?

अगर यह पोस्ट मददगार थी, तो बेझिझक इसे अपने पसंदीदा सोशल मीडिया प्लेटफॉर्म पर फैलाएं। और अगर आप कुछ बेहतरीन विचार जोड़ना चाहते हैं, तो टिप्पणी अनुभाग में आपका स्वागत है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. चाकू

  2. टी-एसक्यूएल बग, नुकसान, और सर्वोत्तम अभ्यास - नियतत्ववाद

  3. PHP डेटाबेस एब्स्ट्रैक्शन लेयर्स और CRUD प्लगइन्स की तुलना करना

  4. यदि आप अनुक्रमित दृश्यों और MERGE का उपयोग कर रहे हैं, तो कृपया इसे पढ़ें!

  5. एसक्यूएल, चयन का उपयोग कैसे करें