Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Panduan untuk CTE di SQL Server

Ekspresi Tabel Umum alias CTE di SQL Server memberikan hasil sementara yang ditetapkan dalam T-SQL. Anda dapat merujuknya dalam pernyataan SQL Select, SQL Insert, SQL Delete, atau SQL Update.

Opsi ini tersedia mulai dari SQL Server 2005 dan seterusnya, membantu pengembang menulis kueri yang kompleks dan panjang yang melibatkan banyak GABUNG, agregasi, dan pemfilteran data. Biasanya, pengembang menggunakan subkueri untuk menulis kode T-SQL, dan SQL Server menyimpan CTE ini dalam memori sementara hingga eksekusi kueri selesai. Setelah kueri selesai, kueri akan dihapus dari memori.

CTE di SQL Server:Sintaks

WITH <common_table_expression> ([column names])
AS
(
   <query_definition>
)
<operation>
  • Ini menggunakan nama CTE untuk merujuknya untuk melakukan pernyataan Pilih, Sisipkan, Perbarui, Hapus, atau Gabungkan.
  • Nama kolom dipisahkan dengan koma. Mereka harus cocok dengan kolom yang ditentukan dalam definisi kueri.
  • Definisi kueri melibatkan pernyataan pilih dari satu tabel atau gabungan antara beberapa tabel.
  • Anda dapat merujuk ke nama ekspresi CTE untuk mengambil hasil.

Misalnya, kueri CTE dasar berikut menggunakan bagian berikut:

  • Nama Ekspresi Tabel Umum – SalesCustomerData
  • Daftar kolom – [CustomerID],[FirstName],[LastName],[CompanyName],[EmailAddress],[Phone]
  • Definisi kueri mencakup pernyataan pemilihan yang mendapatkan data dari tabel [SalesLT].[Pelanggan]
  • Bagian terakhir menggunakan pernyataan pilih pada ekspresi CTE dan menyaring rekaman menggunakan klausa where.
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

Dalam contoh lain, kami menghitung total penjualan rata-rata dari CTE. Definisi kueri mencakup klausa GROUP BY. Kemudian, kami menggunakan fungsi AVG() untuk menghitung nilai rata-rata.

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

Anda juga dapat menggunakan CTE untuk memasukkan data ke dalam tabel SQL. Definisi kueri CTE menyertakan data yang diperlukan yang dapat Anda ambil dari tabel yang ada menggunakan gabungan. Kemudian, kueri CTE untuk memasukkan data ke dalam tabel target.

Di sini kita menggunakan pernyataan SELECT INTO untuk membuat tabel baru bernama [CTETest] dari output pernyataan pilih CTE.

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

Anda juga dapat menentukan tabel yang ada yang cocok dengan kolom dengan data yang dimasukkan.

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

Anda dapat memperbarui atau menghapus catatan dalam tabel SQL menggunakan ekspresi tabel umum juga. Kueri berikut menggunakan pernyataan DELETE dan UPDATE dengan CTE.

Perbarui Pernyataan di CTE

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

Hapus Pernyataan di 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

Beberapa CTE

Anda dapat mendeklarasikan beberapa CTE dalam skrip T-SQL dan menggunakan operasi gabungan pada mereka. Untuk beberapa CTE, T-SQL menggunakan koma sebagai pemisah.

Dalam kueri berikut, kami memiliki dua CTE:

  1. Penjualan CTE
  2. Deskripsi CTESales

Kemudian, dalam pernyataan pilih, kami mengambil hasil menggunakan INNER JOIN pada kedua CTE.

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]

Ekspresi Tabel Umum Rekursif

CTE Rekursif berjalan dalam loop prosedural berulang sampai kondisi terpenuhi. Contoh T-SQL berikut menggunakan penghitung ID dan memilih record hingga kondisi WHERE terpenuhi.

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

Penggunaan lain dari CTE rekursif di SQL Server adalah untuk menampilkan data hierarkis. Asumsikan bahwa kita memiliki karyawan tabel, dan memiliki catatan untuk semua karyawan, departemen mereka, dan ID manajer mereka.

--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);

Sekarang, kita perlu membuat data hierarki karyawan. Kita dapat menggunakan CTE rekursif dengan UNION ALL dalam pernyataan pilih.

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 mengembalikan detail tingkat karyawan seperti yang ditunjukkan di bawah ini.

Poin Penting Mengenai Persamaan Tabel Umum

  • Kami tidak dapat menggunakan kembali CTE. Cakupannya terbatas pada pernyataan SELECT, INSERT, UPDATE, atau MERGE luar.
  • Anda dapat menggunakan beberapa CTE; namun, mereka harus menggunakan operator UNION ALL, UNION, INTERSECT, atau EXCERPT.
  • Kita dapat mendefinisikan beberapa definisi kueri CTE dalam CTE non-rekursif.
  • Kami tidak dapat menggunakan ORDER BY (tanpa TOP), INTO, klausa OPTIONS dengan petunjuk kueri, dan FOR BROWSE dalam definisi kueri CTE.

Misalnya, skrip di bawah ini menggunakan klausa ORDER BY tanpa klausa TOP.

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

Ini memberikan kesalahan berikut:

  • Kami tidak dapat membuat indeks di CTE.
  • Nama kolom yang ditentukan dalam CTE harus cocok dengan kolom yang dikembalikan dalam pernyataan pilih.

CTE tidak memiliki kolom [Telepon] dalam kode di bawah ini sementara pernyataan pilih mengembalikan nilainya. Oleh karena itu, Anda mendapatkan pesan kesalahan yang disorot.

  • Jika Anda memiliki beberapa pernyataan dalam skrip T-SQL, pernyataan sebelumnya sebelum CTE harus diakhiri dengan menggunakan titik koma.

Misalnya, pernyataan pilih pertama tidak menyertakan titik koma. Oleh karena itu, Anda mendapatkan kesalahan sintaks yang salah dalam skrip CTE.

Script berfungsi dengan baik jika kita menghentikan pernyataan pilih pertama menggunakan operator titik koma.

  • Kami tidak dapat menggunakan kolom duplikat dalam pernyataan pilih jika kami tidak mendeklarasikan nama kolom secara eksternal.

Misalnya, definisi CTE berikut menentukan kolom duplikat [Telepon]. Ini mengembalikan kesalahan.

Namun, jika Anda menentukan kolom eksternal, itu tidak akan menyebabkan kesalahan. Ini diperlukan saat Anda membutuhkan satu kolom beberapa kali dalam output untuk perhitungan yang berbeda.

Penting:Common Table Expressions (CTE) bukan pengganti tabel temp atau variabel tabel.

  • Tabel sementara dibuat di TempDB, dan kita dapat mendefinisikan batasan indeks yang mirip dengan tabel biasa. Kami tidak dapat mereferensikan tabel temp beberapa kali dalam satu sesi
  • Variabel tabel juga ada di TempDB dan bertindak seperti variabel yang ada selama eksekusi batch. Kami tidak dapat mendefinisikan indeks pada variabel tabel.
  • CTE adalah untuk tujuan referensi tunggal, dan kami tidak dapat menentukan indeks di dalamnya. Itu ada dalam memori dan dijatuhkan setelah referensi dibuat.

Kesimpulan

Common Table Expressions (CTE) memungkinkan pengembang untuk menulis kode yang bersih dan efektif. Secara umum, Anda dapat menggunakan CTE di mana Anda tidak memerlukan banyak referensi seperti tabel sementara, dan kami menjelajahi berbagai skenario untuk pernyataan SELECT, INSERT, UPDATE, DETELTE, dan rekursif.

Dengan bantuan alat modern, seperti SQL Complete SSMS Add-in, penanganan CTE menjadi lebih mudah. Add-in dapat menyarankan CTE dengan cepat, sehingga membuat tugas yang melibatkan CTE jauh lebih mudah. Lihat juga dokumentasi Microsoft untuk detail selengkapnya tentang CTE.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cuplikan Basis Data SQL Server -1

  2. konversikan Nomor Seri Tanggal Excel ke Tanggal Reguler

  3. Apa Makna Pembelajaran Mesin bagi Profesional Basis Data

  4. DENGAN CHECK ADD CONSTRAINT diikuti oleh CHECK CONSTRAINT vs. ADD CONSTRAINT

  5. Cara mendapatkan daftar kolom dengan Batasan Unik di Database SQL Server - Tutorial SQL Server / TSQL Bagian 98