it-swarm.com.de

Verwenden von COLLATE mit UNION

Wie verwende ich COLLATE mit UNION? Ich möchte 2 Tabellen zusammenfassen (beide haben die gleichen Spalten und die gleichen Typen: varchar,int, int, decimal).

Ich habe folgenden Fehler erhalten:

sg 468, Ebene 16, Status 9, Zeile 1 Der Kollatierungskonflikt zwischen "Serbian_Latin_100_CI_AS" und "Croatian_CI_AS" in der UNION-Operation kann nicht gelöst werden.

Meine SQL-Anweisung:

select * from #IA_BIH
union 
select * from #IA_MNE  

Wo soll ich einfügen collate database_default? Ich habe verschiedene Kombinationen ausprobiert, aber es hat nicht funktioniert.

6
Anja

Aufgrund der Sortierungsnamen gehe ich davon aus, dass Sie Microsoft SQL Server verwenden.

COLLATE kann auf Datenbankebene oder auf Spaltenebene verwendet werden. Da Sie versuchen, zwei Tabellen mit UNION zu versehen, wird Ihre Abfrage durch Verwendung der Spaltenkollatierung für die erforderlichen Spalten aufgelöst.

Hier ist ein Beispielcode, der Ihnen helfen soll:

use testdb
GO
CREATE TABLE dbo.Serbian  (Name VARCHAR(20) COLLATE Serbian_Latin_100_CI_AS);
CREATE TABLE dbo.Croatian (Name VARCHAR(20) COLLATE  Croatian_CI_AS);
GO
INSERT INTO dbo.Serbian VALUES ('serbian');
INSERT INTO dbo.Croatian VALUES ('croation');
GO

-- Collate to a particular named collation
SELECT Name COLLATE Serbian_Latin_100_CI_AS as CollatedNameSerbian from dbo.Serbian 
UNION ALL
SELECT Name COLLATE Serbian_Latin_100_CI_AS from dbo.Croatian 
GO
-- Collate to the database default collation
SELECT Name  COLLATE database_default as CollatedNameDBDefault from dbo.Serbian 
UNION ALL
SELECT Name COLLATE database_default from dbo.Croatian 
GO

DROP TABLE dbo.Serbian;
DROP TABLE dbo.Croatian;
GO

Wenn Sie mehrere Spalten mit widersprüchlichen Kollatierungen haben, müssen Sie natürlich auch deren Kollatierungen definieren.

5
RLF

Kollatierungen können etwas schwierig sein, insbesondere für VARCHAR Daten. Sowohl für NVARCHAR als auch für VARCHAR Daten steuern Sortierungen die Sortier- und Vergleichsregeln. Für VARCHAR -Daten steuern Kollatierungen auch den Zeichensatz (d. H. Welche Codepage wird verwendet, um zu bestimmen, welches Zeichen jeder 8-Bit-Wert darstellt). Das Ändern von Kollatierungen für VARCHAR -Daten can führt also zu Datenverlust:

SELECT CHAR(230) AS [DB-Collation],
       CHAR(230) COLLATE Korean_100_CI_AS AS [Korean],
       CHAR(230) COLLATE Albanian_CI_AS AS [Albanian],
       CHAR(230) COLLATE Greek_100_CI_AS AS [Greek];
-- æ            a   ?

Da Sie jedoch eine Kollatierungsfehlanpassung haben, müssen Sie eine davon ändern. Ich würde in diesem speziellen Fall davon abraten, database_default Zu verwenden, da dies relativ zur Datenbank ist, aus der die Abfrage ausgeführt wird, was zu inkonsistentem Verhalten führen kann.

Glücklicherweise haben beide im Fehler erwähnten Kollatierungen dieselbe Codepage: 1250. Sie können diese Informationen mithilfe der folgenden Abfrage herausfinden:

SELECT col.[name], COLLATIONPROPERTY(col.[name], 'CodePage') AS [CodePage]
FROM   sys.fn_helpcollations() col
WHERE  [name] IN (N'Serbian_Latin_100_CI_AS', N'Croatian_CI_AS');

Zu diesem Zeitpunkt müssen Sie eine dieser beiden auswählen, um zu erzwingen, dass die andere identisch ist. Da beide Sortierungen dieselbe Codepage verwenden, wirkt sich die Auswahl nicht auf den verwendeten Zeichensatz aus. Der einzige Unterschied, über den Sie sich Sorgen machen müssen, sind die Regeln für das Sortieren und Vergleichen zwischen Serbisch und Kroatisch. Wählen Sie diejenige aus, die den Erwartungen der Endbenutzer am ehesten entspricht.

Eine Möglichkeit besteht darin, die Kollatierung in der Anweisung SELECT so zu erzwingen, wie es scheint, wie Sie es versuchen, und wie in der Antwort von @ RLF gezeigt. Der Nachteil hierbei ist, dass Sie SELECT * Nicht mehr verwenden können (wenn dies Code in einer gespeicherten Prozedur ist, ist es wahrscheinlich am besten, SELECT * Ohnehin nicht zu verwenden).

Eine andere Möglichkeit besteht darin, die Sortierung für eine dieser Tabellen zu erzwingen, wenn Sie die temporäre Tabelle erstellen, unabhängig davon, ob dies mit CREATE TABLE Oder SELECT INTO Durchgeführt wird:

SELECT ac.*
FROM   sys.all_columns ac
WHERE  ac.[object_id] = OBJECT_ID(N'sys.objects')
AND    ac.[name] = N'name';
-- SQL_Latin1_General_CP1_CI_AS (on my system, at least)

SELECT [name] COLLATE Hebrew_100_CI_AS AS [name]
INTO   #coltest
FROM   sys.objects;

SELECT sc.*
FROM   [tempdb].sys.columns sc
WHERE  sc.[object_id] = OBJECT_ID(N'tempdb..#coltest');
-- Hebrew_100_CI_AS

Die Vorteile hier sind, dass Sie dann:

  1. verwenden Sie SELECT * in Ihrer UNION-Abfrage.
  2. führen Sie mehrere Abfragen für diese Tabellen aus, ohne dass Sie jeder eine COLLATE -Option hinzufügen müssen.

Unter der Annahme, dass die Standardkollatierung für die Datenbank, in der CREATE TABLE Oder SELECT INTO Ausgeführt wird, eine der beiden in der Fehlermeldung angegebenen Kollatierungen ist, können Sie fortfahren und verwenden COLLATE database_default.

2
Solomon Rutzky