it-swarm.com.de

Der Kollatierungskonflikt zwischen "SQL_Latin1_General_CP1_CI_AS" und "Latin1_General_CI_AS" kann in der Gleichheitsoperation nicht aufgelöst werden

Ich habe den folgenden Code

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

Beim Ausführen des Codes bekomme ich den Fehler, der in den Titel eingefügt wird, nachdem die beiden Joins für Tabelle C hinzugefügt wurden. Ich denke, das hat etwas mit der Tatsache zu tun, dass ich SQL Server 2008 verwende und eine Kopie dieser Datenbank auf wiederhergestellt habe Meine Maschine ist 2005.

276
jhowe

In Ihrer Tabelle gibt es zwei unterschiedliche Kollatierungen. Mit dieser Abfrage können Sie überprüfen, welche Sortierungen jede Spalte in Ihrer Tabelle hat.

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

Sortierfolgen werden beim Sortieren und Vergleichen von Strings benötigt und verwendet. Im Allgemeinen ist es eine gute Idee, eine einzige, eindeutige Kollatierung in Ihrer Datenbank zu verwenden. Verwenden Sie keine unterschiedlichen Kollatierungen in einer einzelnen Tabelle oder Datenbank.

Wenn Sie sich für eine einzelne Sortierung entschieden haben, können Sie die Tabellen/Spalten, die noch nicht übereinstimmen, mit diesem Befehl ändern:

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

Marc

UPDATE: Um die Volltextindizes in Ihrer Datenbank zu finden, verwenden Sie diese Abfrage hier:

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

Sie können den Volltextindex dann löschen, indem Sie

DROP FULLTEXT INDEX ON (tablename)
271
marc_s

Ich mache folgendes:

...WHERE 
    fieldname COLLATE DATABASE_DEFAULT = otherfieldname COLLATE DATABASE_DEFAULT

Funktioniert jedes Mal. :)

707
Valkyrie

Verwenden Sie die collate-Klausel in Ihrer Abfrage:

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

Die Syntax ist möglicherweise nicht genau richtig (siehe BOL), aber Sie können dies tun, um die Kollatierung für die Abfrage im Handumdrehen zu ändern. Möglicherweise müssen Sie die Klausel für jeden Join hinzufügen.

edit: Ich habe festgestellt, dass dies nicht ganz richtig war - die Sortierklausel folgt dem Feld, das Sie ändern müssen - in diesem Beispiel habe ich die Sortierung im Feld tA.oldValue geändert. 

63
Ray

Ermitteln Sie die Felder, für die dieser Fehler ausgegeben wird, und fügen Sie folgende Felder hinzu: COLLATE DATABASE_DEFAULT

Es gibt zwei Tabellen im Feld Code:

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

Aktualisieren Sie Ihre Abfrage auf:

...
and table1.Code COLLATE DATABASE_DEFAULT = table2.Code COLLATE DATABASE_DEFAULT
...
24
Palak.Maheria

@Valkyrie tolle Antwort. Ich dachte, ich habe hier einen Fall eingefügt, wenn ich dasselbe mit einer Unterabfrage innerhalb einer gespeicherten Prozedur durchführe, da ich mich gefragt habe, ob Ihre Antwort in diesem Fall funktioniert und sie wirklich großartig war.

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

Fügen Sie in den Where-Kriterien collate SQL_Latin1_General_CP1_CI_AS hinzu.

Das funktioniert für mich.

WHERE U.Fullname = @SearchTerm  collate SQL_Latin1_General_CP1_CI_AS
10

Dies kann leicht passieren, wenn Sie zwei verschiedene Datenbanken und speziell zwei verschiedene Datenbanken von zwei verschiedenen Servern haben. Am besten können Sie es in eine gemeinsame Sammlung ändern und den Join oder den Vergleich durchführen. 

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

Die Hauptursache ist, dass die SQL Server-Datenbank, aus der Sie das Schema entnommen haben, eine Sortierung aufweist, die sich von Ihrer lokalen Installation unterscheidet. Wenn Sie sich keine Gedanken über die Sortierung machen möchten, installieren Sie SQL Server lokal mit derselben Sortierung wie die SQL Server 2008-Datenbank.

6
Robert

fehler (Kann den Kollatierungskonflikt zwischen ... nicht auflösen.) tritt normalerweise beim Vergleich von Daten aus mehreren Datenbanken auf.

da Sie die Sortierung von Datenbanken jetzt nicht ändern können, verwenden Sie COLLATE DATABASE_DEFAULT.

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

Ich hatte so etwas schon einmal und wir fanden heraus, dass die Sortierung zwischen zwei Tabellen unterschiedlich war. 

Stellen Sie sicher, dass diese gleich sind.

4
Adriaan Stander

Dank der Antwort von marc_s löste ich mein ursprüngliches Problem - es inspirierte mich, einen Schritt weiter zu gehen und einen Ansatz für die Umwandlung einer ganzen Tabelle auf einmal zu veröffentlichen - das Skript tsql zur Generierung der alter-Spalte-Anweisungen

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)

erhält: ALTER TABLE-Partner ALTER COLUMN myTable NVARCHAR (4000) COLLATE Latin1_General_CI_AS NOT NULL

Ich gebe zu, von der Notwendigkeit verwirrt zu sein, dass col.max_length/2

3
justSteve

Ich habe den Inhalt dieser site verwendet, um das folgende Skript zu erstellen, das die Sortierung aller Spalten in allen Tabellen ändert:

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

Überprüfen Sie die übereinstimmende Ebene der Sortierung (Server, Datenbank, Tabelle, Spalte, Zeichen). 

Wenn es der Server ist, haben mir diese Schritte einmal geholfen:

  1. Stoppen Sie den Server
  2. Finden Sie Ihr sqlservr.exe-Tool
  3. Führen Sie diesen Befehl aus:

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

  4. Starten Sie Ihren SQL Server:

    net start name_of_instance

  5. Überprüfen Sie die Sortierung Ihres Servers erneut.

Hier gibt es mehr Infos:

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

2

Wenn dies in der gesamten Datenbank vorkommt, sollten Sie Ihre DB-Sortierung wie folgt ändern:

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 

Referenz hier

2
Justin

Für diejenigen, die über ein CREATE DATABASE-Skript (wie in meinem Fall) für die Datenbank verfügen, die dieses Problem verursacht, können Sie das folgende CREATE-Skript verwenden, um die Kollatierung abzugleichen:

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

oder

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

Damit wird die gewünschte Kollatierung auf alle Tabellen angewendet, was genau das war, was ich brauchte. Es ist ideal, wenn Sie versuchen, die Sortierung für alle Datenbanken auf einem Server gleich zu halten. Hoffen Sie, dass dies hilft.

Weitere Informationen finden Sie unter folgendem Link: SQL SERVER - Erstellen einer Datenbank mit unterschiedlicher Sortierung auf dem Server

2
pechar

Der @ JustSteve-Antwort wurde Code hinzugefügt, um sich mit den Spalten varchar und varchar (MAX) zu befassen:

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

Sie können dies leicht mit 4 einfachen Schritten tun

  1. sichern Sie Ihre Datenbank
  2. datenbankkollatierung ändern: Klicken Sie mit der rechten Maustaste auf die Datenbank, wählen Sie Eigenschaften aus, gehen Sie zu den Optionen und ändern Sie die Kollatierung in die erforderliche Kollatierung.
  3. Generieren Sie ein Skript, um alle Datenbankobjekte zu löschen und erneut zu erstellen: Klicken Sie mit der rechten Maustaste auf Ihre Datenbank, wählen Sie Aufgaben aus, wählen Sie Skript generieren aus.
  4. Führen Sie das oben generierte Skript aus
1

dies ist, was wir getan haben. In unserer Situation benötigen wir eine Ad-hoc-Abfrage, die mit einer Terminbeschränkung bei Bedarf ausgeführt wird. Die Abfrage ist in einer Tabelle definiert.

Unsere neue Abfrage muss Daten zwischen verschiedenen Datenbanken abgleichen und Daten aus beiden Datenbanken enthalten.

Es scheint, dass sich die COLLATION zwischen der Datenbank, die Daten aus dem iSeries/AS400-System importiert, und unserer Berichtsdatenbank unterscheidet. Dies könnte auf die spezifischen Datentypen (z. B. griechische Akzente auf Namen usw.) zurückzuführen sein.

Also haben wir die Join-Klausel verwendet:

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

Um dieses Problem in der Abfrage zu beheben, ohne eine der Datenbanken zu ändern, können Sie die Ausdrücke auf der anderen Seite des "=" - Zeichens mit umsetzen

COLLATE SQL_Latin1_General_CP1_CI_AS

wie vorgeschlagen hier .

1
Lars Ericson

Ich hatte einen ähnlichen Fehler (Kann den Kollatierungskonflikt zwischen "SQL_Latin1_General_CP1_CI_AS" und "SQL_Latin1_General_CP1250_CI_AS" in der INTERSECT-Operation nicht lösen), als ich den alten Jdbc-Treiber verwendete.

Ich habe dieses Problem gelöst, indem ich einen neuen Treiber von Microsoft oder einem Open-Source-Projekt jTDS heruntergeladen habe.

1
krzy-wa

ALTER DATABASE test2 - Geben Sie hier Ihren Datenbanknamen ein COLLATE Latin1_General_CS_AS - Ersetzen Sie es mit der gewünschten Sortierung

1
jig's
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 )
1
Arati

In Ihrer Datenbank gibt es möglicherweise keine Kollatierungsprobleme. Wenn Sie jedoch eine Kopie Ihrer Datenbank von einer Sicherung auf einem Server mit einer anderen Kollatierung als Origin wiederherstellen und der Code temporäre Tabellen erstellt, erben die temporären Tabellen die Kollatierung der Server und es würde Konflikte mit Ihrer Datenbank geben.

0
ajeh