Megosztás a következőn keresztül:


Tartalmazott adatbázis-kollációk

A következőkre vonatkozik:SQL ServerAzure SQL Managed Instance

A különböző tulajdonságok befolyásolják a szöveges adatok rendezési sorrendjét és egyenlőségi szemantikáját, beleértve a kis- és nagybetűk érzékenységét, a hangsúlyérzékenységet és a használt alapnyelvet. Ezeket a tulajdonságokat az SQL Server az adatok rendezési lehetőségével fejezi ki. Az összehasonlítások részletesebb tárgyalását lásd a Összehasonlítás és Unicode támogatás című témakörben.

A rendezés nem csak a felhasználói táblákban tárolt adatokra vonatkozik, hanem az SQL Server által kezelt összes szövegre, beleértve a metaadatokat, az ideiglenes objektumokat, a változóneveket stb. Ezek kezelése a tartalmazott és a nem tartalmazott adatbázisokban különbözik. Ez a változás nem sok felhasználót érint, de segít a példányok függetlenségének és egységességének biztosításában. Ez azonban némi zavart és problémákat is okozhat a tartalmazott és a nem tartalmazott adatbázisokhoz hozzáférő munkamenetek esetében.

A tartalmazott adatbázisok rendezési viselkedése részben eltér a nem tartalmazott adatbázisok viselkedésétől. Ez a viselkedés általában előnyös, mivel biztosítja a példányfüggetlenséget és az egyszerűséget. Egyes felhasználóknak lehetnek problémáik, különösen akkor, ha egy munkamenet a tárolt és a nem tartalmazott adatbázisokhoz is hozzáfér.

Ez a cikk tisztázza a változás tartalmát, és megvizsgálja azokat a területeket, ahol a változás problémákat okozhat.

Megjegyzés:

Az Azure SQL Database esetében a tartalmazott adatbázisok rendezései eltérőek. Az adatbázis-rendezés és a katalógus rendezése beállítható az adatbázis létrehozásakor, és nem frissíthető. Adja meg az adatok (COLLATE) és a rendszer metaadatainak és objektumazonosítóinak katalógusba rendezési módját (CATALOG_COLLATION). További információ: CREATE DATABASE.

Nem korlátozott adatbázisok

Minden adatbázis alapértelmezett rendezéssel rendelkezik (amely egy adatbázis létrehozásakor vagy módosításakor állítható be). Az adatbázis összes metaadatához ez a rendezés használatos, és az adatbázis összes sztringoszlopára alapértelmezett rendezésként szolgál. A felhasználók a záradék használatával COLLATE bármely oszlophoz választhatnak eltérő rendezést.

1. példa

Ha például Pekingben dolgoznánk, kínai betűrendet használhatnánk.

ALTER DATABASE MyDB
    COLLATE Chinese_Simplified_Pinyin_100_CI_AS;

Most, ha létrehozunk egy oszlopot, az alapértelmezett rendezés ez a kínai rendezés, de választhatunk egy másikat, ha szeretnénk:

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

Itt van az eredmények összessége.

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

Ez viszonylag egyszerűnek tűnik, de számos probléma merül fel. Mivel egy oszlop rendezése attól az adatbázistól függ, amelyben a tábla létrejön, problémák merülnek fel a tárolt tempdbideiglenes táblák használatával kapcsolatban. A rendezés tempdb általában megegyezik a példány rendezésével, amelynek nem kell egyeznie az adatbázis-rendezéssel.

2. példa

Például vegyük a korábban bemutatott (kínai) adatbázist, amelyet egy Latin1_General kollációval rendelkező példányban használunk:

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

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

Első pillantásra ez a két tábla úgy néz ki, mintha ugyanazzal a sémával rendelkeznének, de mivel az adatbázisok rendezései eltérnek, az értékek nem kompatibilisek:

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

Itt van az eredmények összessége.

Msg 468, Level 16, State 9, Line 2

A "Latin1_General_100_CI_AS_KS_WS_SC" és a "Chinese_Simplified_Pinyin_100_CI_AS" közötti kollációs ütközés nem oldható fel az egyenlőség művelet végrehajtásakor.

Ezt az ideiglenes tábla explicit módon történő rendezésével javíthatjuk. Az SQL Server ezt megkönnyíti a DATABASE_DEFAULT záradék kulcsszójának COLLATE megadásával.

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;

Ez a lekérdezés most hiba nélkül fut.

A változók esetén is láthatunk rendezéstől függő viselkedést. Vegye figyelembe a következő függvényt:

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

Ez egy meglehetősen sajátos függvény. Kis- és nagybetűérzékeny rendezés esetén a @i visszatérési záradék nem tud kötődni sem a @I-hez, sem a -höz. Egy kis- és nagybetűket nem érzékeny Latin1_General rendezési sorrendben @i összekapcsolódik @I-val, és a függvény 1 értéket ad vissza. Egy kis- és nagybetűk között nem különbséget tevő török rendezésű, @i-hez kötődik, és a függvény visszaadja a 2-t. Ez pusztítást okozhat egy olyan adatbázison, amely különböző rendezésű példányok között mozog.

Tartalmazott adatbázisok

Mivel a tartalmazott adatbázisok tervezési célja, hogy önállóvá tegyék őket, a példánytól és tempdb a rendezéstől való függőséget meg kell szakítani. Ehhez a tartalmazott adatbázisok bemutatják a katalógus-rendezés fogalmát. A katalógus rendezést a rendszer metaadataihoz és átmeneti objektumokhoz használja. A részletek az alábbiak szerint vannak megadva.

Egy tartalmazott adatbázisban a katalógus rendezése a következő Latin1_General_100_CI_AS_WS_KS_SC: . Ez a rendezés az SQL Server összes példányán található összes tárolt adatbázis esetében megegyezik, és nem módosítható.

Az adatbázis-rendezés megmarad, de csak a felhasználói adatok alapértelmezett rendezéseként használatos. Alapértelmezés szerint az adatbázis rendezése megegyezik az model adatbázis-rendezéssel, de a felhasználó módosíthatja egy CREATE vagy ALTER DATABASE parancs révén, mint a nem tartalmazott adatbázisok esetén.

Az CATALOG_DEFAULT feltételben egy új kulcsszó, COLLATE, érhető el. Ez a parancsikon a metaadatok aktuális rendezéséhez használható mind a tárolt, mind a nem tartalmazott adatbázisokban. Ez azt jelzi, hogy egy nem tartalmazott adatbázisban CATALOG_DEFAULT a rendszer az aktuális adatbázis-rendezést adja vissza, mivel a metaadatok az adatbázis-rendezésben lesznek rendezve. Egy tartalmazott adatbázisban ez a két érték eltérő lehet, mivel a felhasználó módosíthatja az adatbázis-rendezést, hogy az ne egyezzen a katalógus rendezésével.

A nem tartalmazott és a tárolt adatbázisok különböző objektumainak viselkedését ebben a táblázatban foglaljuk össze:

Termék Nem tartalmazott adatbázis Tartalmazott adatbázis
Felhasználói adatok (alapértelmezett) DATABASE_DEFAULT DATABASE_DEFAULT
Ideiglenes adatok (alapértelmezett) tempdb egybevetés DATABASE_DEFAULT
Metadaták DATABASE_DEFAULT / CATALOG_DEFAULT CATALOG_DEFAULT
Ideiglenes metaadatok tempdb rendezés CATALOG_DEFAULT
Változók Példányok rendezése CATALOG_DEFAULT
Goto-címkék Példányok rendezése CATALOG_DEFAULT
Kurzornevek Példányok összehasonlítása és rendezése CATALOG_DEFAULT

A korábban ismertetett temp table példában láthatjuk, hogy ez a rendezési viselkedés szükségtelenné teszi a legtöbb temp tábla által használt explicit COLLATE záradék használatát. Egy tartalmazott adatbázisban ez a kód hiba nélkül fut, még akkor is, ha az adatbázis és a példány rendezése eltér:

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;

Ez a lekérdezés azért működik, mert mind a T1_txt, mind a T2_txt a tartalmazott adatbázis rendezésében van rendezve.

Átmenet a tartalmazott és a nem tartalmazott környezetek között

Mindaddig, amíg egy tárolt adatbázis munkamenete megmarad, azon az adatbázison belül kell maradnia, amelyhez csatlakozott. Ebben az esetben a viselkedés egyszerű. Azonban, ha egy munkamenet keresztezi a tartalmazott és a nem tartalmazott környezeteket, a viselkedés összetettebbé válik, mivel a két szabálykészletet át kell hidalni. Ez részben tartalmazott adatbázisban fordulhat elő, mivel egy felhasználó egy másik adatbázisba kerülhet USE . Ebben az esetben a rendezési szabályok különbségét a következő elv kezeli.

  • A kötegek rendezési viselkedését az az adatbázis határozza meg, amelyben a köteg megkezdődik.

Ez a döntés a parancsok kiadása előtt történik, beleértve a kezdeti USEparancsokat is. Ez azt jelenti, hogy ha egy köteg egy tartalmazott adatbázisban kezdődik, de az első parancs USE egy nem tartalmazó adatbázisra vonatkozik, az köteghez továbbra is a tartalmazott rendezési szabályokat alkalmazza. Ebben a forgatókönyvben például egy változóra való hivatkozás több lehetséges kimenetelsel is rendelkezhet:

  • A hivatkozás pontosan egy egyezést talál. Ebben az esetben a hivatkozás hiba nélkül működik.

  • Előfordulhat, hogy a hivatkozás nem talál egyezést az aktuális összevetésben, ahol korábban volt ilyen. Ez hibát jelez, amely azt jelzi, hogy a változó nem létezik, annak ellenére, hogy látszólag létrejött.

  • A hivatkozás több olyan egyezést is megtalálhat, amelyek eredetileg eltérőek voltak. Ez szintén hibát jelez.

Ezt néhány példával illusztráljuk. Ezek esetében feltételezzük, hogy van egy részben tartalmazott adatbázis, MyCDB amelynek az adatbázis-rendezési beállítása az alapértelmezett rendezés. Latin1_General_100_CI_AS_WS_KS_SC Feltételezzük, hogy a példány rendezése Latin1_General_100_CS_AS_WS_KS_SC. A két kolláció csak a kis- és nagybetűk érzékenységében különbözik.

1. példa

Az alábbi példa azt az esetet szemlélteti, amikor a hivatkozás pontosan egy egyezést talál.

USE MyCDB;
GO

CREATE TABLE #a (x INT);

INSERT INTO #a VALUES (1);
GO

USE master;
GO

SELECT * FROM #a;
GO

Results:

Itt van az eredmények összessége.

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

Ebben az esetben az azonosított #a mind a kis- és nagybetűkre nem érzékeny, mind az érzékeny katalógusösszevetésben is kötődést mutat, és a kód működik.

2. példa

Az alábbi példa azt az esetet szemlélteti, amikor a hivatkozás nem talál egyezést az aktuális rendezésben, pedig korábban volt ilyen egyezés.

USE MyCDB;
GO

CREATE TABLE #a (x INT);

INSERT INTO #A VALUES (1);
GO

Itt a #A kapcsolódik #a-hez a kis- és nagybetűkre nem érzékeny alapértelmezett rendezésben, és a beszúrás sikeres.

Itt van az eredmények összessége.

(1 row(s) affected)

De ha folytatjuk a szkriptet...

USE master;
GO

SELECT * FROM #A;
GO

Hibát kapunk, amikor megpróbálunk kötődni a #A kis- és nagybetű érzékeny példány rendezéséhez.

Itt van az eredmények összessége.

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

3. példa

Az alábbi példa azt az esetet szemlélteti, amikor a hivatkozás több, eredetileg eltérő egyezést talál. Először tempdb-ban kezdünk (amely azonos kis- és nagybetű érzékeny rendezést alkalmaz, mint a mi példányunk), és végrehajtjuk a következő utasításokat.

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

Ez a lekérdezés sikeres, mivel a táblák különböznek ebben a rendezésben:

Itt van az eredmények összessége.

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

Ha azonban a tárolt adatbázisba lépünk, azt tapasztaljuk, hogy már nem tudunk ezekhez a táblákhoz kapcsolódni.

USE MyCDB;
GO

SELECT * FROM #a;
GO

Itt van az eredmények összessége.

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.