將 COLLATE 與 UNION 一起使用
怎麼
COLLATE
用UNION
?我想合併 2 個表(都有相同的列和相同的類型:)varchar,int, int, decimal
。我收到以下錯誤:
sg 468, Level 16, State 9, Line 1 無法解決 UNION 操作中“Serbian_Latin_100_CI_AS”和“Croatian_CI_AS”之間的排序規則衝突。
我的 SQL 語句:
select * from #IA_BIH union select * from #IA_MNE
我應該在哪裡插入
collate database_default
?我嘗試了不同的組合,但沒有奏效。
根據排序規則名稱,我假設您使用的是 Microsoft SQL Server。
COLLATE 可以在數據庫級別或列級別使用。由於您正在嘗試 UNION 兩個表,因此在所需列上使用列排序規則將解決您的查詢。
這是一個範常式式碼,可以幫助您:
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
當然,如果您有多個列的排序規則衝突,您還需要定義它們的排序規則。
排序規則可能有點棘手,尤其是對於
VARCHAR
數據。對於NVARCHAR
和VARCHAR
數據,排序規則控制排序和比較規則。但是對於VARCHAR
數據,排序規則還控製字元集(即使用哪個程式碼頁來確定每個 8 位值代表什麼字元)。VARCHAR
因此,更改數據的排序規則可能會導致數據失去: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 ?
但是,由於您的排序規則不匹配,因此您需要更改其中之一。我建議不要
database_default
在這種特殊情況下使用,因為這將與正在執行查詢的數據庫相關,這可能會導致行為不一致。幸運的是,錯誤中提到的兩個排序規則具有相同的程式碼頁:1250。您可以使用以下查詢找到此資訊:
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');
此時,您需要從這兩個中選擇一個來強制另一個相同。因為兩個排序規則使用相同的程式碼頁,所以選擇不會影響正在使用的字元集。您需要關注的唯一區別是塞爾維亞語和克羅地亞語之間的排序和比較規則;選擇最符合最終使用者期望的那個。
一種選擇是在
SELECT
聲明中強制執行排序規則,因為您正在嘗試執行此操作,如@RLF 的回答所示。這裡的缺點是您不能再使用SELECT *
(如果這是儲存過程中的程式碼,最好還是不要使用SELECT *
)。另一種選擇是在創建臨時表時強制其中一個表的排序規則,無論是使用
CREATE TABLE
或完成SELECT INTO
: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
這樣做的好處是您可以:
SELECT *
在您的UNION
查詢中使用。- 對這些表執行多個查詢,而無需
COLLATE
為每個表添加選項。並且,假設正在執行
CREATE TABLE
or的數據庫的預設排序規則SELECT INTO
是錯誤消息中指出的兩個排序規則之一,那麼您可以繼續使用COLLATE database_default
.