Sdílet prostřednictvím


Kolace databáze s omezením

platí pro:SQL Serverazure SQL Managed Instance

Různé vlastnosti ovlivňují pořadí řazení a sémantiku rovnosti textových dat, včetně citlivosti písmen, citlivosti zvýraznění a používaného základního jazyka. Tyto vlastnosti se vyjadřují pro SQL Server prostřednictvím volby kolace dat. Podrobnější diskuzi o samotných kolacích (řazení) najdete v tématu Podpora kolací a Unicode.

Kolace platí nejen pro data uložená v uživatelských tabulkách, ale pro veškerý text zpracovávaný SQL Serverem, včetně metadat, dočasných objektů, názvů proměnných atd. Zpracování těchto databází se liší v obsažených a neobsadných databázích. Tato změna nemá vliv na mnoho uživatelů, ale pomáhá poskytovat nezávislost a jednotnost instancí. To ale může také způsobit určité nejasnosti a problémy s relacemi, které přistupují k obsaženým i neobsaženým databázím.

Chování kolace oddělených databází se jemně liší od chování v neoddělených databázích. Toto chování je obecně přínosné a poskytuje nezávislost a jednoduchost instance. Někteří uživatelé můžou mít problémy, zejména v případě, že relace přistupuje k obsahovaným i neobsahovaným databázím.

Tento článek vysvětluje obsah změny a zkoumá oblasti, ve kterých by změna mohla způsobit problémy.

Poznámka:

Pro Azure SQL Database se kolace pro obsažené databáze liší. Kolace databáze a kolace katalogu je možné nastavit při vytváření databáze a nedá se aktualizovat. Zadejte kolaci pro data (COLLATE) a kolaci katalogu pro systémová metadata a identifikátory objektů (CATALOG_COLLATION). Další informace naleznete v tématu CREATE DATABASE.

Databáze, které nejsou obsažené

Všechny databáze mají výchozí kolaci (kterou je možné nastavit při vytváření nebo změně databáze). Tato kolace se používá pro všechna metadata v databázi a výchozí nastavení pro všechny řetězcové sloupce v databázi. Uživatelé mohou zvolit jinou kolaci pro konkrétní sloupec pomocí klauzule COLLATE.

Příklad 1

Pokud bychom například pracovali v Pekingu, můžeme použít čínskou kolaci:

ALTER DATABASE MyDB
    COLLATE Chinese_Simplified_Pinyin_100_CI_AS;

Když teď vytvoříme sloupec, jeho výchozí kolací je tato čínská kolace, ale můžeme si vybrat jinou, pokud chceme:

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

Tady je soubor výsledků.

name            collation_name
--------------- ----------------------------------
mycolumn1       Chinese_Simplified_Pinyin_100_CI_AS
mycolumn2       Frisian_100_CS_AS

Zdá se to poměrně jednoduché, ale vzniká několik problémů. Vzhledem k tomu, že kolace sloupce závisí na databázi, ve které je tabulka vytvořena, vznikají problémy s použitím dočasných tabulek, které jsou uloženy v tempdb. Kolace tempdb obvykle odpovídá kolaci instance, která nemusí odpovídat kolaci databáze.

Příklad 2

Představte si například dříve zobrazenou (čínskou Latin1_General ) databázi při použití v instanci s kolací:

CREATE TABLE T1 (T1_txt NVARCHAR (MAX));
GO

CREATE TABLE #T2 (T2_txt NVARCHAR (MAX));
GO

Na první pohled vypadají tyto dvě tabulky jako stejné schéma, ale vzhledem k tomu, že kolace databází se liší, jsou hodnoty nekompatibilní:

SELECT T1_txt, T2_txt
FROM T1
     INNER JOIN #T2
         ON T1.T1_txt = #T2.T2_txt;

Tady je soubor výsledků.

Msg 468, level 16, state 9, line 2

Nelze vyřešit konflikt kolace mezi "Latin1_General_100_CI_AS_KS_WS_SC" a "Chinese_Simplified_Pinyin_100_CI_AS" ve stejné operaci.

Tento problém můžeme vyřešit explicitním seřazením dočasné tabulky. SQL Server to usnadňuje poskytnutím klíčového DATABASE_DEFAULT slova pro klauzuli COLLATE .

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
     INNER JOIN #T2
         ON T1.T1_txt = #T2.T2_txt;

Tento dotaz se teď spustí bez chyby.

Můžeme také vidět chování závislé na kolaci s proměnnými. Zvažte následující funkci:

CREATE FUNCTION f (@x INT)
RETURNS INT
AS
BEGIN
    DECLARE @I AS INT = 1;
    DECLARE @İ AS INT = 2;
    RETURN @x * @i;
END

To je spíše zvláštní funkce. V kolaci s rozlišováním malých a velkých písmen nemůže klauzule pro návrat vytvořit vazbu ani na @I ani na . V kolaci Latin1_General nerozeznávají malá a velká písmena, @i váže se na @I, a funkce vrátí 1. V turecké kolaci, která nerozlišuje, se @i váže na a funkce vrátí hodnotu 2. To může způsobit havárii databáze, která se pohybuje mezi instancemi s různými kolacemi.

Uzavřené databáze

Vzhledem k tomu, že cílem návrhu obsažených databází je zajistit, aby byly soběstačné, musí být závislost na instanci a tempdb kolacích přerušena. Za tímto účelem zavádějí databáze nový koncept kolace katalogu. Kolace katalogu se používá pro systémová metadata a přechodné objekty. Podrobnosti jsou uvedeny následujícím způsobem.

V obsažené databázi je kolace katalogu Latin1_General_100_CI_AS_WS_KS_SC. Tato kolace je stejná pro všechny obsažené databáze na všech instancích SQL Serveru a nedá se změnit.

Kollace databáze se uchovává, ale slouží pouze jako výchozí kollace uživatelských dat. Ve výchozím nastavení je kolace databáze rovna model kolaci databáze, ale uživatel ji může změnit pomocí příkazu CREATE nebo ALTER DATABASE, podobně jako u samostatných databází.

Nové klíčové slovo , CATALOG_DEFAULTje k dispozici v klauzuli COLLATE . Používá se jako zástupce aktuálního řazení metadat v databázích obsažených i neobsahujících. To znamená, že v neobsažené databázi CATALOG_DEFAULT vrátí aktuální kolaci databáze, protože metadata jsou kolovaná podle kolace databáze. V databázi s omezením se tyto dvě hodnoty můžou lišit, protože uživatel může změnit kolaci databáze tak, aby se neshodovaly s kolací katalogu.

Chování různých objektů v neobsažených a obsažených databázích je shrnuto v této tabulce:

Položka Neomezená databáze Uzavřená databáze
Uživatelská data (výchozí) DATABASE_DEFAULT DATABASE_DEFAULT
Dočasná data (výchozí) tempdb řazení DATABASE_DEFAULT
Metadatové informace DATABASE_DEFAULT / CATALOG_DEFAULT CATALOG_DEFAULT
Dočasná metadata tempdb řazení CATALOG_DEFAULT
Variables Kolace instancí CATALOG_DEFAULT
Goto labels Kolace instancí CATALOG_DEFAULT
Názvy kurzorů Srovnání instancí CATALOG_DEFAULT

V příkladu dočasné tabulky, který jsme popsali dříve, vidíme, že toto třídicí chování eliminuje potřebu explicitní klauzule COLLATE ve většině případů použití těchto tabulek. V databázi s omezením se teď tento kód spustí bez chyby, i když se kolace databáze a instance liší:

CREATE TABLE T1 (T1_txt NVARCHAR (MAX));
GO

CREATE TABLE #T2 (T2_txt NVARCHAR (MAX));
GO

SELECT T1_txt, T2_txt
FROM T1
     INNER JOIN #T2
         ON T1.T1_txt = #T2.T2_txt;

Tento dotaz funguje, protože T1_txt i T2_txt jsou seřazeny podle kolace v rámci obsažené databáze.

Kombinace mezi uzavřenými a neuzavřenými kontexty

Dokud relace v obsažené databázi zůstane obsažená, musí zůstat v databázi, ke které byla připojena. V tomto případě je chování jednoduché. Pokud ale relace překračuje mezi obsaženými a neobsaženými kontexty, je chování složitější, protože tyto dvě sady pravidel musí být překlenuty. K tomu může dojít v částečně obsažené databázi, protože uživatel může USE přejít do jiné databáze. V tomto případě se rozdíl v pravidlech kolace zpracovává následujícím principem.

  • Chování kolace dávky je určeno databází, ve které dávka začíná.

Toto rozhodnutí je provedeno před vydáním jakýchkoli příkazů, včetně počátečního USE. To znamená, že pokud dávka začíná v obsažené databázi, ale prvním příkazem je USE k databázi, která není obsažená, chování obsaženého řazení se stále používá pro dávku. V tomto scénáři může mít například odkaz na proměnnou několik možných výsledků:

  • Odkaz může najít přesně jednu shodu. V tomto případě odkaz funguje bez chyby.

  • Referenční hodnotu nemusí být možné nalézt v aktuálním nastavení kolace, kde se dříve shodovala. To vyvolá chybu, která značí, že proměnná neexistuje, i když byla zřejmě vytvořena.

  • Odkaz může najít více shod, které byly původně odlišné. Tím dojde také k chybě.

Ukážeme si to několika příklady. Předpokládáme, že existuje částečně obsažená databáze s názvem MyCDB, a její kolace databáze je nastavena na výchozí kolaci, Latin1_General_100_CI_AS_WS_KS_SC. Předpokládáme, že kolace instance je Latin1_General_100_CS_AS_WS_KS_SC. Dvě kolace se liší pouze v případě citlivosti.

Příklad 1

Následující příklad ukazuje případ, kdy odkaz najde přesně jednu shodu.

USE MyCDB;
GO

CREATE TABLE #a (x INT);

INSERT INTO #a VALUES (1);
GO

USE master;
GO

SELECT * FROM #a;
GO

Results:

Tady je soubor výsledků.

x
-----------
1

V tomto případě svázaná #a se váže jak na kolaci katalogu nerozlišující velikost písmen, tak na kolaci instance rozlišující velikost písmen, a kód funguje.

Příklad 2

Následující příklad ilustruje situaci, kdy odkaz nenalezne shodu v aktuálním pořadí, přestože dříve existovala.

USE MyCDB;
GO

CREATE TABLE #a (x INT);

INSERT INTO #A VALUES (1);
GO

V tomto případě se #A váže na #a v rámci výchozí kolace, která nerozlišuje malá a velká písmena, a vložení funguje.

Tady je soubor výsledků.

(1 row(s) affected)

Ale pokud budeme pokračovat ve skriptu...

USE master;
GO

SELECT * FROM #A;
GO

Při pokusu o vytvoření vazby #A v kolaci instance s ohledem na velikost písmen se zobrazí chyba.

Tady je soubor výsledků.

Msg 208, Level 16, State 0, Line 2
Invalid object name '#A'.

Příklad 3

Následující příklad ukazuje případ, kdy odkaz najde více shod, které byly původně odlišné. Nejprve začneme tempdb (která má stejnou kolaci s rozlišováním velkých a malých písmen jako naše instance) a provedeme následující příkazy.

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

Tento dotaz je úspěšný, protože tabulky jsou v této kolaci odlišné:

Tady je soubor výsledků.

(1 row(s) affected)
(1 row(s) affected)

Pokud se ale přesuneme do databáze s omezením, zjistíme, že se už s těmito tabulkami nemůžeme svázat.

USE MyCDB;
GO

SELECT * FROM #a;
GO

Tady je soubor výsledků.

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.