Udostępnij za pomocą


Sortowania zawartej bazy danych

Dotyczy:SQL ServerAzure SQL Managed Instance

Różne właściwości mają wpływ na kolejność sortowania i semantykę równości danych tekstowych, w tym uwzględnianie wielkości liter, czułość akcentu i język bazowy używany. Te cechy są wyrażane w programie SQL Server przez wybór sortowania danych. Aby uzyskać bardziej szczegółowe omówienie samego sortowania, zobacz Obsługa sortowania i Unicode.

Sortowania mają zastosowanie nie tylko do danych przechowywanych w tabelach użytkowników, ale także do całego tekstu obsługiwanego przez SQL Server, w tym metadanych, obiektów tymczasowych, nazw zmiennych itp. Obsługa tych elementów różni się w bazach danych o ograniczonych i nieograniczonych zasobach. Ta zmiana nie ma wpływu na wielu użytkowników, ale pomaga zapewnić niezależność i jednolitość wystąpień. Jednak może to również spowodować pewne zamieszanie i problemy w sesjach uzyskujących dostęp zarówno do zawartych, jak i niezawartych baz danych.

Zachowanie sortowania w zawartych bazach danych ma subtelne różnice w porównaniu do zachowania w niezawartych bazach danych. Takie zachowanie jest ogólnie korzystne, gwarantując niezależność wystąpienia i prostotę. Niektórzy użytkownicy mogą mieć problemy, szczególnie w przypadku, gdy sesja uzyskuje dostęp zarówno do zawartych, jak i nieuwzwiązanych baz danych.

Ten artykuł wyjaśnia zawartość zmiany i analizuje obszary, w których zmiana może powodować problemy.

Uwaga / Notatka

W przypadku usługi Azure SQL Database sortowania dla zawartych baz danych różnią się. Sortowanie bazy danych i sortowanie wykazu można ustawić podczas tworzenia bazy danych i nie można ich aktualizować. Określ sortowanie dla danych (COLLATE) i sortowania wykazu dla metadanych systemu i identyfikatorów obiektów (CATALOG_COLLATION). Aby uzyskać więcej informacji, zobacz CREATE DATABASE (TWORZENIE BAZY DANYCH).

Nieograniczone bazy danych

Wszystkie bazy danych mają sortowanie domyślne (które można ustawić podczas tworzenia lub zmieniania bazy danych). To sortowanie jest używane dla wszystkich metadanych w bazie danych oraz jako domyślny dla wszystkich kolumn tekstowych w bazie danych. Użytkownicy mogą wybrać inne sortowanie dla dowolnej konkretnej kolumny przy użyciu klauzuli COLLATE .

Przykład 1

Jeśli na przykład pracujemy w Pekinie, możemy użyć sortowania chińskiego:

ALTER DATABASE MyDB
    COLLATE Chinese_Simplified_Pinyin_100_CI_AS;

Teraz, jeśli utworzymy kolumnę, jej domyślne sortowanie to sortowanie chińskie, ale możemy wybrać inną kolumnę, jeśli chcemy:

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

Oto zestaw wyników.

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

Wydaje się to stosunkowo proste, ale pojawiają się kilka problemów. Ponieważ sortowanie kolumny zależy od bazy danych, w której jest tworzona tabela, występują problemy z użyciem tabel tymczasowych przechowywanych w tempdbprogramie . Sortowanie tempdb zazwyczaj odpowiada sortowaniu dla instancji, które nie musi być zgodne z sortowaniem bazy danych.

Przykład 2

Rozważmy na przykład pokazaną wcześniej (chińską) bazę danych, jeśli jest używana w wystąpieniu z sortowaniem Latin1_General :

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

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

Na pierwszy rzut oka te dwie tabele wyglądają tak, jakby miały ten sam schemat, ale ponieważ sortowania baz danych różnią się, wartości są niezgodne:

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

Oto zestaw wyników.

Msg 468, poziom 16, stan 9, wiersz 2

Nie można rozwiązać konfliktu sortowania między "Latin1_General_100_CI_AS_KS_WS_SC" i "Chinese_Simplified_Pinyin_100_CI_AS" w operacji równej.

Możemy rozwiązać ten problem, jawnie sortując tabelę tymczasową. Program SQL Server ułatwia to, podając DATABASE_DEFAULT słowo kluczowe dla 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;

To zapytanie jest teraz uruchamiane bez błędu.

Możemy również zaobserwować zależne od sortowania zachowanie zmiennych. Rozważmy następującą funkcję:

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

Jest to dość osobliwa funkcja. W sortowaniu uwzględniającym wielkość liter klauzula zwracania nie może wiązać się z @I ani z . W sortowaniu Latin1_General, które nie rozróżnia wielkości liter, @i łączy się z @I, a funkcja zwraca 1. W przypadku nie uwzględniania wielkości liter w tureckim sortowaniu @i wiąże się z , a funkcja zwraca wartość 2. Może to wywołać spustoszenie w bazie danych, która przenosi się między wystąpieniami z różnymi kolejnościami sortowania.

Zawarte bazy danych

Ponieważ celem projektowania zawartych baz danych jest uczynienie ich samodzielnymi, zależność od wystąpienia i tempdb sortowania musi zostać zerwana. W tym celu zawarte bazy danych przedstawiają koncepcję sortowania wykazu. Sortowanie wykazu jest używane w przypadku metadanych systemu i obiektów przejściowych. Szczegółowe informacje są podane w następujący sposób.

W zawartej bazie danych sortowanie wykazu to Latin1_General_100_CI_AS_WS_KS_SC. Sortowanie jest takie samo dla wszystkich zawartych baz danych we wszystkich wystąpieniach programu SQL Server i nie można ich zmienić.

Sortowanie bazy danych jest zachowywane, ale jest używane tylko jako domyślne sortowanie danych użytkownika. Domyślnie sortowanie bazy danych jest takie samo jak model sortowanie bazy danych, ale użytkownik może je zmienić za pomocą polecenia CREATE lub ALTER DATABASE, tak jak w przypadku niepowiązanych baz danych.

Nowe słowo kluczowe , CATALOG_DEFAULTjest dostępne w klauzuli COLLATE . Jest to używane jako skrót do bieżącego sortowania metadanych zarówno w zawartych, jak i nieuwzwiązanych bazach danych. Oznacza to, że w bazie danych bez ograniczeń CATALOG_DEFAULT zwraca bieżące sortowanie bazy danych, ponieważ metadane są sortowane według sortowania bazy danych. W zawartej bazie danych te dwie wartości mogą być różne, ponieważ użytkownik może zmienić sortowanie bazy danych, aby nie pasować do sortowania wykazu.

Zachowanie różnych obiektów zarówno w nieuwzwiązanych, jak i zawartych bazach danych jest podsumowane w tej tabeli:

Produkt Niepowiązana baza danych Zawarta baza danych
Dane użytkownika (ustawienie domyślne) DATABASE_DEFAULT DATABASE_DEFAULT
Dane tymczasowe (ustawienie domyślne) tempdb Sortowanie DATABASE_DEFAULT
Metadane DATABASE_DEFAULT / CATALOG_DEFAULT CATALOG_DEFAULT
Metadane tymczasowe tempdb Sortowanie CATALOG_DEFAULT
Variables Sortowanie wystąpień CATALOG_DEFAULT
Etykiety "goto" Sortowanie wystąpień CATALOG_DEFAULT
Nazwy kursorów Sortowanie wystąpień CATALOG_DEFAULT

W przykładzie tabeli tymczasowej opisanym wcześniej widać, że to zachowanie sortowania eliminuje potrzebę jawnej klauzuli COLLATE w większości przypadków użycia tabeli tymczasowej. W zawartej bazie danych ten kod jest teraz uruchamiany bez błędu, nawet jeśli sortowanie bazy danych i wystąpień są różne:

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;

To zapytanie działa, ponieważ zarówno T1_txt , jak i T2_txt są uporządkowane według ustawień sortowania bazy danych w zawartej bazie danych.

Między kontekstami zawartymi i nieograniczonymi

Dopóki sesja w zawartej bazie danych pozostanie zawarta, musi pozostać w bazie danych, z którą nawiązała połączenie. W takim przypadku zachowanie jest proste. Jednak jeśli sesja przekracza konteksty zawarte i niezwiązane, zachowanie staje się bardziej złożone, ponieważ dwa zestawy reguł muszą być łączone. Może się to zdarzyć w częściowo zawartej bazie danych, ponieważ użytkownik może USE korzystać z innej bazy danych. W tym przypadku różnica w regułach sortowania jest obsługiwana przez następującą zasadę.

  • Zachowanie sortowania dla partii jest określane przez bazę danych, w której rozpoczyna się partia.

Ta decyzja jest podjęta przed wydaniem jakichkolwiek poleceń, w tym początkowego USE. Oznacza to, że jeśli grupa rozpoczyna się w zawartej bazie danych, ale pierwszym poleceniem jest USE do bazy danych nie będącej częścią, zachowanie sortowania w zawartości jest nadal używane dla grupy. Biorąc pod uwagę ten scenariusz, odwołanie do zmiennej, na przykład, może mieć wiele możliwych wyników:

  • Odwołanie może znaleźć dokładnie jedno dopasowanie. W takim przypadku referencja działa bez błędu.

  • Odwołanie może nie znaleźć dopasowania w bieżącym porządku sortowania, w którym poprzednio istniało dopasowanie. Spowoduje to wystąpienie błędu wskazującego, że zmienna nie istnieje, mimo że została ona najwyraźniej utworzona.

  • Referencja może znaleźć wiele dopasowań, które były pierwotnie odrębne. Spowoduje to również wystąpienie błędu.

Zilustrujemy to za pomocą kilku przykładów. W przypadku tych zakładamy, że istnieje częściowo zawarta baza danych o nazwie MyCDB z ustawionym sortowaniem bazy danych na sortowanie domyślne. Latin1_General_100_CI_AS_WS_KS_SC Zakładamy, że sortowanie instancji to Latin1_General_100_CS_AS_WS_KS_SC. Te dwa sortowania różnią się tylko wrażliwością na wielkość liter.

Przykład 1

Poniższy przykład ilustruje przypadek, w którym referencja znajduje dokładnie jedno dopasowanie.

USE MyCDB;
GO

CREATE TABLE #a (x INT);

INSERT INTO #a VALUES (1);
GO

USE master;
GO

SELECT * FROM #a;
GO

Results:

Oto zestaw wyników.

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

W takim przypadku zidentyfikowane #a są powiązane zarówno w kolejności sortowania katalogu bez uwzględniania wielkości liter, jak i w kolejności sortowania instancji z uwzględnieniem wielkości liter, i kod działa.

Przykład 2

Poniższy przykład ilustruje przypadek, w którym odwołanie nie znajduje dopasowania w bieżącym sortowaniu, mimo że wcześniej takie istniało.

USE MyCDB;
GO

CREATE TABLE #a (x INT);

INSERT INTO #A VALUES (1);
GO

W tym miejscu #A jest powiązany z #a w sortowaniu domyślnym bez uwzględniania wielkości liter, a wstawianie działa.

Oto zestaw wyników.

(1 row(s) affected)

Ale jeśli będziemy kontynuować skrypt...

USE master;
GO

SELECT * FROM #A;
GO

Występuje błąd podczas próby powiązania z #A w uwzględniającej wielkość liter sortowaniu instancji.

Oto zestaw wyników.

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

Przykład 3

Poniższy przykład ilustruje przypadek, w którym referencja znajduje wiele dopasowań, które pierwotnie były odrębne. Najpierw zaczynamy od tempdb (który ma taką samą, uwzględniającą wielkość liter, kolejność sortowania jak nasza instancja) i wykonujemy następujące instrukcje.

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

To zapytanie powiedzie się, ponieważ tabele są odrębne w tym sortowaniu:

Oto zestaw wyników.

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

Jeśli jednak przejdziemy do naszej zawartej bazy danych, okaże się, że nie możemy już powiązać z tymi tabelami.

USE MyCDB;
GO

SELECT * FROM #a;
GO

Oto zestaw wyników.

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.