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

SQL सर्वर में CTE के लिए गाइड

सामान्य तालिका अभिव्यक्ति उर्फ CTE SQL सर्वर में T-SQL में एक अस्थायी परिणाम सेट प्रदान करता है। आप इसे SQL Select, SQL Insert, SQL Delete, या SQL Update Statement में संदर्भित कर सकते हैं।

विकल्प SQL सर्वर 2005 के बाद से उपलब्ध है, जिससे डेवलपर्स को कई जॉइन, एकत्रीकरण और डेटा फ़िल्टरिंग से जुड़े जटिल और लंबी क्वेरी लिखने में मदद मिलती है। आमतौर पर, डेवलपर्स टी-एसक्यूएल कोड लिखने के लिए सबक्वायरी का उपयोग करते हैं, और एसक्यूएल सर्वर इन सीटीई को अस्थायी रूप से मेमोरी में स्टोर करता है जब तक कि क्वेरी निष्पादन समाप्त नहीं हो जाता। एक बार क्वेरी समाप्त हो जाने पर, इसे स्मृति से हटा दिया जाता है।

SQL सर्वर में

CTE:सिंटैक्स

WITH <common_table_expression> ([column names])
AS
(
   <query_definition>
)
<operation>
  • यह एक सीटीई नाम का उपयोग करता है, इसे सिलेक्ट, इंसर्ट, अपडेट, डिलीट या मर्ज स्टेटमेंट करने के लिए संदर्भित करता है।
  • कॉलम नाम अल्पविराम से अलग किए गए हैं। उन्हें क्वेरी परिभाषा में परिभाषित कॉलम से मेल खाना चाहिए।
  • क्वेरी परिभाषा में एक टेबल से चुनिंदा स्टेटमेंट शामिल हैं या कई टेबल के बीच जुड़ते हैं।
  • परिणाम प्राप्त करने के लिए आप सीटीई अभिव्यक्ति नाम का उल्लेख कर सकते हैं।

उदाहरण के लिए, निम्नलिखित बुनियादी सीटीई क्वेरी निम्नलिखित भागों का उपयोग करती है:

  • सामान्य तालिका अभिव्यक्ति नाम - SalesCustomerData
  • कॉलम सूची - [ग्राहक आईडी], [प्रथम नाम], [अंतिम नाम], [कंपनी नाम], [ईमेल पता], [फोन]
  • क्वेरी परिभाषा में एक चयन कथन शामिल है जो [SalesLT] से डेटा प्राप्त करता है। [ग्राहक] तालिका
  • अंतिम भाग सीटीई अभिव्यक्ति पर चयन कथन का उपयोग करता है और जहां खंड का उपयोग करके रिकॉर्ड फ़िल्टर करता है।
WITH SalesCustomerdata ([CustomerID],[FirstName],[LastName],[CompanyName],[EmailAddress],[Phone])
AS(
SELECT [CustomerID]
      ,[FirstName]
      ,[LastName]
      ,[CompanyName]
      ,[EmailAddress]
      ,[Phone]
   FROM [SalesLT].[Customer] 
)
SELECT * FROM SalesCustomerdata where Firstname like 'Raj%' 
ORDER BY CustomerID desc

एक अन्य उदाहरण में, हम सीटीई से औसत कुल बिक्री की गणना करते हैं। क्वेरी परिभाषा में ग्रुप बाय क्लॉज शामिल है। बाद में, हम औसत मान की गणना के लिए AVG() फ़ंक्शन का उपयोग करते हैं।

WITH Salesdata ([SalesOrderID],[Total])
AS(
SELECT [SalesOrderID]
         ,count(*) AS total
          FROM [SalesLT].[SalesOrderHeader]
        GROUP BY [SalesOrderID]
)
SELECT avg(total) FROM salesdata

आप SQL तालिका में डेटा सम्मिलित करने के लिए CTE का उपयोग भी कर सकते हैं। CTE क्वेरी परिभाषा में वह आवश्यक डेटा शामिल होता है जिसे आप जॉइन का उपयोग करके मौजूदा तालिकाओं से प्राप्त कर सकते हैं। बाद में, लक्ष्य तालिका में डेटा डालने के लिए CTE को क्वेरी करें।

यहां हम CTE सेलेक्ट स्टेटमेंट के आउटपुट से [CTETest] नाम की एक नई टेबल बनाने के लिए SELECT INTO स्टेटमेंट का इस्तेमाल करते हैं।

WITH CTEDataInsert
AS 
(
SELECT
    p.[ProductID]
    ,p.[Name]
    ,pm.[Name] AS [ProductModel]
    ,pmx.[Culture]
    ,pd.[Description]
FROM [SalesLT].[Product] p
    INNER JOIN [SalesLT].[ProductModel] pm
    ON p.[ProductModelID] = pm.[ProductModelID]
    INNER JOIN [SalesLT].[ProductModelProductDescription] pmx
    ON pm.[ProductModelID] = pmx.[ProductModelID]
    INNER JOIN [SalesLT].[ProductDescription] pd
    ON pmx.[ProductDescriptionID] = pd.[ProductDescriptionID]
)
SELECT * INTO CTETest FROM CTEDataInsert
GO

आप एक मौजूदा तालिका भी निर्दिष्ट कर सकते हैं जो सम्मिलित डेटा के साथ कॉलम से मेल खाती है।

WITH CTEDataInsert
AS 
(
SELECT
    p.[ProductID]
    ,p.[Name]
    ,pm.[Name] AS [ProductModel]
    ,pmx.[Culture]
    ,pd.[Description]
FROM [SalesLT].[Product] p
    INNER JOIN [SalesLT].[ProductModel] pm
    ON p.[ProductModelID] = pm.[ProductModelID]
    INNER JOIN [SalesLT].[ProductModelProductDescription] pmx
    ON pm.[ProductModelID] = pmx.[ProductModelID]
    INNER JOIN [SalesLT].[ProductDescription] pd
    ON pmx.[ProductDescriptionID] = pd.[ProductDescriptionID]
)
INSERT into CTETest select * FROM CTEDataInsert
GO

आप सामान्य तालिका अभिव्यक्ति का उपयोग करके भी SQL तालिका में रिकॉर्ड को अपडेट या हटा सकते हैं। निम्नलिखित प्रश्न CTE के साथ DELETE और UPDATE स्टेटमेंट का उपयोग करते हैं।

CTE में विवरण अपडेट करें

WITH Salesdata ([SalesOrderID],[Freight])
AS(
SELECT [SalesOrderID]
         ,[Freight]
          FROM [SalesLT].[SalesOrderHeader]
        )
UPDATE SalesData SET [Freight]=100.00 WHERE [SalesOrderID]=71774
Go

CTE में स्टेटमेंट हटाएं

WITH Salesdata ([SalesOrderID],[Freight])
AS(
SELECT [SalesOrderID]
         ,[Freight]
          FROM [SalesLT].[SalesOrderHeader]
        )
delete SalesData  WHERE [SalesOrderID]=71774
GO
SELECT * FROM [SalesLT].[SalesOrderHeader] WHERE SalesOrderID=71774

एकाधिक CTE

आप टी-एसक्यूएल स्क्रिप्ट में कई सीटीई घोषित कर सकते हैं और उन पर जुड़ने के संचालन का उपयोग कर सकते हैं। एकाधिक सीटीई के लिए, टी-एसक्यूएल अल्पविराम का उपयोग विभाजक के रूप में करता है।

निम्नलिखित प्रश्न में, हमारे पास दो सीटीई हैं:

  1. सीटीईएसबिक्री
  2. सीटीईएसविवरण

बाद में, सेलेक्ट स्टेटमेंट में, हम दोनों CTE पर INNER JOIN का उपयोग करके परिणाम प्राप्त करते हैं।

WITH CTESales
AS 
(
SELECT
     p.[ProductID]
    ,p.[Name]
    ,pm.[Name] AS [ProductModel]
    ,pmx.[Culture]
    ,pmx.[ProductDescriptionID]
   FROM [SalesLT].[Product] p
    INNER JOIN [SalesLT].[ProductModel] pm
    ON p.[ProductModelID] = pm.[ProductModelID]
    INNER JOIN [SalesLT].[ProductModelProductDescription] pmx
    ON pm.[ProductModelID] = pmx.[ProductModelID]
    INNER JOIN [SalesLT].[ProductDescription] pd
    ON pmx.[ProductDescriptionID] = pd.[ProductDescriptionID]
),CTESalesDescription

AS (

SELECT  description AS describe,[ProductDescriptionID]
from [SalesLT].[ProductDescription]  
)

SELECT  productid, [Name],[ProductModel],describe
FROM CTESales 
INNER JOIN CTESalesDescription 
    ON 
CTESales.[ProductDescriptionID] = CTESalesDescription.[ProductDescriptionID]

पुनरावर्ती सामान्य तालिका अभिव्यक्तियां

रिकर्सिव सीटीई एक बार-बार प्रक्रियात्मक लूप में चलता है जब तक कि शर्त पूरी नहीं हो जाती। निम्नलिखित टी-एसक्यूएल उदाहरण एक आईडी काउंटर का उपयोग करता है और WHERE की शर्त पूरी होने तक रिकॉर्ड का चयन करता है।

Declare @ID int =1;
;with RecursiveCTE as  
   (  
      SELECT @ID as ID
        UNION ALL  
      SELECT  ID+ 1
  FROM  RecursiveCTE  
  WHERE ID <5
    )  
 
SELECT * FROM RecursiveCTE

SQL सर्वर में पुनरावर्ती CTE का एक अन्य उपयोग पदानुक्रमित डेटा प्रदर्शित करना है। मान लें कि हमारे पास एक कर्मचारी है तालिका, और इसमें सभी कर्मचारियों, उनके विभागों और उनके प्रबंधकों की आईडी के रिकॉर्ड हैं।

--Script Reference: Microsoft Docs

CREATE TABLE dbo.MyEmployees  
(  
EmployeeID SMALLINT NOT NULL,  
FirstName NVARCHAR(30)  NOT NULL,  
LastName  NVARCHAR(40) NOT NULL,  
Title NVARCHAR(50) NOT NULL,  
DeptID SMALLINT NOT NULL,  
ManagerID INT NULL,  
 CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC)   
);  
INSERT INTO dbo.MyEmployees VALUES   
 (1, N'Ken', N'Sánchez', N'Chief Executive Officer',16,NULL)  
,(273, N'Brian', N'Welcker', N'Vice President of Sales',3,1)  
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',3,273)  
,(275, N'Michael', N'Blythe', N'Sales Representative',3,274)  
,(276, N'Linda', N'Mitchell', N'Sales Representative',3,274)  
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',3,273)  
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',3,285)  
,(16,  N'David',N'Bradley', N'Marketing Manager', 4, 273)  
,(23,  N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);

अब, हमें कर्मचारी पदानुक्रम डेटा उत्पन्न करने की आवश्यकता है। हम चयन कथन में UNION ALL के साथ पुनरावर्ती CTE का उपयोग कर सकते हैं।

WITH DirectReports(Name, Title, EmployeeID, EmployeeLevel, Sort)  
AS (SELECT CONVERT(VARCHAR(255), e.FirstName + ' ' + e.LastName),  
        e.Title,  
        e.EmployeeID,  
        1,  
        CONVERT(VARCHAR(255), e.FirstName + ' ' + e.LastName)  
    FROM dbo.MyEmployees AS e  
    WHERE e.ManagerID IS NULL  
    UNION ALL  
    SELECT CONVERT(VARCHAR(255), REPLICATE ('|    ' , EmployeeLevel) +  
        e.FirstName + ' ' + e.LastName),  
        e.Title,  
        e.EmployeeID,  
        EmployeeLevel + 1,  
        CONVERT (VARCHAR(255), RTRIM(Sort) + '|    ' + FirstName + ' ' +   
                 LastName)  
    FROM dbo.MyEmployees AS e  
    JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID  
    )  
SELECT EmployeeID, Name, Title, EmployeeLevel  
FROM DirectReports   
ORDER BY Sort;

CTE नीचे दिखाए गए अनुसार कर्मचारी स्तर का विवरण देता है।

सामान्य तालिका अभिव्यक्तियों के संबंध में महत्वपूर्ण बिंदु

  • हम सीटीई का पुन:उपयोग नहीं कर सकते। इसका दायरा बाहरी SELECT, INSERT, UPDATE, या MERGE स्टेटमेंट तक सीमित है।
  • आप कई सीटीईएस का उपयोग कर सकते हैं; हालांकि, उन्हें UNION ALL, UNION, INTERSECT, या EXCERPT ऑपरेटरों का उपयोग करना चाहिए।
  • हम गैर-पुनरावर्ती सीटीई में कई सीटीई क्वेरी परिभाषाओं को परिभाषित कर सकते हैं।
  • हम CTE क्वेरी परिभाषा में ORDER BY (बिना टॉप के), INTO, OPTIONS क्लॉज को क्वेरी संकेत के साथ, और FOR BROWSE का उपयोग नहीं कर सकते।

उदाहरण के लिए, नीचे दी गई स्क्रिप्ट बिना टॉप क्लॉज के ORDER BY क्लॉज का इस्तेमाल करती है।

WITH CTEDataInsert
AS 
(
SELECT
    p.[ProductID]
    ,p.[Name]
    ,pm.[Name] AS [ProductModel]
    ,pmx.[Culture]
    ,pd.[Description]
FROM [SalesLT].[Product] p
    INNER JOIN [SalesLT].[ProductModel] pm
    ON p.[ProductModelID] = pm.[ProductModelID]
    INNER JOIN [SalesLT].[ProductModelProductDescription] pmx
    ON pm.[ProductModelID] = pmx.[ProductModelID]
    INNER JOIN [SalesLT].[ProductDescription] pd
    ON pmx.[ProductDescriptionID] = pd.[ProductDescriptionID]
    ORDER BY productid
)
select * FROM CTEDataInsert 
GO

यह निम्न त्रुटि देता है:

  • हम सीटीई पर एक इंडेक्स नहीं बना सकते।
  • CTE में परिभाषित कॉलम नाम चुनिंदा स्टेटमेंट में दिए गए कॉलम से मेल खाना चाहिए।

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

  • यदि आपके पास टी-एसक्यूएल स्क्रिप्ट में एक से अधिक स्टेटमेंट हैं, तो सीटीई से पहले के पिछले स्टेटमेंट को अर्धविराम का उपयोग करके समाप्त कर देना चाहिए।

उदाहरण के लिए, पहले चयन कथन में अर्धविराम शामिल नहीं है। इसलिए, आपको एक गलत सिंटैक्स त्रुटि मिलती है सीटीई लिपि में।

यदि हम अर्धविराम ऑपरेटर का उपयोग करके पहले चयन कथन को समाप्त करते हैं तो स्क्रिप्ट ठीक काम करती है।

  • अगर हम कॉलम के नाम को बाहरी रूप से घोषित नहीं करते हैं, तो हम सेलेक्ट स्टेटमेंट में डुप्लीकेट कॉलम का उपयोग नहीं कर सकते।

उदाहरण के लिए, निम्नलिखित सीटीई परिभाषा डुप्लिकेट कॉलम [फ़ोन] निर्दिष्ट करती है। यह एक त्रुटि देता है।

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

महत्वपूर्ण:सामान्य तालिका अभिव्यक्तियाँ (CTE) अस्थायी तालिकाओं या तालिका चर के लिए प्रतिस्थापन नहीं हैं।

  • TempDB में अस्थायी तालिकाएँ बनती हैं, और हम एक नियमित तालिका के समान सूचकांक बाधाओं को परिभाषित कर सकते हैं। हम एक सत्र में कई बार अस्थायी तालिका का संदर्भ नहीं दे सकते हैं
  • टेमपडीबी में टेबल वेरिएबल भी मौजूद हैं और बैच निष्पादन के दौरान मौजूद वेरिएबल की तरह कार्य करते हैं। हम टेबल वेरिएबल पर एक इंडेक्स को परिभाषित नहीं कर सकते हैं।
  • CTE एक ही संदर्भ उद्देश्य के लिए है, और हम इस पर अनुक्रमणिका को परिभाषित नहीं कर सकते हैं। यह स्मृति में मौजूद रहता है और संदर्भ दिए जाने के बाद छोड़ दिया जाता है।

निष्कर्ष

कॉमन टेबल एक्सप्रेशंस (CTE) डेवलपर्स को स्वच्छ और प्रभावी कोड लिखने की अनुमति देता है। आम तौर पर, आप सीटीई का उपयोग कर सकते हैं जहां आपको अस्थायी तालिका जैसे एकाधिक संदर्भों की आवश्यकता नहीं होती है, और हमने चयन, सम्मिलित, अद्यतन, डीईटीईएलटीई कथन, और रिकर्सिव सीटीई के लिए विभिन्न परिदृश्यों का पता लगाया।

SQL कम्प्लीट SSMS ऐड-इन जैसे आधुनिक टूल की मदद से CTE को हैंडल करना और भी आसान हो जाता है। ऐड-इन सीटीई को तुरंत सुझा सकता है, इस प्रकार सीटीई से जुड़े कार्यों को और अधिक सरल बना देता है। साथ ही, CTE के बारे में अधिक जानकारी के लिए Microsoft दस्तावेज़ देखें।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर एक्सप्रेस की सीमाएं

  2. NVARCHAR(MAX) के लिए अधिकतम वर्ण क्या हैं?

  3. दो SQL सर्वर डेटाबेस (स्कीमा और डेटा) की तुलना करने के लिए सबसे अच्छा उपकरण क्या है?

  4. विदेशी कुंजी बाधा चक्र या एकाधिक कैस्केड पथ का कारण बन सकती है?

  5. MS SQL सर्वर डेटाबेस में स्वचालित अनुक्रमणिका डीफ़्रेग्मेंटेशन