システム運用において、データベースの文字化けは思いがけない混乱の一つです。
特にSQL Serverを利用する際、慣れていないとデータの先頭にNを付けても「データが?に文字化けする」現象に直面することがあります。
SQL Serverに日本語のデータを入れるには、本来NVARCHARかNCHAR型を使う必要があり、この2つの型ではないカラムに日本語のデータを入れようとしていることが理由です。
文字型データとエンコーディング
データベースは、文字情報を保存するためにさまざまなデータ型が用意されています。
SQL Serverにおいて、標準的な文字列型にはCHAR型、VARCHAR型、そしてNCHAR型、NVARCHAR型があります。
- CHAR型、VARCHAR型は、非Unicode文字列を扱います。
- NCHAR型、NVARCHAR型は、Unicode文字列を扱います。
重要なのが、Unicodeは世界中の文字を統一して表現できる文字コード体系であり、日本語、中国語、ハングルなどの多言語を正確に扱うためには不可欠な仕組みです。
なぜ「?」に文字化けするのか
CHAR型やVARCHAR型を使用している場合、SQL Serverはデフォルトのコードページ(例えば、英語圏ならLatin1)に基づいて文字を保存します。
これらの型は、多バイト文字(日本語など)に対応していないため、登録できない文字があると、それを代替として「?」に置き換える仕様になっています。
これは、そもそも格納できない文字を無理に保存しようとする際の、システム側の仕様です。
一方、NCHAR型やNVARCHAR型は、Unicodeをベースにしているため、日本語をはじめとする幅広い文字体系を正確に保存することができます。
つまり、多言語対応が必要な場面では、常にNCHARまたはNVARCHARを使用することが推奨されます。
実例|違いの確認
たとえば、次のような例を考えてみましょう。
-- VARCHARに日本語を格納しようとする CREATE TABLE [TestTable] ( [TextValue] VARCHAR(100) ); INSERT INTO [TestTable] ([TextValue]) VALUES ('こんにちは'); SELECT * FROM [TestTable];
この場合、結果セットには「?????」と表示されるか、「?」だけが見えるかもしれません。一方、以下のようにNVARCHARを使用すると、
-- NVARCHARに日本語を格納する CREATE TABLE [TestTable] ( [TextValue] NVARCHAR(100) ); INSERT INTO [TestTable] ([TextValue]) VALUES (N'こんにちは'); SELECT * FROM [TestTable];
正しく「こんにちは」と表示されます。
ここでのポイントは、文字列リテラルの前に「N」を付与することも忘れてはいけない点です。
これにより、SQL Serverに「これはUnicode文字列ですよ」と明示的に伝えることができます。
非Unicodeカラムに日本語を入れる
望ましくはありませんが、誤った設計で本番運用が開始された場合、非Unicodeカラムにデータを入れる必要が出てくるかも知れません。
この場合、カラムの照合順序を「Japanese_XJIS_140_CS_AS_KS(Shift-JISで表現可能な文字)」に変更します。
-- カラム単位で照合順序を見る SELECT COLUMN_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TestTable'; -- またはDB全体のデフォルト照合順序 SELECT DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS Collation; -- 対象カラムの照合順序の変更を行う ALTER TABLE [TestTable] ALTER COLUMN [TextValue] VARCHAR(100) COLLATE Japanese_XJIS_140_CS_AS_KS;
上記の例だとvarcharに日本語を入れても表在されますが、Shift-JIS範囲内のみなので最終的にはnvarcharに変更した方がいいです。
まとめ
SQL Serverにおいてデータが「?」に文字化けしてしまう最大の原因は、文字列型がNVARCHARやNCHARではないことにあります。
非Unicode型では表現できない文字を保存しようとすると、仕様上自動的に「?」に置き換わります。
日本語を含むマルチバイト文字を正しく取り扱うためには、データ型の選択が極めて重要です。
設計段階から意識的にNCHARやNVARCHARを採用することが、トラブル防止の第一歩といえるでしょう。