Nie można rozwiązać konfliktu sortowania między „SQL_Latin1_General_CP1_CI_AS” i „Latin1_General_CI_AS” w operacji równej operacji


344

Mam następujący kod

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

Podczas uruchamiania kodu błąd jest wklejany w tytule po dodaniu dwóch złączeń dla tabeli C. Myślę, że może to mieć coś wspólnego z faktem, że korzystam z programu SQL Server 2008 i przywróciłem kopię tej bazy danych na moja maszyna, która jest rok 2005.

Odpowiedzi:


307

Masz niedopasowanie dwóch różnych zestawień w swoim stole. Możesz sprawdzić, jakie zestawienia ma każda kolumna w twoich tabelach, używając tego zapytania:

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

Zestawienia są potrzebne i używane podczas zamawiania i porównywania ciągów. Zasadniczo dobrym pomysłem jest stosowanie jednego, unikalnego zestawienia w całej bazie danych - nie używaj różnych zestawień w obrębie jednej tabeli lub bazy danych - pytasz tylko o problemy ...

Po zaakceptowaniu pojedynczego zestawienia możesz zmienić te tabele / kolumny, które nie pasują jeszcze za pomocą tego polecenia:

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

Marc

AKTUALIZACJA: aby znaleźć indeksy pełnotekstowe w bazie danych, użyj tego zapytania tutaj:

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

Następnie możesz upuścić indeks pełnotekstowy, używając:

DROP FULLTEXT INDEX ON (tablename)

Dzięki marc, właśnie tego szukałem, jeden ze stolików był innym zestawieniem z jakiegoś głupiego powodu! Spróbuję zmienić standardowe zestawienie i zobaczę, co się stanie.
jhowe

marc, otrzymuję to teraz: nie można zmienić ani upuścić kolumny, ponieważ jest włączona dla wyszukiwania pełnotekstowego.
jhowe

1
W takim przypadku musisz tymczasowo upuścić indeks pełnotekstowy na tę tabelę, zmienić sortowanie, a następnie ponownie utworzyć indeks pełnotekstowy
marc_s,

1
Dzięki OP, utworzyłem tymczasowy stół, więc to pomogło, ale ponieważ nie mogłem go zmienić, musiałem tylko zadeklarować go poprawnie, aby zacząć (w następujący sposób): DECLARE @ TABLE TABLE (CompareMessage VARCHAR (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL)
FrostbiteXIII

1
dlaczego nie możemy mieć 2 różnych zestawień na tym samym stole. Jeśli mam 1 kolumnę jako nvarchar, która potrzebuje tylko angielskich nazw i inną kolumnę jako rosyjskie litery, inną kolumnę jako japońskie litery. Jak to zorganizować? Czy istnieje jedno zestawienie obejmujące wszystkie te elementy?
batmaci,

856

Wykonuję następujące czynności:

...WHERE 
    fieldname COLLATE DATABASE_DEFAULT = otherfieldname COLLATE DATABASE_DEFAULT

Działa za każdym razem. :)


68
Jest to jeden z najbardziej przydatnych postów na SO
Jamie Strauss,

2
Użyłem tego rozwiązania, ponieważ pracowałem z dwoma starszymi systemami korzystającymi z tej samej bazy danych, więc nie byłem pewien, czy zmiana sortowania tabel zepsuje funkcjonalność.
paolobueno

5
Jeśli te same dwa pola są używane razem w innych miejscach (porównania, związki, łączenie itp.), Upewnij się, że każde z nich ma również określone sortowanie.
Zarepheth,

5
To jest bardzo przydatne. Korzystam z lokalnej bazy danych i wykonuję zapytania do połączonego serwera, który ma dwa różne układy. Oczywiście nie mogę zmienić sortowania na połączonym serwerze i nie chciałem zmieniać mojej lokalnie, więc jest to absolutnie najlepsza odpowiedź.
jtate

7
@ppumkin Chociaż jest to świetne rozwiązanie, nadal pozwala uniknąć problemu, a nie go rozwiązać. Chyba że chcesz zmienić sortowanie dla każdego zapytania, co jest uciążliwe i nie optymalnie działa. Chociaż jest to świetna odpowiedź, zaakceptowana odpowiedź jest lepsza.
Rob

80

Użyj collateklauzuli w swoim zapytaniu:

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

Może nie mam poprawnej składni (sprawdź BOL), ale możesz to zrobić, aby zmienić sortowanie w locie dla zapytania - może być konieczne dodanie klauzuli dla każdego sprzężenia.

edycja: Zdałem sobie sprawę, że to nie do końca było właściwe - klauzula sortowania idzie za polem, które należy zmienić - w tym przykładzie zmieniłem sortowanie w tA.oldValuepolu.


29

Zidentyfikuj pola, dla których generuje ten błąd, i dodaj do nich następujące: COLLATE DATABASE_DEFAULT

Istnieją dwie tabele połączone w polu Kod:

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

Zaktualizuj zapytanie do:

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

Dzięki. Pracując w bazie danych prod, nie zawsze możemy zmieniać strukturę bazy danych zgodnie z przyjętą odpowiedzią.
Jennifer Wood

20

Może się to łatwo zdarzyć, gdy masz 2 różne bazy danych, a zwłaszcza 2 różne bazy danych z 2 różnych serwerów. Najlepszą opcją jest zmiana na wspólną kolekcję i wykonanie połączenia lub porównania.

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

13

@Valkyrie niesamowita odpowiedź. Pomyślałem, że włożyłem tu przypadek, gdy wykonuję to samo z podzapytaniem, to procedura przechowywana, ponieważ zastanawiałem się, czy twoja odpowiedź działa w tym przypadku, i zrobiła się niesamowicie.

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

12

W miejscu, w którym dodawane są kryteria collate SQL_Latin1_General_CP1_CI_AS

To działa dla mnie.

WHERE U.Fullname = @SearchTerm  collate SQL_Latin1_General_CP1_CI_AS

6

Główną przyczyną jest to, że baza danych serwera SQL, z której wzięto schemat, zawiera sortowanie różniące się od instalacji lokalnej. Jeśli nie chcesz się martwić o sortowanie, zainstaluj ponownie program SQL Server lokalnie, używając tego samego sortowania, co baza danych SQL Server 2008.


Miałem ten sam problem, musisz najpierw sprawdzić właściwości serwera i bazy danych, aby sprawdzić, czy mają one takie same sortowanie
madan

5

błąd (nie można rozwiązać konfliktu sortowania między ....) zwykle występuje podczas porównywania danych z wielu baz danych.

ponieważ nie możesz teraz zmienić sortowania baz danych, użyj COLLATE DATABASE_DEFAULT.

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

to nie różni się od innej już udzielonej odpowiedzi: stackoverflow.com/a/1607725/479251
Pac0

4

Miałem już coś takiego i stwierdziliśmy, że zestawienie między 2 tabelami było inne.

Sprawdź, czy są takie same.


4

Dzięki odpowiedzi marc_s rozwiązałem swój pierwotny problem - zainspirowany, aby pójść o krok dalej i opublikować jedno podejście do transformacji całej tabeli jednocześnie - skrypt tsql do generowania instrukcji alter column:

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)

dostaje: ALTER TABELA Podmiot stowarzyszony ALTER COLUMN myTable NVARCHAR (4000) COLLATE Latin1_General_CI_AS NOT NULL

Przyznaję, że jestem zaskoczony potrzebą col.max_length / 2 -


Myślę, że podział przez dwa jest wymagany, ponieważ długość jest przechowywana wewnętrznie jako liczba bajtów. Nvarchar przyjmuje dwa bajty na znak zamiast jednego jako varchar.
Zebi 18.04.16

Świetna robota, jakkolwiek powyższe zapytania nie liczą się dla typów danych ncha prawdopodobnie z powodu col.max_length / 2 -
Imran

2

Dla tych, którzy mają skrypt CREATE DATABASE (jak w moim przypadku) dla bazy danych, która powoduje ten problem, możesz użyć następującego skryptu CREATE, aby dopasować zestawienie:

-- 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

lub

-- 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

Odnosi się to do pożądanego sortowania do wszystkich tabel, a tego właśnie potrzebowałem. Idealne jest, aby spróbować utrzymać to samo sortowanie dla wszystkich baz danych na serwerze. Mam nadzieję że to pomoże.

Więcej informacji na następujący link: SQL SERVER - Tworzenie bazy danych z innym sortowaniem na serwerze


2

Użyłem treści z tej strony, aby utworzyć następujący skrypt, który zmienia sortowanie wszystkich kolumn we wszystkich tabelach:

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. Długość kolumn nvarchar musi być podzielona przez 2
palota

2

Sprawdź poziom niedopasowanego sortowania (serwer, baza danych, tabela, kolumna, znak).

Jeśli to serwer, te kroki pomogły mi raz:

  1. Zatrzymaj serwer
  2. Znajdź narzędzie sqlservr.exe
  3. Uruchom to polecenie:

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

  4. Uruchom serwer SQL:

    net start name_of_instance

  5. Sprawdź ponownie sortowanie swojego serwera.

Oto więcej informacji:

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


2

Jeśli występuje to w całej bazie danych, lepiej zmienić sortowanie bazy danych w następujący sposób:

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 

Odnośnik tutaj


niestety nie zmieni to sortowania dla istniejących tabel, ale tylko domyślne dla nowych tabel
RockScience

2

Dodano kod do odpowiedzi @ JustSteve, aby radzić sobie z kolumnami varchar i varchar (MAX):

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

Aby rozwiązać ten problem w zapytaniu bez zmiany bazy danych, możesz rzutować wyrażenia po drugiej stronie znaku „=” za pomocą

COLLATE SQL_Latin1_General_CP1_CI_AS

jak sugerowano tutaj .


1

Miałem podobny błąd (nie mogę rozwiązać konfliktu sortowania między „SQL_Latin1_General_CP1_CI_AS” i „SQL_Latin1_General_CP1250_CI_AS” w operacji INTERSECT), kiedy użyłem starego sterownika jdbc.

Rozwiązałem to, pobierając nowy sterownik z Microsoft lub projektu open source jTDS .


1

oto co zrobiliśmy, w naszej sytuacji potrzebujemy wykonania zapytania ad hoc z użyciem ograniczenia daty na żądanie, a zapytanie jest zdefiniowane w tabeli.

Nasze nowe zapytanie musi dopasowywać dane między różnymi bazami danych i obejmować dane z obu z nich.

Wygląda na to, że COLLATION różni się między db, który importuje dane z systemu iSeries / AS400, a naszą bazą danych raportowania - może to wynikać z określonych typów danych (takich jak greckie akcenty na imiona i tak dalej).

Dlatego użyliśmy poniższej klauzuli łączenia:

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

1

Możesz to łatwo zrobić za pomocą 4 prostych kroków

  1. wykonaj kopię zapasową bazy danych, po prostu dodaj
  2. zmień sortowanie bazy danych: kliknij prawym przyciskiem myszy bazę danych, wybierz właściwości, przejdź do opcji i zmień sortowanie na wymagane sortowanie.
  3. Wygeneruj skrypt, aby usunąć i odtworzyć wszystkie obiekty bazy danych: kliknij bazę danych prawym przyciskiem myszy, wybierz zadania, wybierz wygeneruj skrypt ... (upewnij się, że wybierasz Drop & Create w Zaawansowanych opcjach kreatora, wybierz także Schemat i dane)
  4. Uruchom skrypt wygenerowany powyżej

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

Możesz nie mieć żadnych problemów z sortowaniem w bazie danych, ale jeśli przywróciłeś kopię bazy danych z kopii zapasowej na serwerze z innym zestawieniem niż pochodzenie, a Twój kod tworzy tabele tymczasowe, te tabele tymczasowe odziedziczą sortowanie od serwer i wystąpiłyby konflikty z bazą danych.


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

0

Miałem podobny wymóg; dokumentując moje podejście tutaj dla każdego z podobnym scenariuszem ...

Scenariusz

  • Mam bazę danych z czystej instalacji z poprawnymi zestawieniami.
  • Mam inną bazę danych, która ma niewłaściwe zestawienia.
  • Muszę zaktualizować to drugie, aby użyć zestawień zdefiniowanych na pierwszym.

Rozwiązanie

Użyj porównania schematów programu SQL Server (z SQL Server Data Tools / Visual Studio), aby porównać źródło (czysta instalacja) z miejscem docelowym (db z niepoprawnym zestawieniem).

W moim przypadku bezpośrednio porównałem dwa DB; chociaż możesz pracować za pośrednictwem projektu, aby umożliwić ręczne dostosowywanie elementów między ...

  • Uruchom program Visual Studio
  • Utwórz nowy projekt danych programu SQL Server
  • Kliknij Narzędzia, SQL Server, Nowe porównanie schematów
  • Wybierz źródłową bazę danych
  • Wybierz docelową bazę danych
  • Kliknij opcje (⚙)
    • Pod Object Typeswybierz tylko te typy, które Cię interesują (dla mnie było to tylko Viewsi Tables)
    • Pod Generalwybierz:
      • Blokuj możliwą utratę danych
      • Wyłącz i włącz ponownie wyzwalacze DDL
      • Zignoruj ​​ścieżkę pliku dostawcy kryptograficznego
      • Zignoruj ​​ścieżkę pliku i pliku dziennika
      • Zignoruj ​​rozmiar pliku
      • Ignoruj ​​umieszczanie grupy plików
      • Zignoruj ​​ścieżkę do katalogu pełnego tekstu
      • Zignoruj ​​obudowę słowa kluczowego
      • Zignoruj ​​identyfikatory SID logowania
      • Zignoruj ​​cytowane identyfikatory
      • Ignoruj ​​żywotność trasy
      • Zignoruj ​​średnik między instrukcjami
      • Zignoruj ​​białe znaki
      • Moduł odświeżania skryptu
      • Sprawdzanie poprawności skryptu pod kątem nowych ograniczeń
      • Sprawdź zgodność sortowania
      • Sprawdź wdrożenie
  • Kliknij Porównaj
    • Odznacz wszystkie obiekty oznaczone do usunięcia (Uwaga: mogą nadal występować problemy z sortowaniem; ale ponieważ nie są one zdefiniowane w bazie danych źródła / szablonu, nie wiemy; tak czy inaczej, nie chcemy stracić rzeczy, jeśli jesteśmy kierowanie tylko na zmiany sortowania). Możesz odznaczyć wszystkie naraz, klikając DELETEfolder prawym przyciskiem myszy i wybierając EXCLUDE.
    • Podobnie wykluczamy dla każdego CREATE obiektów (tutaj, ponieważ nie istnieją one w celu, nie mogą mieć tam niewłaściwego zestawienia; pytanie, czy powinny istnieć, jest pytaniem na inny temat).
    • Kliknij każdy obiekt pod ZMIEŃ, aby zobaczyć skrypt dla tego obiektu. Użyj mechanizmu różnicowego, aby upewnić się, że zmieniamy tylko układanie (wszelkie inne ręcznie wykryte różnice, które prawdopodobnie będziesz chciał ręcznie wykluczyć / obsługiwać te obiekty).
  • Kliknij, Updateaby wprowadzić zmiany

Wciąż wymaga to trochę wysiłku ręcznego (np. Sprawdzenie, czy wpływasz tylko na sortowanie) - ale radzi sobie z zależnościami.

Możesz także zachować projekt bazy danych prawidłowego schematu, aby móc użyć uniwersalnego szablonu dla swoich baz danych, jeśli masz więcej niż 1 do aktualizacji, zakładając, że wszystkie docelowe bazy danych powinny mieć ten sam schemat.

Możesz także użyć funkcji znajdź / zamień na plikach w projekcie bazy danych, jeśli chcesz tam masowo zmienić ustawienia (np. Aby utworzyć projekt z nieprawidłowej bazy danych za pomocą porównania schematów, zmienić pliki projektu, a następnie przełączyć źródło / cel w porównanie schematu w celu wypchnięcia zmian z powrotem do DB).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.