Meskipun mereka datang dengan banyak batasan dan beberapa peringatan implementasi penting, tampilan yang diindeks masih merupakan fitur SQL Server yang sangat kuat ketika digunakan dengan benar dalam situasi yang tepat. Salah satu penggunaan yang umum adalah untuk memberikan tampilan pra-agregasi dari data pokok, memberikan pengguna kemampuan untuk melakukan kueri hasil secara langsung tanpa menimbulkan biaya pemrosesan gabungan, filter, dan agregat yang mendasari setiap kali kueri dijalankan.
Meskipun fitur Edisi Perusahaan baru seperti penyimpanan kolumnar dan pemrosesan mode batch telah mengubah karakteristik kinerja banyak kueri besar jenis ini, masih tidak ada cara yang lebih cepat untuk mendapatkan hasil selain menghindari semua pemrosesan yang mendasarinya sepenuhnya, tidak peduli seberapa efisien pemrosesan itu. mungkin telah menjadi.
Sebelum tampilan yang diindeks (dan sepupunya yang lebih terbatas, kolom yang dihitung) ditambahkan ke produk, profesional basis data terkadang menulis kode multi-pemicu kompleks untuk menyajikan hasil kueri penting dalam tabel nyata. Pengaturan semacam ini sangat sulit untuk dilakukan dengan benar dalam semua keadaan, terutama jika sering terjadi perubahan serentak pada data yang mendasarinya.
Fitur tampilan yang diindeks membuat semua ini lebih mudah, di mana itu diterapkan dengan bijaksana dan benar. Mesin database menangani semua yang diperlukan untuk memastikan data yang dibaca dari tampilan yang diindeks selalu cocok dengan kueri dan data tabel yang mendasarinya.
Pemeliharaan Inkremental
SQL Server menyimpan data tampilan yang diindeks disinkronkan dengan kueri yang mendasarinya dengan secara otomatis memperbarui indeks tampilan dengan tepat setiap kali data berubah dalam tabel dasar. Biaya kegiatan pemeliharaan ini ditanggung oleh proses pengubahan basis data. Operasi ekstra yang diperlukan untuk mempertahankan indeks tampilan ditambahkan secara diam-diam ke rencana eksekusi untuk operasi penyisipan, pembaruan, penghapusan, atau penggabungan asli. Di latar belakang, SQL Server juga menangani masalah yang lebih halus terkait isolasi transaksi, misalnya memastikan penanganan yang benar untuk transaksi yang berjalan di bawah snapshot atau membaca isolasi snapshot yang dilakukan.
Membangun operasi rencana eksekusi ekstra yang diperlukan untuk mempertahankan indeks tampilan dengan benar bukanlah masalah sepele, karena siapa pun yang telah mencoba implementasi "tabel ringkasan yang dikelola oleh kode pemicu" akan mengetahuinya. Kompleksitas tugas adalah salah satu alasan mengapa tampilan yang diindeks memiliki begitu banyak batasan. Membatasi area permukaan yang didukung ke sambungan dalam, proyeksi, pilihan (filter), dan agregat SUM dan COUNT_BIG mengurangi kerumitan implementasi secara signifikan.
Tampilan yang diindeks dipertahankan secara bertahap . Ini berarti pemroses kueri menentukan efek bersih dari perubahan tabel dasar pada tampilan, dan hanya menerapkan perubahan yang diperlukan untuk memperbarui tampilan. Dalam kasus sederhana, ia dapat menghitung delta yang diperlukan hanya dari perubahan tabel dasar dan data yang saat ini disimpan dalam tampilan. Jika definisi tampilan berisi gabungan, bagian pemeliharaan tampilan terindeks dari rencana eksekusi juga perlu mengakses tabel gabungan, tetapi ini biasanya dapat dilakukan secara efisien, dengan indeks tabel dasar yang sesuai.
Untuk menyederhanakan implementasi lebih lanjut, SQL Server selalu menggunakan bentuk rencana dasar yang sama (sebagai titik awal) untuk mengimplementasikan operasi pemeliharaan tampilan terindeks. Fasilitas normal yang disediakan oleh pengoptimal kueri digunakan untuk menyederhanakan dan mengoptimalkan bentuk pemeliharaan standar yang sesuai. Sekarang kita akan beralih ke contoh untuk membantu menyatukan konsep-konsep ini.
Contoh 1 – Sisipan Baris Tunggal
Misalkan kita memiliki tabel sederhana berikut dan tampilan terindeks:
CREATE TABLE dbo.T1 ( GroupID integer NOT NULL, Value integer NOT NULL ); GO INSERT dbo.T1 (GroupID, Value) VALUES (1, 1), (1, 2), (2, 3), (2, 4), (2, 5); GO CREATE VIEW dbo.IV WITH SCHEMABINDING AS SELECT T1.GroupID, SumValue = SUM(T1.Value), NumRows = COUNT_BIG(*) FROM dbo.T1 AS T1 WHERE T1.GroupID BETWEEN 1 AND 5 GROUP BY T1.GroupID; GO CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.IV (GroupID);
Setelah script tersebut dijalankan, data pada tabel sampel akan terlihat seperti ini:
Dan tampilan Terindeks berisi:
Contoh paling sederhana dari rencana pemeliharaan tampilan terindeks untuk penyiapan ini terjadi saat kita menambahkan satu baris ke tabel dasar:
INSERT dbo.T1 (GroupID, Value) VALUES (3, 6);
Rencana eksekusi untuk sisipan ini ditunjukkan di bawah ini:
Mengikuti angka-angka dalam diagram, operasi rencana eksekusi ini berlangsung sebagai berikut:
- Operator Sisipkan Tabel menambahkan baris baru ke tabel dasar. Ini adalah satu-satunya operator paket yang terkait dengan sisipan tabel dasar; semua operator yang tersisa peduli dengan pemeliharaan tampilan yang diindeks.
- Eager Table Spool menyimpan data baris yang dimasukkan ke penyimpanan sementara.
- Operator Urutan memastikan cabang teratas dari rencana berjalan sampai selesai sebelum cabang berikutnya dalam Urutan diaktifkan. Dalam kasus khusus ini (menyisipkan satu baris), akan valid untuk menghapus Urutan (dan gulungan di posisi 2 dan 4), secara langsung menghubungkan input Agregat Aliran ke output Sisipan Tabel. Pengoptimalan yang memungkinkan ini tidak diterapkan, sehingga Urutan dan Kumparan tetap ada.
- Spool Tabel Eager ini dikaitkan dengan spool di posisi 2 (memiliki properti ID Node Utama yang menyediakan tautan ini secara eksplisit). Spool memutar ulang baris (satu baris dalam kasus ini) dari penyimpanan sementara yang sama yang ditulis oleh spool utama. Seperti disebutkan di atas, spool dan posisi 2 dan 4 tidak diperlukan, dan ditampilkan hanya karena mereka ada di template umum untuk pemeliharaan tampilan terindeks.
- Stream Aggregate menghitung jumlah data kolom Nilai dalam set yang disisipkan, dan menghitung jumlah baris yang ada per grup kunci tampilan. Outputnya adalah data tambahan yang diperlukan untuk menjaga agar tampilan tetap sinkron dengan data dasar. Catatan, Stream Aggregate tidak memiliki elemen Group By karena pengoptimal kueri hanya mengetahui satu nilai yang sedang diproses. Namun, pengoptimal tidak menerapkan logika serupa untuk mengganti agregat dengan proyeksi (jumlah dari satu nilai hanyalah nilai itu sendiri, dan hitungannya akan selalu satu untuk satu sisipan baris). Menghitung jumlah dan jumlah agregat untuk satu baris data bukanlah operasi yang mahal, jadi pengoptimalan yang terlewat ini tidak perlu dikhawatirkan.
- Penggabungan menghubungkan setiap perubahan inkremental yang dihitung ke kunci yang ada dalam tampilan yang diindeks. Gabung adalah gabungan luar karena data yang baru dimasukkan mungkin tidak sesuai dengan data yang ada dalam tampilan.
- Operator ini menempatkan baris yang akan diubah dalam tampilan.
- Compute Scalar memiliki dua tanggung jawab penting. Pertama, ini menentukan apakah setiap perubahan inkremental akan memengaruhi baris yang ada dalam tampilan, atau apakah baris baru harus dibuat. Ini dilakukan dengan memeriksa untuk melihat apakah gabungan luar menghasilkan nol dari sisi tampilan gabungan. Sisipan sampel kami adalah untuk grup 3, yang saat ini tidak ada dalam tampilan, jadi baris baru akan dibuat. Fungsi kedua dari Compute Scalar adalah menghitung nilai baru untuk kolom tampilan. Jika baris baru akan ditambahkan ke tampilan, ini hanyalah hasil jumlah tambahan dari Stream Aggregate. Jika baris yang ada di tampilan akan diperbarui, nilai baru adalah nilai yang ada di baris tampilan ditambah jumlah tambahan dari Agregat Aliran.
- Kumparan Meja Eager ini untuk Perlindungan Halloween. Diperlukan untuk kebenaran saat operasi penyisipan memengaruhi tabel yang juga direferensikan di sisi akses data kueri. Secara teknis tidak diperlukan jika operasi pemeliharaan baris tunggal menghasilkan pembaruan ke baris tampilan yang ada, tetapi tetap dalam rencana.
- Operator terakhir dalam rencana diberi label sebagai operator Pembaruan, tetapi ia akan melakukan Sisipan atau Pembaruan untuk setiap baris yang diterimanya tergantung pada nilai kolom "kode tindakan" yang ditambahkan oleh Skalar Hitung di simpul 8 . Secara umum, operator pembaruan ini mampu menyisipkan, memperbarui, dan menghapus.
Ada sedikit detail di sana, jadi untuk meringkas:
- Data grup agregat berubah menurut kunci cluster unik tampilan. Ini menghitung efek bersih dari perubahan tabel dasar pada setiap kolom per kunci.
- Gabungan luar menghubungkan perubahan inkremental per tombol ke baris yang ada dalam tampilan.
- Skalar komputasi menghitung apakah baris baru harus ditambahkan ke tampilan, atau baris yang ada diperbarui. Ini menghitung nilai kolom terakhir untuk operasi penyisipan atau pembaruan tampilan.
- Operator pembaruan tampilan menyisipkan baris baru atau memperbarui yang sudah ada seperti yang diarahkan oleh kode tindakan.
Contoh 2 – Sisipan Multi-baris
Percaya atau tidak, rencana eksekusi insert tabel dasar baris tunggal yang dibahas di atas tunduk pada sejumlah penyederhanaan. Meskipun beberapa kemungkinan pengoptimalan lebih lanjut terlewatkan (seperti yang disebutkan), pengoptimal kueri masih berhasil menghapus beberapa operasi dari template pemeliharaan tampilan terindeks umum, dan mengurangi kerumitan lainnya.
Beberapa pengoptimalan ini diizinkan karena kami hanya menyisipkan satu baris, tetapi yang lain diaktifkan karena pengoptimal dapat melihat nilai literal yang ditambahkan ke tabel dasar. Misalnya, pengoptimal dapat melihat bahwa nilai grup yang dimasukkan akan melewati predikat dalam klausa WHERE tampilan.
Jika sekarang kita menyisipkan dua baris, dengan nilai "tersembunyi" dalam variabel lokal, kita mendapatkan rencana yang sedikit lebih rumit:
DECLARE @Group1 integer = 4, @Value1 integer = 7, @Group2 integer = 5, @Value2 integer = 8; INSERT dbo.T1 (GroupID, Value) VALUES (@Group1, @Value1), (@Group2, @Value2);
Operator baru atau yang diubah diberi keterangan seperti sebelumnya:
- Pemindaian Konstan menyediakan nilai untuk disisipkan. Sebelumnya, pengoptimalan untuk penyisipan baris tunggal memungkinkan operator ini dihilangkan.
- Operator Filter eksplisit sekarang diperlukan untuk memeriksa apakah grup yang dimasukkan ke tabel dasar cocok dengan klausa WHERE dalam tampilan. Seperti yang terjadi, kedua baris baru akan lulus tes, tetapi pengoptimal tidak dapat melihat nilai dalam variabel untuk mengetahui hal ini sebelumnya. Selain itu, tidak akan aman untuk menyimpan paket yang melewatkan filter ini dalam cache karena penggunaan ulang paket di masa mendatang dapat memiliki nilai yang berbeda dalam variabel.
- Pengurutan sekarang diperlukan untuk memastikan baris tiba di Agregat Aliran dalam urutan grup. Pengurutan sebelumnya telah dihapus karena tidak ada gunanya mengurutkan satu baris.
- Stream Aggregate sekarang memiliki properti "grup menurut", yang cocok dengan kunci cluster unik dari tampilan.
- Urutan ini diperlukan untuk menampilkan baris dalam tombol tampilan, urutan kode tindakan, yang diperlukan untuk operasi yang benar dari operator Ciutkan. Sortir adalah operator pemblokiran penuh sehingga tidak perlu lagi Eager Table Spool untuk Perlindungan Halloween.
- Operator Ciutkan yang baru menggabungkan penyisipan dan penghapusan yang berdekatan pada nilai kunci yang sama ke dalam satu operasi pembaruan. Operator ini sebenarnya tidak diperlukan dalam hal ini, karena tidak ada kode tindakan penghapusan yang dapat dibuat (hanya sisipan dan pembaruan). Ini tampaknya merupakan kelalaian, atau mungkin sesuatu yang tertinggal untuk alasan keamanan. Bagian dari rencana kueri pembaruan yang dibuat secara otomatis dapat menjadi sangat kompleks, sehingga sulit untuk mengetahuinya secara pasti.
Properti Filter (berasal dari klausa WHERE tampilan) adalah:
Stream Agregate mengelompokkan dengan tombol tampilan, dan menghitung jumlah dan jumlah agregat per grup:
Skalar Hitung mengidentifikasi tindakan yang harus diambil per baris (dalam kasus ini sisipkan atau perbarui), dan menghitung nilai yang akan disisipkan atau diperbarui dalam tampilan:
Kode tindakan diberi label ekspresi [Act1xxx]. Nilai yang valid adalah 1 untuk pembaruan, 3 untuk penghapusan, dan 4 untuk sisipan. Ekspresi tindakan ini menghasilkan sisipan (kode 4) jika tidak ada baris yang cocok ditemukan dalam tampilan (yaitu gabungan luar mengembalikan null untuk kolom NumRows). Jika baris yang cocok ditemukan, kode tindakannya adalah 1 (perbarui).
Perhatikan bahwa NumRows adalah nama yang diberikan ke kolom COUNT_BIG(*) yang diperlukan dalam tampilan. Dalam rencana yang dapat mengakibatkan penghapusan dari tampilan, Skalar Hitung akan mendeteksi saat nilai ini menjadi nol (tidak ada baris untuk grup saat ini) dan menghasilkan kode tindakan penghapusan (3).
Ekspresi yang tersisa mempertahankan jumlah dan jumlah agregat dalam tampilan. Perhatikan bahwa label ekspresi [Expr1009] dan [Expr1010] bukanlah hal baru; mereka merujuk ke label yang dibuat oleh Stream Aggregate. Logikanya sederhana:jika baris yang cocok tidak ditemukan, nilai baru yang akan dimasukkan hanyalah nilai yang dihitung secara agregat. Jika baris yang cocok dalam tampilan ditemukan, nilai yang diperbarui adalah nilai saat ini di baris ditambah kenaikan yang dihitung oleh agregat.
Terakhir, operator pembaruan tampilan (ditampilkan sebagai Pembaruan Indeks Berkelompok di SSMS) menunjukkan referensi kolom tindakan ([Act1013] yang ditentukan oleh Skalar Hitung):
Contoh 3 – Pembaruan Multi-baris
Sejauh ini kita hanya melihat sisipan ke tabel dasar. Rencana eksekusi untuk penghapusan sangat mirip, hanya dengan beberapa perbedaan kecil dalam perhitungan terperinci. Oleh karena itu, contoh berikut ini beralih untuk melihat rencana pemeliharaan untuk pembaruan tabel dasar:
DECLARE @Group1 integer = 1, @Group2 integer = 2, @Value integer = 1; UPDATE dbo.T1 SET Value = Value + @Value WHERE GroupID IN (@Group1, @Group2);
Seperti sebelumnya, kueri ini menggunakan variabel untuk menyembunyikan nilai literal dari pengoptimal, mencegah beberapa penyederhanaan diterapkan. Juga berhati-hati untuk memperbarui dua grup terpisah, mencegah pengoptimalan yang dapat diterapkan ketika pengoptimal mengetahui hanya satu grup (satu baris dari tampilan yang diindeks) yang akan terpengaruh. Rencana eksekusi beranotasi untuk kueri pembaruan ada di bawah ini:
Perubahan dan point of interestnya adalah:
- Operator Split baru mengubah setiap pembaruan baris tabel dasar menjadi operasi penghapusan dan penyisipan yang terpisah. Setiap baris pembaruan dibagi menjadi dua baris terpisah, menggandakan jumlah baris setelah titik ini dalam rencana. Split adalah bagian dari pola split-sort-collapse yang diperlukan untuk melindungi dari kesalahan pelanggaran kunci unik sementara yang salah.
- Agregat Aliran dimodifikasi untuk memperhitungkan baris masuk yang dapat menentukan penghapusan atau penyisipan (karena Pemisahan, dan ditentukan oleh kolom kode tindakan di baris). Baris sisipan menyumbangkan nilai asli dalam jumlah agregat; tanda dibalik untuk menghapus baris tindakan. Demikian pula, jumlah baris agregat di sini menghitung baris sisipan sebagai +1 dan menghapus baris sebagai -1.
- Logika Hitung Skalar juga dimodifikasi untuk mencerminkan bahwa efek bersih dari perubahan per grup mungkin memerlukan tindakan penyisipan, pembaruan, atau penghapusan terhadap tampilan yang terwujud. Sebenarnya tidak mungkin untuk kueri pembaruan khusus ini untuk menghasilkan baris yang disisipkan atau dihapus terhadap tampilan ini, tetapi logika yang diperlukan untuk menyimpulkan bahwa itu berada di luar kemampuan penalaran pengoptimal saat ini. Kueri pembaruan atau definisi tampilan yang sedikit berbeda memang dapat menghasilkan campuran tindakan penyisipan, penghapusan, dan pembaruan tampilan.
- Operator Ciutkan disorot murni karena perannya dalam pola split-sort-collapse yang disebutkan di atas. Perhatikan bahwa itu hanya menciutkan penghapusan dan penyisipan pada kunci yang sama; penghapusan dan penyisipan yang tak tertandingi setelah Ciutkan sangat mungkin dilakukan (dan cukup biasa).
Seperti sebelumnya, properti operator utama yang harus dilihat untuk memahami pekerjaan pemeliharaan tampilan yang diindeks adalah Filter, Stream Aggregate, Outer Join, dan Compute Scalar.
Contoh 4 – Pembaruan Multi-baris dengan Gabung
Untuk melengkapi ikhtisar rencana pelaksanaan pemeliharaan tampilan terindeks, kita memerlukan tampilan contoh baru yang menggabungkan beberapa tabel, dan menyertakan proyeksi dalam daftar pilihan:
CREATE TABLE dbo.E1 (g integer NULL, a integer NULL); CREATE TABLE dbo.E2 (g integer NULL, a integer NULL); CREATE TABLE dbo.E3 (g integer NULL, a integer NULL); GO INSERT dbo.E1 (g, a) VALUES (1, 1); INSERT dbo.E2 (g, a) VALUES (1, 1); INSERT dbo.E3 (g, a) VALUES (1, 1); GO CREATE VIEW dbo.V1 WITH SCHEMABINDING AS SELECT g = E1.g, sa1 = SUM(ISNULL(E1.a, 0)), sa2 = SUM(ISNULL(E2.a, 0)), sa3 = SUM(ISNULL(E3.a, 0)), cbs = COUNT_BIG(*) FROM dbo.E1 AS E1 JOIN dbo.E2 AS E2 ON E2.g = E1.g JOIN dbo.E3 AS E3 ON E3.g = E2.g WHERE E1.g BETWEEN 1 AND 5 GROUP BY E1.g; GO CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.V1 (g);
Untuk memastikan kebenaran, salah satu persyaratan tampilan yang diindeks adalah bahwa jumlah agregat tidak dapat beroperasi pada ekspresi yang mungkin bernilai nol. Definisi tampilan di atas menggunakan ISNULL untuk memenuhi persyaratan itu. Contoh kueri pembaruan yang menghasilkan komponen rencana pemeliharaan indeks yang cukup komprehensif ditunjukkan di bawah ini, bersama dengan rencana eksekusi yang dihasilkannya:
UPDATE dbo.E1 SET g = g + 1, a = a + 1;
Rencananya terlihat cukup besar dan rumit sekarang, tetapi sebagian besar elemennya persis seperti yang telah kita lihat. Perbedaan utamanya adalah:
- Cabang teratas dari paket tersebut mencakup sejumlah operator Compute Scalar tambahan. Ini bisa diatur lebih kompak, tetapi pada dasarnya mereka hadir untuk menangkap nilai pra-pembaruan dari kolom non-pengelompokan. Skalar Hitung di sebelah kiri Pembaruan Tabel menangkap nilai pasca-pembaruan kolom "a", dengan proyeksi ISNULL diterapkan.
- Skalar Hitung baru di area rencana ini menghitung nilai yang dihasilkan oleh ekspresi ISNULL pada setiap tabel sumber. Secara umum, proyeksi pada tabel yang digabungkan dalam tampilan akan diwakili oleh Hitung Skalar di sini. Penyortiran di area rencana ini hadir murni karena pengoptimal memilih strategi gabung gabung karena alasan biaya (ingat, gabung memerlukan input yang diurutkan kunci gabung).
- Dua operator gabungan baru, dan cukup mengimplementasikan gabungan dalam definisi tampilan. Gabungan ini selalu muncul sebelum Agregat Aliran yang menghitung efek inkremental dari perubahan pada tampilan. Perhatikan bahwa perubahan ke tabel dasar dapat mengakibatkan baris yang digunakan untuk memenuhi kriteria bergabung tidak lagi bergabung, dan sebaliknya. Semua potensi kerumitan ini ditangani dengan benar (mengingat pembatasan tampilan yang diindeks) oleh Stream Aggregate yang menghasilkan ringkasan perubahan per kunci tampilan setelah penggabungan dilakukan.
Pemikiran Terakhir
Paket terakhir itu mewakili cukup banyak templat lengkap untuk mempertahankan tampilan yang diindeks, meskipun penambahan indeks nonclustered ke tampilan akan menambahkan operator tambahan yang dikumpulkan dari output operator pembaruan tampilan juga. Selain dari Split tambahan (dan kombinasi Sortir dan Ciutkan jika indeks nonclustered tampilan itu unik), tidak ada yang istimewa dari kemungkinan ini. Menambahkan klausa keluaran ke kueri tabel dasar juga dapat menghasilkan beberapa operator tambahan yang menarik, tetapi sekali lagi, ini tidak khusus untuk pemeliharaan tampilan yang diindeks saja.
Untuk meringkas strategi keseluruhan yang lengkap:
- Perubahan tabel dasar diterapkan seperti biasa; nilai pra-pembaruan dapat ditangkap.
- Operator terpisah dapat digunakan untuk mengubah pembaruan menjadi pasangan hapus/sisipkan.
- Spool yang bersemangat menyimpan informasi perubahan tabel dasar ke penyimpanan sementara.
- Semua tabel dalam tampilan diakses, kecuali tabel dasar yang diperbarui (yang dibaca dari spool).
- Proyeksi dalam tampilan diwakili oleh Skalar Hitung.
- Filter dalam tampilan diterapkan. Filter dapat didorong ke dalam pemindaian atau dicari sebagai residu.
- Penggabungan yang ditentukan dalam tampilan dilakukan.
- Agregat menghitung perubahan inkremental bersih yang dikelompokkan berdasarkan kunci tampilan yang dikelompokkan.
- Set perubahan inkremental adalah bagian luar yang digabungkan dengan tampilan.
- A Compute Scalar menghitung kode tindakan (menyisipkan/memperbarui/menghapus terhadap tampilan) untuk setiap perubahan, dan menghitung nilai aktual yang akan dimasukkan atau diperbarui. Logika komputasi didasarkan pada output agregat dan hasil gabungan luar ke tampilan.
- Perubahan diurutkan ke dalam kunci tampilan dan urutan kode tindakan, dan diciutkan ke pembaruan yang sesuai.
- Akhirnya, perubahan inkremental diterapkan pada tampilan itu sendiri.
Seperti yang telah kita lihat, seperangkat alat normal yang tersedia untuk pengoptimal kueri masih diterapkan ke bagian rencana yang dibuat secara otomatis, yang berarti bahwa satu atau beberapa langkah di atas dapat disederhanakan, diubah, atau dihapus seluruhnya. Namun, bentuk dasar dan pengoperasian rencana tetap utuh.
Jika Anda telah mengikuti contoh kode, Anda dapat menggunakan skrip berikut untuk membersihkan:
DROP VIEW dbo.V1; DROP TABLE dbo.E3, dbo.E2, dbo.E1; DROP VIEW dbo.IV; DROP TABLE dbo.T1;