SQL 2005'ten [SQL_Latin1_General_CP1_CI_AS] 2008'e geçiş - 'geriye dönük uyumluluk' kullanarak herhangi bir özelliği kaybedecek miyim


18

SQL 2005'ten [Instance ve DB'nin harmanlanması SQL_Latin1_General_CP1_CI_AS] SQL Server'a [varsayılan olarak Latin1_General_CI_AS] geçmektedir .

Bir SQL 2008 R2 yüklemesini tamamladım Latin1_General_CI_ASve veritabanının geri yüklenmesi devam ederken varsayılan harmanlamayı kullandım SQL_Latin1_General_CP1_CI_AS. İstisnai sorunlar oluştu - #temp tabloları nerede Latin1_General_CI_ASdb iken ve SQL_Latin1_General_CP1_CI_ASben şimdi buradayım - şimdi tuzaklar hakkında tavsiyeye ihtiyacım var.

SQL 2008 R2 kurulumu, ben kullanımına yüklemesinde seçeneğine sahip 'SQL Collation, used for backwards compatibility'Ben 2005 veritabanı olarak aynı harmanlama seçim yapma olanağına sahip: SQL_Latin1_General_CP1_CI_AS.

  1. Bu, #temp tablolarıyla ilgili sorun yaşamama izin verecek, ancak tuzaklar var mı?

  2. SQL 2008'in "geçerli" harmanlamasını kullanmadan herhangi bir işlevsellik veya özelliği kaybedebilir miyim?

  3. 2008'den SQL 2012'ye geçtiğimizde (örneğin 2 yıl içinde) ne olacak? O zaman sorun yaşayacak mıyım?
  4. Bir noktada gitmek zorunda kalır Latin1_General_CI_ASmıyım?

  5. Bazı DBA'nın komut dosyasının tam veritabanlarının satırlarını tamamladığını okudum ve sonra ekleme komut dosyasını yeni harmanlama ile veritabanına çalıştırıyorum - Çok korkuyorum ve bundan sakınıyorum - bunu tavsiye eder misiniz?


2
SQL Server 2014'te Hekaton'a girebileceğinizi düşünüyorsanız, burada okumayı düşünmek isteyebileceğiniz başka bir şey var .
Aaron Bertrand

Yanıtlar:


20

Her şeyden önce, böyle uzun bir cevap için özür dilerim, çünkü insanlar harmanlama, sıralama düzeni, kod sayfası vb. Terimler hakkında konuştuğunda hala çok fazla karışıklık olduğunu hissediyorum.

Gönderen BOL :

SQL Server'daki harmanlamalar , verileriniz için sıralama kuralları, büyük / küçük harf duyarlılığı ve aksan duyarlılığı özellikleri sağlar . Char ve varchar gibi karakter veri türleriyle kullanılan harmanlamalar, kod sayfasını ve bu veri türü için temsil edilebilecek karşılık gelen karakterleri belirler. SQL Server'ın yeni bir örneğini yüklüyor, veritabanı yedeklemesini geri yüklüyor veya sunucuyu istemci veritabanlarına bağlarken, çalışacağınız verilerin yerel gereksinimlerini, sıralama düzenini ve büyük / küçük harf duyarlılığını anlamanız önemlidir. .

Bu, Harmanlama'nın, verilerin karakter dizilerinin nasıl sıralandığı ve karşılaştırıldığı ile ilgili kuralları belirlediği için çok önemli olduğu anlamına gelir.

Not: COLLATIONPROPERTY hakkında daha fazla bilgi

Şimdi önce farklılıkları anlayalım ......

T-SQL altında çalışıyor:

SELECT *
FROM::fn_helpcollations()
WHERE NAME IN (
        'SQL_Latin1_General_CP1_CI_AS'
        ,'Latin1_General_CI_AS'
        )
GO

SELECT 'SQL_Latin1_General_CP1_CI_AS' AS 'Collation'
    ,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'CodePage') AS 'CodePage'
    ,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'LCID') AS 'LCID'
    ,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
    ,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'Version') AS 'Version'

UNION ALL

SELECT 'Latin1_General_CI_AS' AS 'Collation'
    ,COLLATIONPROPERTY('Latin1_General_CI_AS', 'CodePage') AS 'CodePage'
    ,COLLATIONPROPERTY('Latin1_General_CI_AS', 'LCID') AS 'LCID'
    ,COLLATIONPROPERTY('Latin1_General_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
    ,COLLATIONPROPERTY('Latin1_General_CI_AS', 'Version') AS 'Version'
GO

Sonuçlar şöyle olacaktır:

resim açıklamasını buraya girin

Yukarıdaki sonuçlara bakıldığında, tek fark 2 harmanlama arasındaki Sıralama Düzeni'dir.Ancak bu doğru değil, nedenini aşağıdaki gibi görebilirsiniz:

Test 1:

--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
    DROP TABLE Table_Latin1_General_CI_AS;

IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
    DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;

-- Create a table using collation Latin1_General_CI_AS 
CREATE TABLE Table_Latin1_General_CI_AS (
    ID INT IDENTITY(1, 1)
    ,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
    )

-- add some data to it 
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')

INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('Kin_Tester1')

-- Create second table using collation SQL_Latin1_General_CP1_CI_AS 
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
    ID INT IDENTITY(1, 1)
    ,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
    )

-- add some data to it 
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')

INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('Kin_Tester1')

--Now try to join both tables
SELECT *
FROM Table_Latin1_General_CI_AS LG
INNER JOIN Table_SQL_Latin1_General_CP1_CI_AS SLG ON LG.Comments = SLG.Comments
GO

Test 1'in Sonuçları:

Msg 468, Level 16, State 9, Line 35
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.

Yukarıdaki sonuçlardan, farklı harmanlamalara sahip sütunlardaki değerleri doğrudan COLLATEkarşılaştıramayacağımızı, sütun değerlerini karşılaştırmak için kullanmanız gerektiğini görebiliriz.

TEST 2:

Erland Sommarskog'un msdn hakkındaki bu tartışmada belirttiği gibi büyük fark performanstır .

--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
    DROP TABLE Table_Latin1_General_CI_AS;

IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
    DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;

-- Create a table using collation Latin1_General_CI_AS 
CREATE TABLE Table_Latin1_General_CI_AS (
    ID INT IDENTITY(1, 1)
    ,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
    )

-- add some data to it 
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')

INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_tester1')

-- Create second table using collation SQL_Latin1_General_CP1_CI_AS 
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
    ID INT IDENTITY(1, 1)
    ,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
    )

-- add some data to it 
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')

INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_tester1')

--- Her iki tabloda da Dizin Oluştur

CREATE INDEX IX_LG_Comments ON  Table_Latin1_General_CI_AS(Comments)
go
CREATE INDEX IX_SLG_Comments ON  Table_SQL_Latin1_General_CP1_CI_AS(Comments)

--- Sorguları çalıştırın

DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO

--- Bu IMPLICIT Dönüşümü olacak

resim açıklamasını buraya girin

--- Sorguları çalıştırın

DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO

--- Bunun IMPLICIT Dönüşümü YOKTUR

resim açıklamasını buraya girin

Ben hem benim veritabanı ve Sunucu harmanlamayı çünkü Örtülü dönüşüm için nedenidir SQL_Latin1_General_CP1_CI_ASve masa Table_Latin1_General_CI_AS sütun vardır Yorumlar olarak tanımlanan VARCHAR(50)ile HARMANLA Latin1_General_CI_AS nedenle SQL Server bir IMPLICIT dönüşüm yapmak zorunda araması sırasında,.

Test 3:

Aynı kurulumla, şimdi yürütme planlarındaki değişiklikleri görmek için varchar sütunlarını nvarchar değerleriyle karşılaştıracağız.

- sorguyu çalıştır

DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments =  (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO

resim açıklamasını buraya girin

- sorguyu çalıştır

DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO

resim açıklamasını buraya girin

İlk sorgunun Dizin araması yapabildiğini, ancak İkincil dönüşüm yapması gerektiğini, ikincisinin ise büyük tabloları tarayacağı zaman performans açısından verimsiz olduğunu kanıtlayan bir Dizin taraması gerçekleştirdiğini unutmayın.

Sonuç:

  • Yukarıdaki testlerin tümü, doğru harmanlamaya sahip olmanın veritabanı sunucusu örneğiniz için çok önemli olduğunu göstermektedir.
  • SQL_Latin1_General_CP1_CI_AS unicode ve unicode olmayanlar için verileri sıralamanıza izin veren kurallara sahip bir SQL harmanlaması farklıdır.
  • SQL harmanlama, yukarıdaki testlerde görüldüğü gibi unicode ve unicode olmayan verileri karşılaştırırken Dizin'i kullanamaz, nvarchar verilerini varchar verileriyle karşılaştırırken Dizin taraması yapar ve aramaz.
  • Latin1_General_CI_AS unicode ve unicode olmayanlar için verileri sıralamanıza izin veren kurallara sahip bir Windows harmanlaması aynıdır.
  • Windows harmanlama, unicode ve unicode olmayan verileri karşılaştırırken yine de Index'i (yukarıdaki örnekte Index search) kullanabilir, ancak hafif bir performans cezası görürsünüz.
  • Erland Sommarskog cevap + işaret ettiği bağlantı öğelerini okumanızı tavsiye ederim.

Bu, #temp tablolarıyla ilgili sorun yaşamama izin verecek, ancak tuzaklar var mı?

Yukarıdaki cevabımı gör.

SQL 2008'in "geçerli" harmanlamasını kullanmadan herhangi bir işlevsellik veya özelliği kaybedebilir miyim?

Her şey hangi işlev / özelliklere başvurduğunuza bağlıdır. Harmanlama, verilerin saklanması ve sıralanmasıdır.

2008'den SQL 2012'ye geçtiğimizde (örneğin 2 yıl içinde) ne olacak? O zaman sorun yaşayacak mıyım? Bir noktada Latin1_General_CI_AS'a gitmek zorunda kalır mıyım?

Kefil olamaz! İşler değişebileceğinden ve Microsoft'un önerisiyle aynı çizgide olmak her zaman iyi olduğundan, verilerinizi ve yukarıda bahsettiğim tuzakları anlamanız gerekir. Ayrıca buna ve bu bağlantı öğelerine bakın.

Bazı DBA'nın komut dosyasının tam veritabanlarının satırlarını tamamladığını okudum ve sonra ekleme komut dosyasını yeni harmanlama ile veritabanına çalıştırıyorum - Çok korkuyorum ve bundan sakınıyorum - bunu tavsiye eder misiniz?

Harmanlamayı değiştirmek istediğinizde, bu tür komut dosyaları yararlı olur. Kendimi sunucu harmanlama birçok kez sunucu harmanlama maç için değişen bulduk ve oldukça düzgün yapan bazı komut dosyaları var. İhtiyacınız olursa bana bildirin.

Referanslar :


5

@Kin yaptığı ayrıntılı neyi ilave olarak cevap , sunucunun (yani örneğinin) varsayılan harmanlama geçiş yaparken dikkat edilecek birkaç şey vardır (yatay çizginin üzerinde ürün Soru belirtilen iki alfabe doğrudan alakalı; öğeler yatay çizginin altında genel ile ilgilidir):

  • SİZİN veritabanının varsayılan COLLATION İSE DEĞİL DEĞİŞEN ardından "örtük dönüştürme" performans sorunu Kin cevabı gerektiğini @ açıklanan değildir dize hazır ve yerel değişkenler veritabanı'nın varsayılan Harmanlama değil sunucunun kullandığından bir sorun. Örnek düzeyi Harmanlaması'nın değiştirildiği ancak veritabanı düzeyi Harmanlaması'nın değiştirilmediği senaryo için tek etkiler (her ikisi de aşağıda ayrıntılı olarak açıklanmıştır):

    • geçici tablolarla olası harmanlama çakışmaları (ancak tablo değişkenleriyle değil).
    • Değişkenlerin ve / veya imleçlerin kasası bildirimleriyle eşleşmiyorsa olası bozuk kod (ancak bu yalnızca ikili veya büyük / küçük harfe duyarlı harmanlama içeren bir örneğe taşınırsa gerçekleşebilir).
  • Bu iki Harmanlama arasındaki bir fark, VARCHARveriler için belirli karakterleri nasıl sıraladıklarıdır (bu NVARCHARverileri etkilemez ). EBCDIC olmayan SQL_Harmanlamalar, VARCHARveri için "Dize Sıralama" olarak adlandırılanları , diğer tüm Harmanlamalar ve hattaNVARCHAR EBCDIC olmayan SQL_Harmanlamalar için veriler "Kelime Sırala" olarak adlandırılanları kullanır. Fark, "Kelime Sıralaması" nda, çizgi -ve kesme işaretine '(ve belki birkaç karaktere?) Çok düşük bir ağırlık verilmesi ve dizelerde başka bir fark olmadığı sürece esasen yok sayılmasıdır. Bu davranışı çalışırken görmek için aşağıdakileri çalıştırın:

    DECLARE @Test TABLE (Col1 VARCHAR(10) NOT NULL);
    INSERT INTO @Test VALUES ('aa');
    INSERT INTO @Test VALUES ('ac');
    INSERT INTO @Test VALUES ('ah');
    INSERT INTO @Test VALUES ('am');
    INSERT INTO @Test VALUES ('aka');
    INSERT INTO @Test VALUES ('akc');
    INSERT INTO @Test VALUES ('ar');
    INSERT INTO @Test VALUES ('a-f');
    INSERT INTO @Test VALUES ('a_e');
    INSERT INTO @Test VALUES ('a''kb');
    
    SELECT * FROM @Test ORDER BY [Col1] COLLATE SQL_Latin1_General_CP1_CI_AS;
    -- "String Sort" puts all punctuation ahead of letters
    
    SELECT * FROM @Test ORDER BY [Col1] COLLATE Latin1_General_100_CI_AS;
    -- "Word Sort" mostly ignores dash and apostrophe

    İadeler:

    String Sort
    -----------
    a'kb
    a-f
    a_e
    aa
    ac
    ah
    aka
    akc
    am
    ar

    ve:

    Word Sort
    ---------
    a_e
    aa
    ac
    a-f
    ah
    aka
    a'kb
    akc
    am
    ar

    "String Sort" davranışını "kaybedeceksiniz", ancak ben bir "özellik" dediğimden emin değilim. İstenmeyen sayılan bir davranıştır (Windows harmanlamalarından herhangi birine getirilmediği gerçeği ile kanıtlandığı gibi). Bununla birlikte, bir , iki alfabe (arasındaki davranış kesin bir fark sadece olmayan EBCDIC için, tekrarVARCHAR verilerine) ve "Dize sırala" davranışa dayalı kodu ve / veya müşteri beklentileri olabilir. Bu, kodunuzu test etmenizi ve muhtemelen davranıştaki bu değişikliğin kullanıcılar üzerinde herhangi bir olumsuz etkisi olup olmadığını araştırmayı gerektirir.

  • Arasındaki bir diğer fark SQL_Latin1_General_CP1_CI_ASve Latin1_General_100_CI_ASyapma yeteneğidir Genişletme üzerinde VARCHAR(veri NVARCHARverileri zaten çoğu için bu yapabilir SQL_, örneğin ele alma gibi Harmanlamalar) æbu sanki ae:

    IF ('æ' COLLATE SQL_Latin1_General_CP1_CI_AS =
        'ae' COLLATE SQL_Latin1_General_CP1_CI_AS)
    BEGIN
      PRINT 'SQL_Latin1_General_CP1_CI_AS';
    END;
    
    IF ('æ' COLLATE Latin1_General_100_CI_AS =
        'ae' COLLATE Latin1_General_100_CI_AS)
    BEGIN
      PRINT 'Latin1_General_100_CI_AS';
    END;

    İadeler:

    Latin1_General_100_CI_AS

    Burada "kaybettiğiniz" tek şey olduğunu değil bu genişletmeleri yapabiliyor olmayı. Genel olarak, bu bir Windows Harmanlama'ya geçmenin bir başka yararıdır. Ancak, "Dize Sıralama" ile "Kelime Sıralama" hareketinde olduğu gibi, aynı uyarı geçerlidir: iki harmanlama arasındaki (yine sadece VARCHARveriler için) belirli bir davranış farkıdır ve kodunuz ve / veya müşteriniz olabilir. Bu eşlemelerin olmamasına bağlı beklentiler .Bu, kodunuzu test etmenizi ve muhtemelen davranıştaki bu değişikliğin kullanıcılar üzerinde herhangi bir olumsuz etkisi olup olmadığını araştırmayı gerektirir.

    (ilk önce bu SO cevabında @Zarepheth tarafından not edilmiştir: SQL Server SQL_Latin1_General_CP1_CI_AS güvenle Latin1_General_CI_AS'a dönüştürülebilir mi? )

  • Sunucu düzeyinde harmanlama, dahil olan sistem veritabanlarının harmanlamasını ayarlamak için kullanılır [model]. [model]Veritabanı içeren, yeni veritabanları oluşturmak için bir şablon olarak kullanılır [tempdb]her sunucu başlatma sırasında. Ancak, sunucu düzeyinde harmanlama değişikliği harmanlamayı değiştirse [tempdb]bile CREATE #TempTable, yürütüldüğünde "geçerli" olan veritabanı arasındaki harmanlama farklarını düzeltmenin biraz kolay bir yolu vardır [tempdb]. Geçici tablolar oluştururken, COLLATEyan tümcesi kullanarak bir harmanlama bildirin ve aşağıdakilerin bir harmanlamasını belirtin DATABASE_DEFAULT:

    CREATE TABLE #Temp (Col1 NVARCHAR(40) COLLATE DATABASE_DEFAULT);

  • Birden çok sürüm mevcutsa, istenen harmanlamanın en son sürümünü kullanmak en iyisidir. SQL Server 2005'ten başlayarak, "90" dizi harmanlama getirildi ve SQL Server 2008 "100" dizi harmanlama getirdi. Bu harmanlamaları aşağıdaki sorguları kullanarak bulabilirsiniz:

    SELECT * FROM sys.fn_helpcollations() WHERE [name] LIKE N'%[_]90[_]%'; -- 476
    
    SELECT * FROM sys.fn_helpcollations() WHERE [name] LIKE N'%[_]100[_]%'; -- 2686

    SQL Server 2008 R2'de olduğunuz için Latin1_General_100_CI_ASyerine kullanmalısınız Latin1_General_CI_AS.

  • Bu özel harmanlamaların (örn. SQL_Latin1_General_CP1_CS_ASVe Latin1_General_100_CS_AS) büyük / küçük harfe duyarlı sürümleri arasındaki fark , büyük / küçük harfe duyarlı sıralama yaparken büyük ve küçük harfler arasındadır. Bu [start-end], LIKEişleç ve PATINDEXişlevle kullanılabilen tek karakterli sınıf aralıklarını da (yani ) etkiler . Aşağıdaki üç sorgu, bu etkiyi hem sıralama hem de karakter aralığı için gösterir:

    SELECT tmp.col AS [Upper-case first]
    FROM (VALUES ('a'), ('A'), ('b'), ('B'), ('c'), ('C')) tmp(col)
    WHERE tmp.col LIKE '%[A-C]%' COLLATE SQL_Latin1_General_CP1_CS_AS
    ORDER BY tmp.col COLLATE SQL_Latin1_General_CP1_CS_AS; -- Upper-case first
    
    SELECT tmp.col AS [Lower-case first]
    FROM (VALUES ('a'), ('A'), ('b'), ('B'), ('c'), ('C')) tmp(col)
    WHERE tmp.col LIKE '%[A-C]%' COLLATE Latin1_General_100_CS_AS
    ORDER BY tmp.col COLLATE Latin1_General_100_CS_AS; -- Lower-case first
    
    SELECT tmp.col AS [Lower-case first]
    FROM (VALUES (N'a'), (N'A'), (N'b'), (N'B'), (N'c'), (N'C')) tmp(col)
    WHERE tmp.col LIKE N'%[A-C]%' COLLATE SQL_Latin1_General_CP1_CS_AS
    ORDER BY tmp.col COLLATE SQL_Latin1_General_CP1_CS_AS; -- Lower-case first

    Küçük harfe (aynı harf için) göre büyük harfe göre sıralama yapmanın tek yolu, Hungarian_Technical_*Harmanlamalar ve bir avuç SQL_Harmanlama (yalnızca bu davranışı VARCHARveri için destekleyen) olan bu davranışı destekleyen 31 Harmanlamadan birini kullanmaktır. ).

  • Bu özel değişiklik için daha az önemli, ancak sunucuyu ikili veya büyük / küçük harfe duyarlı bir harmanlama olarak değiştirmenin etkileneceği için bilmek hala iyi. Sunucu düzeyi harmanlamanın da etkilemesi:

    • yerel değişken isimleri
    • CURSOR adları
    • GOTO etiketleri
    • sysnameveri tipinin ad çözümlemesi


    Yani, tüm kötü kodlardan görünüşte sorumlu olan siz veya "yakın zamanda ayrılan programcı" ;-) kasaya dikkat etmediyse ve @SomethingIDdaha sonra bir değişken olarak ilan ettiyse , @somethingIddaha sonradan bahsedilirse , bir davaya taşındığında kırılır duyarlı veya ikili harmanlama. Benzer şekilde, kullandığı kod sysnameveri türü ancak olarak ifade eder SYSNAME, SysNamebir harf duyarlı veya ikili harmanlama kullanarak bir örneğine hareket ederse veya tüm alt durumda başka bir şey de kıracak.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.