Kolase database yang terkandung
Berlaku untuk: SQL Server
Azure SQL Managed Instance
Berbagai properti memengaruhi urutan sortir dan semantik kesetaraan data tekstual, termasuk sensitivitas huruf besar/kecil, sensitivitas aksen, dan bahasa dasar yang digunakan. Kualitas ini dinyatakan ke SQL Server melalui pilihan kolase untuk data. Untuk diskusi kolase yang lebih mendalam, lihat Kolase dan Dukungan Unicode.
Kolase tidak hanya berlaku untuk data yang disimpan dalam tabel pengguna, tetapi untuk semua teks yang ditangani oleh SQL Server, termasuk metadata, objek sementara, nama variabel, dll. Penanganan ini berbeda dalam database yang terkandung dan tidak terkandung. Perubahan ini tidak akan memengaruhi banyak pengguna, tetapi membantu memberikan independensi dan keseragaman instans. Tetapi ini juga dapat menyebabkan beberapa kebingungan, serta masalah untuk sesi yang mengakses database yang terkandung dan tidak terkandung.
Perilaku kolase database yang terkandung berbeda secara halus dari itu dalam database yang tidak terkandung. Perilaku ini umumnya bermanfaat, memberikan kemandirian instans dan kesederhanaan. Beberapa pengguna mungkin mengalami masalah, terutama ketika sesi mengakses database yang terkandung dan tidak terkandung.
Artikel ini mengklarifikasi konten perubahan, dan memeriksa area di mana perubahan dapat menyebabkan masalah.
Catatan
Untuk Azure SQL Database, kolase untuk database mandiri berbeda. Kolase database dan kolase katalog dapat diatur pada pembuatan database dan tidak dapat diperbarui. Tentukan kolate untuk data (COLLATE
) dan kolate katalog untuk metadata sistem dan pengidentifikasi objek (CATALOG_COLLATION
). Untuk mengetahui informasi selengkapnya, lihat CREATE DATABASE.
Database yang tidak terkandung
Semua database memiliki kolase default (yang dapat diatur saat membuat atau mengubah database. Kolase ini digunakan untuk semua metadata dalam database, serta default untuk semua kolom string dalam database. Pengguna dapat memilih kolase yang berbeda untuk kolom tertentu dengan menggunakan COLLATE
klausa.
Contoh 1
Misalnya, jika kita bekerja di Beijing, kita mungkin menggunakan kolate Cina:
ALTER DATABASE MyDB COLLATE Chinese_Simplified_Pinyin_100_CI_AS;
Sekarang jika kita membuat kolom, kolase defaultnya akan menjadi kolase Cina ini, tetapi kita dapat memilih yang lain jika kita ingin:
CREATE TABLE MyTable
(mycolumn1 nvarchar,
mycolumn2 nvarchar COLLATE Frisian_100_CS_AS);
GO
SELECT name, collation_name
FROM sys.columns
WHERE name LIKE 'mycolumn%' ;
GO
Berikut adalah hasil yang ditetapkan.
name collation_name
--------------- ----------------------------------
mycolumn1 Chinese_Simplified_Pinyin_100_CI_AS
mycolumn2 Frisian_100_CS_AS
Ini tampak relatif sederhana, tetapi beberapa masalah muncul. Karena kolase untuk kolom bergantung pada database tempat tabel dibuat, masalah muncul dengan penggunaan tabel sementara yang disimpan di tempdb
. Kolatasi tempdb
biasanya cocok dengan kolater untuk instans, yang tidak harus cocok dengan kolatasi database.
Contoh 2
Misalnya, pertimbangkan database (Tionghoa) di atas saat digunakan pada instans dengan kolatasi Latin1_General :
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max)) ;
GO
Pada pandangan pertama, kedua tabel ini terlihat seperti memiliki skema yang sama, tetapi karena kolaborasi database berbeda, nilai sebenarnya tidak kompatibel:
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt
Berikut adalah hasil yang ditetapkan.
Msg 468, Tingkat 16, Status 9, Baris 2
Tidak dapat mengatasi konflik kolaterasi antara "Latin1_General_100_CI_AS_KS_WS_SC" dan "Chinese_Simplified_Pinyin_100_CI_AS" dalam operasi yang sama dengan.
Kita dapat memperbaikinya dengan menyusun tabel sementara secara eksplisit. SQL Server membuat ini agak lebih mudah dengan menyediakan DATABASE_DEFAULT
kata kunci untuk COLLATE
klausa.
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max) COLLATE DATABASE_DEFAULT);
GO
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt ;
Ini sekarang berjalan tanpa kesalahan.
Kita juga dapat melihat perilaku dependen kolate dengan variabel. Pertimbangkan fungsi berikut:
CREATE FUNCTION f(@x INT) RETURNS INT
AS BEGIN
DECLARE @I INT = 1
DECLARE @İ INT = 2
RETURN @x * @i
END;
Ini adalah fungsi yang agak aneh. Dalam kolatasi peka huruf besar/kecil, @i
dalam klausa pengembalian tidak dapat mengikat ke @I
atau @İ
. Dalam kolater Latin1_General yang tidak peka huruf besar/kecil, @i
mengikat ke @I
, dan fungsi mengembalikan 1
. Tetapi dalam kolatasi Turki yang tidak peka huruf besar/kecil, @i
mengikat ke @İ
, dan fungsi mengembalikan 2. Ini dapat menimbulkan malapetaka pada database yang bergerak di antara instans dengan kolamen yang berbeda.
Database Mandiri
Karena tujuan desain database yang terkandung adalah untuk membuatnya mandiri, ketergantungan pada instans dan tempdb
kolase harus diputus. Untuk melakukan ini, database yang terkandung memperkenalkan konsep kolase katalog. Kolatasi katalog digunakan untuk metadata sistem dan objek sementara. Detail disediakan di bawah ini.
Dalam database mandiri, kolase katalog Latin1_General_100_CI_AS_WS_KS_SC. Kolase ini sama untuk semua database yang terkandung di semua instans SQL Server dan tidak dapat diubah.
Kolase database dipertahankan, tetapi hanya digunakan sebagai kolase default untuk data pengguna. Secara default, kolase database sama dengan model
kolase database, tetapi dapat diubah oleh pengguna melalui CREATE
perintah atau ALTER DATABASE
seperti halnya database yang tidak terkandung.
Kata kunci baru, CATALOG_DEFAULT
, tersedia dalam COLLATE
klausa. Ini digunakan sebagai pintasan ke kolase metadata saat ini dalam database yang terkandung dan tidak terkandung. Artinya, dalam database yang tidak terkandung, CATALOG_DEFAULT
akan mengembalikan kolase database saat ini, karena metadata disusun dalam kolase database. Dalam database mandiri, kedua nilai ini mungkin berbeda, karena pengguna dapat mengubah kolase database sehingga tidak cocok dengan kolase katalog.
Perilaku berbagai objek dalam database yang tidak terkandung dan terkandung dirangkum dalam tabel ini:
Item | Database Tidak Terkandung | Database Terkandung |
---|---|---|
Data Pengguna (default) | DATABASE_DEFAULT | DATABASE_DEFAULT |
Data Sementara (default) | tempdb Pemeriksaan |
DATABASE_DEFAULT |
Metadata | DATABASE_DEFAULT/CATALOG_DEFAULT | CATALOG_DEFAULT |
Metadata Sementara | tempdb Pemeriksaan |
CATALOG_DEFAULT |
Variabel | Kolas Instans | CATALOG_DEFAULT |
Label Goto | Kolas Instans | CATALOG_DEFAULT |
Nama Kursor | Kolas Instans | CATALOG_DEFAULT |
Dalam contoh tabel sementara yang dijelaskan sebelumnya, kita dapat melihat bahwa perilaku kolabasi ini menghilangkan kebutuhan akan klausul eksplisit COLLATE
di sebagian besar penggunaan tabel sementara. Dalam database mandiri, kode ini sekarang berjalan tanpa kesalahan, bahkan jika database dan kolase instans berbeda:
CREATE TABLE T1 (T1_txt nvarchar(max)) ;
GO
CREATE TABLE #T2 (T2_txt nvarchar(max));
GO
SELECT T1_txt, T2_txt
FROM T1
JOIN #T2
ON T1.T1_txt = #T2.T2_txt ;
Ini berfungsi karena keduanya T1_txt
dan T2_txt
disusun dalam kolase database database yang terkandung.
Silang antara konteks yang terkandung dan tidak terkandung
Selama sesi dalam database yang terkandung tetap terkandung, sesi harus tetap berada dalam database yang tersambung dengannya. Dalam hal ini perilakunya sangat mudah. Tetapi jika sesi melintasi antara konteks yang terkandung dan tidak terkandung, perilaku menjadi lebih kompleks, karena dua set aturan harus di bridged. Ini dapat terjadi dalam database yang sebagian berisi, karena pengguna mungkin USE
ke database lain. Dalam hal ini, perbedaan aturan kolajeasi ditangani oleh prinsip berikut.
- Perilaku kolatasi untuk batch ditentukan oleh database tempat batch dimulai.
Perhatikan bahwa keputusan ini dibuat sebelum perintah apa pun dikeluarkan, termasuk inisial USE
. Artinya, jika batch dimulai dalam database yang terkandung, tetapi perintah pertama adalah USE
ke database yang tidak terkandung, perilaku kolase yang terkandung masih akan digunakan untuk batch. Mengingat ini, referensi ke variabel, misalnya, mungkin memiliki beberapa kemungkinan hasil:
Referensi mungkin menemukan persis satu kecocokan. Dalam hal ini, referensi akan berfungsi tanpa kesalahan.
Referensi mungkin tidak menemukan kecocokan dalam kolas saat ini di mana sebelumnya ada satu. Ini akan menimbulkan kesalahan yang menunjukkan bahwa variabel tidak ada, meskipun rupanya dibuat.
Referensi mungkin menemukan beberapa kecocokan yang awalnya berbeda. Ini juga akan menimbulkan kesalahan.
Kami akan mengilustrasikan ini dengan beberapa contoh. Untuk ini, kami berasumsi ada database yang sebagian berisi bernama MyCDB
dengan kolase databasenya diatur ke kolase default, Latin1_General_100_CI_AS_WS_KS_SC. Kami berasumsi bahwa kolate instans Latin1_General_100_CS_AS_WS_KS_SC. Dua kolaborasi hanya berbeda dalam kasus sensitivitas.
Contoh 1
Contoh berikut mengilustrasikan kasus di mana referensi menemukan persis satu kecocokan.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #a VALUES(1);
GO
USE master;
GO
SELECT * FROM #a;
GO
Results:
Berikut adalah hasil yang ditetapkan.
x
-----------
1
Dalam hal ini, #a yang diidentifikasi mengikat dalam kolase katalog yang tidak peka huruf besar/kecil dan kolase instans peka huruf besar/kecil, dan kode berfungsi.
Contoh 2
Contoh berikut mengilustrasikan kasus di mana referensi tidak menemukan kecocokan dalam kolake saat ini di mana ada satu sebelumnya.
USE MyCDB;
GO
CREATE TABLE #a(x int);
INSERT INTO #A VALUES(1);
GO
Di sini, ikatan #A
ke #a
dalam kolater default yang tidak peka huruf besar/kecil, dan sisipan berfungsi,
Berikut adalah hasil yang ditetapkan.
(1 row(s) affected)
Tapi jika kita melanjutkan naskahnya...
USE master;
GO
SELECT * FROM #A;
GO
Kami mendapatkan kesalahan saat mencoba mengikat #A
dalam kolatasi instans peka huruf besar/kecil;
Berikut adalah hasil yang ditetapkan.
Msg 208, Tingkat 16, Status 0, Baris 2
Nama objek tidak valid '#A'.
Contoh 3
Contoh berikut mengilustrasikan kasus di mana referensi menemukan beberapa kecocokan yang awalnya berbeda. Pertama, kita mulai di tempdb
(yang memiliki kolase peka huruf besar/kecil yang sama dengan instans kita) dan menjalankan pernyataan berikut.
USE tempdb;
GO
CREATE TABLE #a(x int);
GO
CREATE TABLE #A(x int);
GO
INSERT INTO #a VALUES(1);
GO
INSERT INTO #A VALUES(2);
GO
Ini berhasil, karena tabel berbeda dalam kolase ini:
Berikut adalah hasil yang ditetapkan.
(1 row(s) affected)
(1 row(s) affected)
Namun, jika kita pindah ke database mandiri kita, kita menemukan bahwa kita tidak dapat lagi mengikat tabel ini.
USE MyCDB;
GO
SELECT * FROM #a;
GO
Berikut adalah hasil yang ditetapkan.
Msg 12800, Level 16, State 1, Line 2
The reference to temp table name #a is ambiguous and cannot be resolved. Possible candidates are #a and #A.