Aynı işleme "SQL_Latin1_General_CP1_CI_AS" ve "Latin1_General_CI_AS" arasındaki harmanlama çakışması çözülemiyor


345

Takip koduna sahibim

SELECT tA.FieldName As [Field Name],
       COALESCE(tO_A.[desc], tO_B.[desc], tO_C.Name, tA.OldVAlue) AS [Old Value],
       COALESCE(tN_A.[desc], tN_B.[desc], tN_C.Name, tA.NewValue) AS [New Value],
       U.UserName AS [User Name],
       CONVERT(varchar, tA.ChangeDate) AS [Change Date] 
  FROM D tA
       JOIN 
       [DRTS].[dbo].[User] U 
         ON tA.UserID = U.UserID
       LEFT JOIN 
       A tO_A 
         on tA.FieldName = 'AID' 
        AND tA.oldValue = CONVERT(VARCHAR, tO_A.ID)
       LEFT JOIN 
       A tN_A 
         on tA.FieldName = 'AID' 
        AND tA.newValue = CONVERT(VARCHAR, tN_A.ID)
       LEFT JOIN 
       B tO_B 
         on tA.FieldName = 'BID' 
        AND tA.oldValue = CONVERT(VARCHAR, tO_B.ID)
       LEFT JOIN 
       B tN_B 
         on tA.FieldName = 'BID' 
        AND tA.newValue = CONVERT(VARCHAR, tN_B.ID)
       LEFT JOIN 
       C tO_C 
         on tA.FieldName = 'CID' 
        AND tA.oldValue = tO_C.Name
       LEFT JOIN 
       C tN_C 
         on tA.FieldName = 'CID' 
        AND tA.newValue = tN_C.Name
 WHERE U.Fullname = @SearchTerm
ORDER BY tA.ChangeDate

Kodu çalıştırırken tablo C için iki birleşimler ekledikten sonra başlığında yapıştırılan hata alıyorum Bu SQL Server 2008 kullanıyorum ve bunun için bu db bir kopyasını geri yükledim gerçeği ile ilgili bir şey olabilir düşünüyorum 2005 olan makinem.

Yanıtlar:


307

Tablonuzda iki farklı harmanlama uyuşmazlığı var. Bu sorguyu kullanarak tablolarınızdaki her bir sütunun hangi harmanlamalarını kontrol edebilirsiniz:

SELECT
    col.name, col.collation_name
FROM 
    sys.columns col
WHERE
    object_id = OBJECT_ID('YourTableName')

Dizeleri sıralarken ve karşılaştırırken harmanlamalara ihtiyaç duyulur ve kullanılır. Veritabanınız boyunca tek, benzersiz bir harmanlama kullanmak genellikle iyi bir fikirdir - tek bir tablo veya veritabanı içinde farklı harmanlama kullanmayın - sadece sorun istiyorsunuz ...

Tek bir harmanlama için karar verdikten sonra, henüz eşleşmeyen tabloları / sütunları bu komutu kullanarak değiştirebilirsiniz:

ALTER TABLE YourTableName
  ALTER COLUMN OffendingColumn
    VARCHAR(100) COLLATE Latin1_General_CI_AS NOT NULL

üzüm posası

GÜNCELLEME: veritabanınızdaki tam metin dizinlerini bulmak için şu sorguyu burada kullanın:

SELECT
    fti.object_Id,
    OBJECT_NAME(fti.object_id) 'Fulltext index',
    fti.is_enabled,
    i.name 'Index name',
    OBJECT_NAME(i.object_id) 'Table name'
FROM 
    sys.fulltext_indexes fti
INNER JOIN 
    sys.indexes i ON fti.unique_index_id = i.index_id

Daha sonra aşağıdakileri kullanarak tam metin dizinini bırakabilirsiniz:

DROP FULLTEXT INDEX ON (tablename)

Tam olarak aradığım şey türü olan teşekkürler marc, tablolardan biri aptalca bir nedenle farklı harmanlama oldu! Standart harmanlamayı değiştirmeye çalışacağım ve ne olacağını göreceğim.
jhowe

marc Bunu şimdi alıyorum: Tam Metin Arama için etkinleştirildiğinden sütun değiştirilemiyor veya bırakılamıyor.
jhowe

1
Bu durumda, tam metin dizininizi bu tabloya geçici olarak bırakmanız, harmanlamayı değiştirmeniz ve ardından tam metin dizini tekrar oluşturmanız gerekir
marc_s

1
Teşekkürler OP, bu yardımcı oldu, bu yüzden geçici bir tablo kuruyordum, ama ben tablo değiştiremedim gibi, ben sadece (aşağıdaki gibi) ile başlamak için doğru beyan gerekir: DECLARE @Table TABLE (CompareMessage VARCHAR (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL)
FrostbiteXIII

1
Neden aynı masada 2 farklı harmanlama yapamıyoruz. Sadece İngilizce isimler ve rus harfleri olarak diğer sütun, Japon harfleri olarak diğer sütun gerektiren nvarchar olarak 1 sütun varsa. Bunu nasıl ayarlayabilirim? Tüm bunları kapsayan tek bir harmanlama var mı?
Mart'ta batmaci

856

Aşağıdakileri yaparım:

...WHERE 
    fieldname COLLATE DATABASE_DEFAULT = otherfieldname COLLATE DATABASE_DEFAULT

Her zaman çalışır. :)



2
Bu çözümü kullandım çünkü aynı db kullanan iki eski sistemle çalışıyordum, bu yüzden tabloların harmanlamasını değiştirmenin işlevselliği bozacağından emin değildim.
paolobueno

5
Aynı iki alan başka yerlerde birlikte kullanılıyorsa (karşılaştırmalar, birlikler, birleşme vb.) Bunların her birinin de harmanlama belirtildiğinden emin olun.
Zarepheth

5
Bu son derece kullanışlıdır. Yerel bir veritabanı kullanıyorum ve bağlantılı bir sunucuya karşı sorgulama ve iki farklı harmanlama var. Açıkçası bağlantılı sunucuda harmanlamayı değiştiremiyorum ve yerel olarak benimkini değiştirmek istemedim, bu yüzden bu kesinlikle en iyi cevap.
14'te

7
@ppumkin Harika bir çözüm olsa da , sorunu çözmek yerine yalnızca sorunu önler . Her sorgu için harmanlamayı değiştirmek istemiyorsanız, bu yorucu ve en iyi performansı göstermez. Harika bir cevap olsa da, hissettiğim kabul edilen cevap daha iyidir.
Rob

80

Kullanım collateSorgunuzda maddesini:

LEFT JOIN C tO_C on tA.FieldName = 'CID' AND tA.oldValue COLLATE Latin1_General_CI_AS = tO_C.Name  

Sözdizimi tam olarak doğru olmayabilir (BOL'u kontrol edin), ancak sorgunun anında harmanlamasını değiştirmek için bunu yapabilirsiniz - her birleştirme için yan tümceyi eklemeniz gerekebilir.

edit: Bu oldukça doğru olmadığını fark - harmanlama cümlesini değiştirmek için gereken alandan sonra gider - bu örnekte tA.oldValuesahada harmanlamayı değiştirdim .


29

Bu hatayı attığı alanları belirleyin ve bunlara aşağıdakileri ekleyin: COLLATE DATABASE_DEFAULT

Kod alanında birleştirilmiş iki tablo vardır:

...
and table1.Code = table2.Code
...

Sorgunuzu şu şekilde güncelleyin:

...
and table1.Code COLLATE DATABASE_DEFAULT = table2.Code COLLATE DATABASE_DEFAULT
...

Teşekkürler. Ürün veritabanında çalışırken, veritabanı yapısını her zaman kabul edilen yanıtın önerdiği şekilde değiştiremeyiz.
Jennifer Wood

21

Bu, 2 farklı veritabanınız ve 2 farklı sunucudan özel olarak 2 farklı veritabanınız olduğunda kolayca gerçekleşebilir. En iyi seçenek, onu ortak bir koleksiyona değiştirmek ve birleştirme veya karşılaştırmayı yapmaktır.

SELECT 
   *
FROM sd
INNER JOIN pd ON sd.SCaseflowID COLLATE Latin1_General_CS_AS = pd.PDebt_code COLLATE Latin1_General_CS_AS

13

@Valkyrie harika cevap. Bir alt sorgu ile aynı işlemi yaparken burada bir dava koyduğumu sanıyordum, cevabınızın bu durumda çalışıp çalışmadığını merak ettim ve harika oldu.

...WHERE fieldname COLLATE DATABASE_DEFAULT in (
          SELECT DISTINCT otherfieldname COLLATE DATABASE_DEFAULT
          FROM ...
          WHERE ...
        )

12

Kriterlerin nereye eklendiğine collate SQL_Latin1_General_CP1_CI_AS

Bu benim için çalışıyor.

WHERE U.Fullname = @SearchTerm  collate SQL_Latin1_General_CP1_CI_AS

6

Temel neden şemayı aldığınız sql sunucusu veritabanının yerel yüklemenizden farklı bir harmanlamaya sahip olmasıdır. Harmanlama konusunda endişelenmek istemiyorsanız SQL Server'ı, SQL Server 2008 veritabanıyla aynı harmanlamayı kullanarak yerel olarak yeniden yükleyin.


Aynı sorun vardı, ilk önce aynı harmanlama olup olmadığını görmek için sunucunuzu ve veritabanı özelliğini kontrol etmeniz gerekir
madan

5

hatası (.... arasındaki harmanlama çakışması çözülemez) genellikle birden çok veritabanındaki veriler karşılaştırılırken oluşur.

veritabanlarının harmanlamasını şimdi değiştiremeyeceğiniz için, COLLATE DATABASE_DEFAULT kullanın.

----------
AND db1.tbl1.fiel1 COLLATE DATABASE_DEFAULT =db2.tbl2.field2 COLLATE DATABASE_DEFAULT 

bu zaten verilen başka bir cevaptan farklı değil: stackoverflow.com/a/1607725/479251
Pac0

4

Daha önce böyle bir şey oldu ve ne buldum 2 tablolar arasındaki harmanlama farklı oldu.

Bunların aynı olup olmadığını kontrol edin.


4

Marc_s'ın cevabı sayesinde, orijinal sorunumu çözdüm - bir adım daha ileri gitmekten ve bir seferde tüm bir tabloyu dönüştürmek için bir yaklaşım yayınlamaktan ilham aldım - tsql scriptini alter sütun ifadeleri oluşturmak için:

DECLARE @tableName VARCHAR(MAX)
SET @tableName = 'affiliate'
--EXEC sp_columns @tableName
SELECT  'Alter table ' + @tableName + ' alter column ' + col.name
        + CASE ( col.user_type_id )
            WHEN 231
            THEN ' nvarchar(' + CAST(col.max_length / 2 AS VARCHAR) + ') '
          END + 'collate Latin1_General_CI_AS ' + CASE ( col.is_nullable )
                                                    WHEN 0 THEN ' not null'
                                                    WHEN 1 THEN ' null'
                                                  END
FROM    sys.columns col
WHERE   object_id = OBJECT_ID(@tableName)

alır: ALTER TABLE Ortaklık ALTER COLUMN myTable NVARCHAR (4000) COLLATE Latin1_General_CI_AS NOT NULL

Col.max_length / 2 ihtiyacından şaşkın olduğumu itiraf edeceğim -


Sanırım ikiye bölmek gerekiyor çünkü uzunluk dahili olarak bayt sayısı olarak saklanıyor. Nvarchar karakter başına iki bayt, varchar yerine iki bayt alır.
Zebi

Harika bir çalışma, muhtemelen col.max_length / 2 nedeniyle ncha veri türleri için doz sayımı nasıl sorgulanır / -
Imran

2

Bu soruna neden olan veritabanı için CREATE DATABASE komut dosyası (benim durumum gibi) olanlar için harmanlamayı eşleştirmek için aşağıdaki CREATE komut dosyasını kullanabilirsiniz:

-- Create Case Sensitive Database
CREATE DATABASE CaseSensitiveDatabase
COLLATE SQL_Latin1_General_CP1_CS_AS -- or any collation you require
GO
USE CaseSensitiveDatabase
GO
SELECT *
FROM sys.types
GO
--rest of your script here

veya

-- Create Case In-Sensitive Database
CREATE DATABASE CaseInSensitiveDatabase
COLLATE SQL_Latin1_General_CP1_CI_AS -- or any collation you require
GO
USE CaseInSensitiveDatabase
GO
SELECT *
FROM sys.types
GO
--rest of your script here

Bu, istediğim harmanlamayı tüm tablolara uygular. Sunucudaki tüm veritabanları için harmanlamayı aynı tutmaya çalışmak idealdir. Bu yardımcı olur umarım.

Aşağıdaki bağlantı hakkında daha fazla bilgi: SQL SERVER - Sunucuda Farklı Harmanlama ile Veritabanı Oluşturma


2

Tüm sitelerdeki tüm sütunların harmanlamasını değiştiren aşağıdaki komut dosyasını oluşturmak için bu sitedeki içeriği kullandım :

CREATE PROCEDURE [dbo].[sz_pipeline001_collation] 
    -- Add the parameters for the stored procedure here
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;


SELECT 'ALTER TABLE [' + SYSOBJECTS.Name + '] ALTER COLUMN [' + SYSCOLUMNS.Name + '] ' +
SYSTYPES.name + 
    CASE systypes.NAME
    WHEN 'text' THEN ' '
    ELSE
    '(' + RTRIM(CASE SYSCOLUMNS.length
    WHEN -1 THEN 'MAX'
    ELSE CONVERT(CHAR,SYSCOLUMNS.length)
    END) + ') ' 
    END

    + ' ' + ' COLLATE Latin1_General_CI_AS ' + CASE ISNULLABLE WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END
    FROM SYSCOLUMNS , SYSOBJECTS , SYSTYPES
    WHERE SYSCOLUMNS.ID = SYSOBJECTS.ID
    AND SYSOBJECTS.TYPE = 'U'
    AND SYSTYPES.Xtype = SYSCOLUMNS.xtype
    AND SYSCOLUMNS.COLLATION IS NOT NULL
    AND NOT ( sysobjects.NAME LIKE 'sys%' )
    AND NOT ( SYSTYPES.name LIKE 'sys%' )

END

1
SYSCOLUMNS. Nvarchar sütunlarının
uzunluğu

2

Uyuşmayan harmanlama düzeyini kontrol edin (sunucu, veritabanı, tablo, sütun, karakter).

Sunucu ise, bu adımlar bir kez bana yardımcı oldu:

  1. Sunucuyu durdurun
  2. Sqlservr.exe aracınızı bulun
  3. Bu komutu çalıştırın:

    sqlservr -m -T4022 -T3659 -s"name_of_insance" -q "name_of_collation"

  4. SQL sunucunuzu başlatın:

    net start name_of_instance

  5. Sunucunuzun harmanlamasını tekrar kontrol edin.

İşte daha fazla bilgi:

https://www.mssqltips.com/sqlservertip/3519/changing-sql-server-collation-after-installation/


2

Bu, DB'nizin tamamında gerçekleşirse, DB harmanlamanızı bu şekilde değiştirmek daha iyidir:

USE master;  
GO  
ALTER DATABASE MyOptionsTest  
COLLATE << INSERT COLATION REQUIRED >> ;  
GO  

--Verify the collation setting.  
SELECT name, collation_name  
FROM sys.databases  
WHERE name = N'<< INSERT DATABASE NAME >>';  
GO 

Burada referans


ne yazık ki bu mevcut tablolar için harmanlamayı değiştirmeyecek, sadece yeni tablolar için varsayılanı değiştirecektir
RockScience

2

@ JustSteve'in varchar ve varchar (MAX) sütunlarıyla başa çıkma cevabına kod eklendi:

DECLARE @tableName VARCHAR(MAX)
SET @tableName = 'first_notes'
--EXEC sp_columns @tableName
SELECT  'Alter table ' + @tableName + ' alter column ' + col.name
        + CASE ( col.user_type_id )
            WHEN 231
            THEN ' nvarchar(' + CAST(col.max_length / 2 AS VARCHAR) + ') '
            WHEN 167
            THEN ' varchar(' + CASE col.max_length 
                                WHEN -1 
                                THEN 'MAX'
                                ELSE 
                                CAST(col.max_length AS VARCHAR)
                                end
                                 + ') '
          END + 'collate Latin1_General_CI_AS ' + CASE ( col.is_nullable )
                                                    WHEN 0 THEN ' not null'
                                                    WHEN 1 THEN ' null'
                                                  END
FROM    sys.columns col
WHERE   object_id = OBJECT_ID(@tableName)

2

Herhangi bir veritabanını değiştirmeden sorgudaki bu sorunu gidermek için, ifadeleri "=" işaretinin diğer tarafına

COLLATE SQL_Latin1_General_CP1_CI_AS

burada önerildiği gibi .


1

Eski jdbc sürücüsü kullandığımda benzer bir hata (INTERSECT işleminde "SQL_Latin1_General_CP1_CI_AS" ve "SQL_Latin1_General_CP1250_CI_AS" arasındaki harmanlama çakışması çözülemedi).

Yeni sürücü indirerek çözdüm Microsoft veya açık kaynaklı proje jTDS'den çözdüm .


1

İşte yaptıklarımız, bizim durumumuzda, talep üzerine bir tarih kısıtlaması kullanılarak yürütülecek geçici bir sorgumuz olması gerekir ve sorgu bir tabloda tanımlanır.

Yeni sorgumuzun farklı veritabanları arasındaki verileri eşleştirmesi ve her ikisinden veri içermesi gerekir.

KOLEKSİYON, iSeries / AS400 sisteminden veri aktaran db ile raporlama veritabanımız arasında farklı görünüyor - bunun nedeni belirli veri türlerinden (isimlerdeki Yunanca vurgular vb.) Kaynaklanıyor olabilir.

Bu yüzden aşağıdaki birleştirme maddesini kullandık:

...LEFT Outer join ImportDB..C4CTP C4 on C4.C4CTP COLLATE Latin1_General_CS_AS=CUS_Type COLLATE Latin1_General_CS_AS

1

Bunu 4 kolay adımı kullanarak kolayca yapabilirsiniz

  1. veritabanınızı yedekleyin,
  2. veritabanı harmanlamasını değiştir: veritabanına sağ tıklayın, özellikleri seçin, seçeneklere gidin ve harmanlamayı gerekli harmanlamaya değiştirin.
  3. Tüm veritabanı nesnelerinizi Bırakmak ve Yeniden Oluşturmak için bir komut dosyası oluşturun: veritabanınızı sağ tıklayın, görevleri seçin, komut dosyası oluştur ... 'u seçin (Sihirbazın Gelişmiş seçeneklerinde Bırak ve Oluştur'u seçtiğinizden emin olun, Ayrıca Şema ve Veri'yi seçin)
  4. Yukarıda Oluşturulan Komut Dosyasını Çalıştırma

1
INSERT INTO eSSLSmartOfficeSource2.[dbo].DeviceLogs  (DeviceId,UserId,LogDate,UpdateFlag) 
SELECT DL1.DeviceId ,DL1.UserId COLLATE DATABASE_DEFAULT,DL1.LogDate 
,0 FROM eSSLSmartOffice.[dbo].DeviceLogs DL1 
WHERE  NOT EXISTS 
(SELECT DL2.DeviceId ,DL2.UserId COLLATE DATABASE_DEFAULT
,DL2.LogDate ,DL2.UpdateFlag 
FROM eSSLSmartOfficeSource2.[dbo].DeviceLogs DL2    
WHERE  DL1.DeviceId =DL2.DeviceId
 and DL1.UserId collate  Latin1_General_CS_AS=DL2.UserId collate  Latin1_General_CS_AS
  and DL1.LogDate =DL2.LogDate )

0

Veritabanınızda herhangi bir harmanlama sorunu olmayabilir, ancak veritabanınızın bir kopyasını başlangıç ​​noktasından farklı harmanlama içeren bir sunucudaki yedeklemeden geri yüklediyseniz ve kodunuz geçici tablolar oluşturuyorsa, bu geçici tablolar harmanlamayı devralır ve veritabanınızla çakışma olur.


0
ALTER DATABASE test2            --put your database name here
COLLATE Latin1_General_CS_AS    --replace with the collation you need

0

Benzer bir gereksinimim vardı; benzer senaryoya sahip herkes için buradaki yaklaşımımı belgeliyor ...

senaryo

  • Doğru harmanlama ile temiz bir yükleme bir veritabanı var.
  • Yanlış harmanlama olan başka bir veritabanı var.
  • Birincisinde tanımlanan harmanlamaları kullanmak için ikincisini güncellemem gerekiyor.

Çözüm

Kaynağı (temiz yükleme) hedefle (geçersiz harmanlama ile db) karşılaştırmak için SQL Server Şema Karşılaştırması'nı ( SQL Server Veri Araçları / Visual Studio'dan) kullanın.

Benim durumumda iki DB'yi doğrudan karşılaştırdım; aralarında parçaları elle ayarlamanıza izin vermek için bir proje aracılığıyla çalışabilirsiniz ...

  • Visual Studio'yu çalıştırın
  • Yeni bir SQL Server Veri Projesi oluşturma
  • Araçlar, SQL Server, Yeni Şema Karşılaştırması'nı tıklayın
  • Kaynak veritabanını seçin
  • Hedef veritabanını seçin
  • Tıklama seçenekleri (⚙)
    • Altında Object Typesilgilendiğiniz yalnızca türlerini seçin (benim için yalnızca idi Viewsve Tables)
    • Altında Generalseçin:
      • Olası veri kaybını engelle
      • DDL tetikleyicilerini devre dışı bırak ve yeniden etkinleştir
      • Şifreleme sağlayıcısı dosya yolunu yoksay
      • Dosya ve Günlük Dosyası Yolunu Yoksay
      • Dosya boyutunu yoksay
      • Dosya grubu yerleşimini yoksay
      • Tam metin kataloğu dosya yolunu yoksay
      • Anahtar kelime muhafazasını yoksay
      • Giriş SID'lerini yoksay
      • Alıntılanan tanımlayıcıları yoksay
      • Rota ömrünü yoksay
      • İfadeler arasındaki noktalı virgül yoksay
      • Boşluğu yoksay
      • Komut dosyası yenileme modülü
      • Yeni kısıtlamalar için kod doğrulaması
      • Harmanlama uyumluluğunu doğrulayın
      • Dağıtımı doğrulayın
  • Karşılaştır'ı tıklayın
    • Silinmek üzere işaretlenmiş nesnelerin işaretini kaldırın (Not: bunların hala harmanlama sorunları olabilir; ancak kaynak / şablon db'de tanımlanmadığından bilmiyoruz; her iki durumda da, yalnızca hedefleme harmanlama değişiklikleri). Sen sağ tıklayarak bir defada tüm unchceck olabilir DELETEklasörüne ve seçme EXCLUDE.
    • Aynı şekilde, CREATE nesne tutun (burada hedefte bulunmadıkları için orada yanlış harmanlama yapamazlar; var olmaları gerekip gerekmediği başka bir konu için bir sorundur).
    • Bu nesnenin komut dosyasını görmek için DEĞİŞTİR altındaki her bir nesneye tıklayın. Farkı yalnızca harmanlamayı değiştirdiğimizden emin olmak için (diğer farklılıkları manuel olarak saptadığınızda, bu nesneleri manuel olarak hariç tutmak / işlemek isteyeceksiniz).
  • UpdateDeğişiklikleri itmek için tıklayın

Bu yine de manuel çaba gerektirir (örneğin yalnızca harmanlamayı etkilediğinizi kontrol etmek) - ancak sizin için bağımlılıkları ele alır.

Ayrıca, geçerli şemanın bir veritabanı projesini tutabilirsiniz, böylece tüm hedef DB'lerin aynı şema ile sonuçlanması gerektiğini varsayarak, 1'den fazla güncellemeniz varsa DB'leriniz için evrensel bir şablon kullanabilirsiniz.

Ayrıca, ayarları toplu olarak değiştirmek isterseniz bir veritabanı projesindeki dosyaları bul / değiştir özelliğini de kullanabilirsiniz (örn. Şema karşılaştırması kullanarak projeyi geçersiz veritabanından oluşturabilir, proje dosyalarını değiştirebilir, ardından kaynağı / hedefi değiştirebilirsiniz. şema, değişikliklerinizi tekrar DB'ye aktarmak için karşılaştırılır).

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.