web-dev-qa-db-ja.com

SQL Server-varcharを別の照合(コードページ)に変換して文字エンコードを修正

SQL_Latin1_General_CP850_BIN2照合順序を使用するSQL Serverデータベースを照会しています。テーブル行の1つには、+ /-文字(Windows-1252コードページの10進コード177)を含む値を持つvarcharがあります。

SQL Server Management Studioでテーブルを直接クエリすると、この行の+/-文字の代わりに意味不明な文字が表示されます。このテーブルをSSISパッケージのソースとして使用すると、宛先テーブル(通常のSQL_Latin1_General_CP1_CI_AS照合を使用)が正しい+/-文字になります。

ここで、SSISを使用せずにソーステーブルを直接クエリするメカニズムを構築する必要があります。意味のない文字ではなく正しい文字を取得する方法でこれを行うにはどうすればよいですか?私の推測では、列をSQL_Latin1_General_CP1_CI_AS照合順序に変換/キャストする必要がありますが、意味不明な文字を取得し続けるため、それは機能しません。

私は運のない次を試しました:

select 
columnName collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
cast (columnName as varchar(100)) collate SQL_Latin1_General_CP1_CI_AS
from tableName

select 
convert (varchar, columnName) collate SQL_Latin1_General_CP1_CI_AS
from tableName

私は何を間違えていますか?

20
lunadesign

文字セットの変換は、データベース接続レベルで暗黙的に行われます。パラメータ「Auto Translate = False」を使用して、ODBCまたはADODB接続文字列で自動変換を強制的にオフにできます。これは推奨されません。参照: https://msdn.Microsoft .com/en-us/library/ms130822.aspx

データベースとクライアントのコードページが一致しない場合、SQL Server 2005にコードページの非互換性があります。 https://support.Microsoft.com/kb/KbView/9048

SQL-Management Console 2008以降は、UNICODEアプリケーションです。入力または要求されたすべての値は、アプリケーションレベルでそのように解釈されます。列照合との会話は暗黙的に行われます。これは次の方法で確認できます。

SELECT CAST(N'±' as varbinary(10)) AS Result

これにより、Unicode文字U + 00B1(管理コンソールウィンドウで入力)である0xB100が返されます。 Management Studioの「自動翻訳」をオフにできません

選択で別の照合を指定すると、「自動変換」がまだアクティブである限り、最終的に二重変換になります(データが失われる可能性があります)。元の文字は、選択時に最初に新しい照合順序に変換され、次に、「適切な」アプリケーションコードページに「自動変換」されます。そのため、さまざまなCOLLATIONテストですべて同じ結果が表示されます。

結果をVARBINARYの代わりにVARCHARとしてキャストすると、照合が指定されると効果があり、SQL Server変換が提示される前にクライアントによって無効にされないことを確認できます。 :

SELECT cast(columnName COLLATE SQL_Latin1_General_CP850_BIN2 as varbinary(10)) from tableName
SELECT cast(columnName COLLATE SQL_Latin1_General_CP1_CI_AS as varbinary(10)) from tableName

これにより、columnNameに文字「±」のみが含まれる場合、それぞれ0xF1または0xB1が取得されます。

使用しているフォントが適切なグリフを提供していない場合、正しい結果が得られても、間違った文字が表示される可能性があります。

適切なサンプルでクエリをVARBINARYにキャストして、キャラクターの実際の内部表現を再確認し、このコードが実際に定義されたデータベース照合SQL_Latin1_General_CP850_BIN2に対応するかどうかを確認してください

SELECT CAST(columnName as varbinary(10)) from tableName

アプリケーションの照合とデータベースの照合の違いは、変換が常に同じ方法で行われる限り、気付かない場合があります。別の照合を持つクライアントを追加するとすぐに問題が発生します。次に、内部変換が文字と正しく一致しないことがあります。

ただし、結果セットを解釈するとき、Management Studioは通常最終的な参照ではないことに注意してください。 MSで意味がわからなくても、正しい出力である可能性があります。問題は、アプリケーションでレコードが正しく表示されるかどうかです。

13
Robert Orso

キャストではなく変換に使用する必要があります:

SELECT
 CONVERT(varchar(50), N'æøåáäĺćçčéđńőöřůýţžš')
 COLLATE Cyrillic_General_CI_AI

http://blog.sqlpositive.com/2010/03/using-convert-with-collat​​e-to-strip-accents-from-unicode-strings/

5
castleless

さらに情報が必要な場合があります。これが、SQL Server 2008で再現するために行ったことです。

CREATE DATABASE [Test] ON  PRIMARY 
    ( 
    NAME = N'Test'
    , FILENAME = N'...Test.mdf' 
    , SIZE = 3072KB 
    , FILEGROWTH = 1024KB 
    )
    LOG ON 
    ( 
    NAME = N'Test_log'
    , FILENAME = N'...Test_log.ldf' 
    , SIZE = 1024KB 
    , FILEGROWTH = 10%
    )
    COLLATE SQL_Latin1_General_CP850_BIN2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[MyTable]
    (
    [SomeCol] [varchar](50) NULL
    ) ON [PRIMARY]
GO
Insert MyTable( SomeCol )
Select '±' Collate SQL_Latin1_General_CP1_CI_AS
GO
Select SomeCol, SomeCol Collate SQL_Latin1_General_CP1_CI_AS
From MyTable

結果には元のキャラクターが表示されます。クエリで照合を宣言すると、SQL Serverの観点から適切な文字が返されますが、プレゼンテーションレイヤーがUTF-8などのさらに異なるものに変換される場合があります。

1
Thomas

試してください:

SELECT CAST( CAST([field] AS VARBINARY) AS varchar) 
1
user1403869