プログラムの単体テスト用DB(SQL Server)として、LinuxコンテナのSQL Serverを使ってみてるのですが、テストデータを何にしようかな、とSQL Server Management StudioからポチポチInsertしてたところ、文字化け。
もう夜遅いので今度調べよう。と、寝ました。
で、今日。調査開始。
まずはSQLserver2022 On LinuxのDockerコンテナをPowershellで起動
DB作って、テーブル作って、日本語のデータをInsert。
テーブル構成も日本語のデータが登録できればいいので適当。
CREATE DATABASE testdb;
use testdb;
CREATE TABLE test (
id INT PRIMARY KEY,
message VARCHAR(255)
);
INSERT INTO test (id, message) VALUES (1, 'おはよう');
INSERT INTO test (id, message) VALUES (2, 'Good Morning');
select * from test;
とりあえず、再現OK。"おはよう"は文字化けして????になってる
で、SQLServerを使っていてそんな感じになった記憶が無いので、日本語バージョンでインストールしていたからかな?と思い、WindowsServer上にSQL Server2022をインストールしてみて同じようにやってみた。
そしたらやっぱり文字化けしていない。
じゃあ、英語バージョンで同じようにやったら文字化けするんだろうなぁ、と思いWindowsServer上に英語バージョンのSQL Server2022をインストールし同じように実行したところ、文字化けしていない。なんで?
調べたところ、2012年のSQL Server Japan Support Team Blogに「非 Unicode から Unicode への変換ができなかったから」、「データベースの照合順序がLatin1_General_CI_ASの場合」にデータが?になるとのこと。
確かにコンテナのSQL Serverインスタンスは照合順序が"SQL_Latin1_General_CP1_CI_AS"
なので、試しにCREATE DATABASEステートメントでデータを入れるDBの照合順序をJapanese_CI_ASに指定してみる。
CREATE DATABASE [testdb]
COLLATE Japanese_CI_AS;
USE testdb;
DROP TABLE IF EXISTS test;
CREATE TABLE test (
id INT PRIMARY KEY,
message NVARCHAR(255)
);
INSERT INTO test (id, message) VALUES (1, N'おはよう');
INSERT INTO test (id, message) VALUES (2, N'Good Morning');
select * from test;
すると文字化けしなくなった
もう一個試し。いま稼働しているコンテナを削除し、
docker runでカスタム SQL Server照合順序を指定(-e "MSSQL_COLLATION=Japanese_CI_AS")を追加
"Japanese_CI_AS"になっていることを確認
それからこのままCreate Database、Create Table、データInsert。
文字化けしてないことを確認
で、もうひとつ実験。
いま稼働しているコンテナを削除し、もう一回、カスタム SQL Server照合順序を指定せずにDocker run
Create Databaseでも照合順序を指定せず、テーブルのカラムmessageの型を"VARCHAR"ではなく、"NVARCHAR"に指定。日本語をInsertの際、Unicode文字列として処理されるようNプレフィックスを付ける
CREATE DATABASE testdb;
use testdb;
CREATE TABLE test (
id INT PRIMARY KEY,
message NVARCHAR(255)
);
INSERT INTO test (id, message) VALUES (1, N'おはよう');
INSERT INTO test (id, message) VALUES (2, 'Good Morning');
select * from test;
これも文字化けしない。
じゃあ、今後どれで行こうかというとDocker runの時のカスタム SQL Server照合順序指定でいいかな