Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini berisi panduan penting untuk menggunakan tabel sementara dan menyoroti prinsip-prinsip tabel sementara tingkat sesi.
Menggunakan informasi dalam artikel ini dapat membantu Anda memodulasi kode Anda, meningkatkan penggunaan kembali dan kemudahan pemeliharaan.
Apa itu tabel sementara?
Tabel sementara berguna saat memproses data, terutama selama transformasi di mana hasil perantara bersifat sementara. Di kumpulan SQL khusus, tabel sementara ada di tingkat sesi.
Tabel sementara hanya terlihat oleh sesi tempat tabel dibuat dan secara otomatis dihilangkan ketika sesi tersebut ditutup.
Tabel sementara menawarkan manfaat performa karena hasilnya ditulis ke penyimpanan lokal daripada penyimpanan jarak jauh.
Tabel sementara di kumpulan SQL khusus
Dalam sumber daya kumpulan SQL khusus, tabel sementara menawarkan manfaat performa karena hasilnya ditulis ke penyimpanan lokal daripada penyimpanan jarak jauh.
Membuat tabel sementara
Tabel sementara dibuat dengan awalan nama tabel Anda dengan #. Contohnya:
CREATE TABLE #stats_ddl
(
[schema_name] NVARCHAR(128) NOT NULL
, [table_name] NVARCHAR(128) NOT NULL
, [stats_name] NVARCHAR(128) NOT NULL
, [stats_is_filtered] BIT NOT NULL
, [seq_nmbr] BIGINT NOT NULL
, [two_part_name] NVARCHAR(260) NOT NULL
, [three_part_name] NVARCHAR(400) NOT NULL
)
WITH
(
DISTRIBUTION = HASH([seq_nmbr])
, HEAP
)
Tabel sementara juga dapat dibuat dengan CTAS menggunakan pendekatan yang sama persis:
CREATE TABLE #stats_ddl
WITH
(
DISTRIBUTION = HASH([seq_nmbr])
, HEAP
)
AS
(
SELECT
sm.[name] AS [schema_name]
, tb.[name] AS [table_name]
, st.[name] AS [stats_name]
, st.[has_filter] AS [stats_is_filtered]
, ROW_NUMBER()
OVER(ORDER BY (SELECT NULL)) AS [seq_nmbr]
, QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name]) AS [two_part_name]
, QUOTENAME(DB_NAME())+'.'+QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name]) AS [three_part_name]
FROM sys.objects AS ob
JOIN sys.stats AS st ON ob.[object_id] = st.[object_id]
JOIN sys.stats_columns AS sc ON st.[stats_id] = sc.[stats_id]
AND st.[object_id] = sc.[object_id]
JOIN sys.columns AS co ON sc.[column_id] = co.[column_id]
AND sc.[object_id] = co.[object_id]
JOIN sys.tables AS tb ON co.[object_id] = tb.[object_id]
JOIN sys.schemas AS sm ON tb.[schema_id] = sm.[schema_id]
WHERE 1=1
AND st.[user_created] = 1
GROUP BY
sm.[name]
, tb.[name]
, st.[name]
, st.[filter_definition]
, st.[has_filter]
)
;
Nota
CTAS adalah perintah yang kuat dan memiliki keuntungan tambahan untuk menjadi efisien dalam penggunaan ruang log transaksi.
Menghilangkan tabel sementara
Ketika sesi baru dibuat, tidak boleh ada tabel sementara.
Jika Anda memanggil prosedur tersimpan yang sama, yang membuat tabel sementara dengan nama yang sama, untuk memastikan bahwa pernyataan CREATE TABLE Anda berhasil, pemeriksaan keberadaan sederhana sebelumnya dengan DROP dapat digunakan seperti dalam contoh berikut.
IF OBJECT_ID('tempdb..#stats_ddl') IS NOT NULL
BEGIN
DROP TABLE #stats_ddl
END
Untuk konsistensi pengkodian, ini adalah praktik yang baik untuk menggunakan pola ini untuk tabel dan tabel sementara. Ada baiknya juga menggunakan DROP TABLE untuk menghapus tabel sementara ketika Anda telah selesai dengan tabel tersebut dalam kode Anda.
Dalam pengembangan prosedur simpanan, umumnya perintah drop digabungkan di akhir prosedur untuk memastikan pembersihan objek.
DROP TABLE #stats_ddl
Memodularisasi kode
Karena tabel sementara dapat dilihat di mana saja dalam sesi pengguna, kemampuan ini dapat dimanfaat untuk membantu Anda memodulasi kode aplikasi Anda.
Misalnya, prosedur tersimpan berikut menghasilkan DDL untuk memperbarui semua statistik dalam database berdasarkan nama statistik:
CREATE PROCEDURE [dbo].[prc_sqldw_update_stats]
( @update_type tinyint -- 1 default 2 fullscan 3 sample 4 resample
,@sample_pct tinyint
)
AS
IF @update_type NOT IN (1,2,3,4)
BEGIN;
THROW 151000,'Invalid value for @update_type parameter. Valid range 1 (default), 2 (fullscan), 3 (sample) or 4 (resample).',1;
END;
IF @sample_pct IS NULL
BEGIN;
SET @sample_pct = 20;
END;
IF OBJECT_ID('tempdb..#stats_ddl') IS NOT NULL
BEGIN
DROP TABLE #stats_ddl
END
CREATE TABLE #stats_ddl
WITH
(
DISTRIBUTION = HASH([seq_nmbr])
)
AS
(
SELECT
sm.[name] AS [schema_name]
, tb.[name] AS [table_name]
, st.[name] AS [stats_name]
, st.[has_filter] AS [stats_is_filtered]
, ROW_NUMBER()
OVER(ORDER BY (SELECT NULL)) AS [seq_nmbr]
, QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name]) AS [two_part_name]
, QUOTENAME(DB_NAME())+'.'+QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name]) AS [three_part_name]
FROM sys.objects AS ob
JOIN sys.stats AS st ON ob.[object_id] = st.[object_id]
JOIN sys.stats_columns AS sc ON st.[stats_id] = sc.[stats_id]
AND st.[object_id] = sc.[object_id]
JOIN sys.columns AS co ON sc.[column_id] = co.[column_id]
AND sc.[object_id] = co.[object_id]
JOIN sys.tables AS tb ON co.[object_id] = tb.[object_id]
JOIN sys.schemas AS sm ON tb.[schema_id] = sm.[schema_id]
WHERE 1=1
AND st.[user_created] = 1
GROUP BY
sm.[name]
, tb.[name]
, st.[name]
, st.[filter_definition]
, st.[has_filter]
)
SELECT
CASE @update_type
WHEN 1
THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+');'
WHEN 2
THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+') WITH FULLSCAN;'
WHEN 3
THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+') WITH SAMPLE '+CAST(@sample_pct AS VARCHAR(20))+' PERCENT;'
WHEN 4
THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+') WITH RESAMPLE;'
END AS [update_stats_ddl]
, [seq_nmbr]
FROM #stats_ddl
;
GO
Pada tahap ini, satu-satunya tindakan yang telah terjadi adalah pembuatan prosedur tersimpan yang menghasilkan tabel sementara, #stats_ddl, dengan pernyataan DDL.
Prosedur tersimpan ini menghapus #stats_ddl yang sudah ada agar tidak mengalami kegagalan jika dijalankan lebih dari sekali dalam sesi.
Namun, karena tidak ada DROP TABLE di akhir prosedur tersimpan, ketika prosedur tersimpan selesai, tabel yang dibuat dibiarkan sehingga dapat dibaca di luar prosedur tersimpan.
Di kumpulan SQL khusus, tidak seperti database SQL Server lainnya, dimungkinkan untuk menggunakan tabel sementara di luar prosedur yang membuatnya. Tabel sementara kumpulan SQL khusus dapat digunakan di mana saja di dalam sesi. Fitur ini dapat menyebabkan kode yang lebih modular dan dapat dikelola seperti dalam contoh berikut:
EXEC [dbo].[prc_sqldw_update_stats] @update_type = 1, @sample_pct = NULL;
DECLARE @i INT = 1
, @t INT = (SELECT COUNT(*) FROM #stats_ddl)
, @s NVARCHAR(4000) = N''
WHILE @i <= @t
BEGIN
SET @s=(SELECT update_stats_ddl FROM #stats_ddl WHERE seq_nmbr = @i);
PRINT @s
EXEC sp_executesql @s
SET @i+=1;
END
DROP TABLE #stats_ddl;
Batasan tabel sementara
Kumpulan SQL khusus memang memberlakukan beberapa batasan saat menerapkan tabel sementara. Saat ini, hanya tabel sementara dengan cakupan sesi yang didukung. Tabel Global Sementara tidak didukung.
Selain itu, tampilan tidak dapat dibuat pada tabel sementara. Tabel sementara hanya dapat dibuat dengan distribusi "hash" atau "round robin". Distribusi tabel sementara yang direplikasi tidak didukung.
Langkah berikutnya
Untuk mempelajari selengkapnya tentang mengembangkan tabel, lihat artikel Merancang tabel menggunakan kumpulan SQL khusus .