Kolase database yang terkandung

Berlaku untuk:SQL ServerAzure 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.  

Langkah berikutnya