Unicode 文字列の格納をテストする際に [森?る] を使うことがよくあるかと思います。
この文言を使って SQL Server のデータ格納を見てみようかと。
森?外るを構成する文字は以下のようになっています。
SELECT NCHAR(0x68ee),NCHAR(0x9dd7),NCHAR(0x5916),NCHAR(0xd842) + NCHAR(0xdf9f),NCHAR(0x308b) SELECT UNICODE(N'森'),UNICODE(N'?'),UNICODE(N'外'),UNICODE(N''),UNICODE(N'る')
これが DB 上、どのように格納されるかが今回の投稿の内容です。
まずは以下のようなクエリでテスト用のデータを登録します。
IF (object_id('えろす師匠') IS NOT NULL) DROP TABLE えろす師匠 GO CREATE TABLE えろす師匠(col1 nvarchar(40)) GO INSERT INTO えろす師匠 VALUES ('森?外る'),(N'森?外る') SELECT * FROM えろす師匠 CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)
実行すると、以下のような結果が取得できます。
N プレフィックスで Unicode Native 形式として修飾しなかった場合は、CP932 で文字が取り扱われるかと思いますので、表現できない文字については [?] (0x003F / 63) で表現されます。
それでは実際に格納されているデータを見てみたいと思います。
上記の結果からデータは ファイル ID : 1 / ページ ID : 197 に格納されていることが確認できますので、以下のクエリを実行して実際のデータを取得します。
DECLARE @DBNAME sysname = DB_NAME() DBCC TRACEON(3604) DBCC PAGE(@DBNAME,1,197,3)
取得した情報で該当する箇所は以下のような内容となります。
Slot 0 Offset 0x60 Length 23 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS 0000000000000000: 30000400 01000001 001700ee 683f0016 593f003f 0………..h?..Y?.? Slot 0 Column 1 Offset 0xb Length 12 Length (physical) 12 col1 = 森?外??る Slot 1 Offset 0x77 Length 23 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS 0000000000000000: 30000400 01000001 001700ee 68d79d16 5942d89f 0………..h×..YBO. Slot 1 Column 1 Offset 0xb Length 12 Length (physical) 12 col1 = 森?外る |
各データを分解してみてみたいと思います。
[森] は [0x68EE] になりますので、以下の個所が該当することがわかります。
0000000000000000: 30000400 01000001 001700ee 683f0016 593f003f 0………..h?..Y?.? 0000000000000000: 30000400 01000001 001700ee 68d79d16 5942d89f 0………..h×..YBO. |
次の [?] ですが、Native 形式で指定をしなかった場合は [?] で表示がされていました。
[?] は [0x003F] になりますので以下の個所が該当していることになりま す。
Native 形式の場合は [0x9DD7] が格納されていますね。
0000000000000000: 30000400 01000001 001700ee 683f0016 593f003f 0………..h?..Y?.? 0000000000000000: 30000400 01000001 001700ee 68d79d16 5942d89f 0………..h×..YBO. |
データ型で対応していない文字コードの文字を格納しようとした場合は、? となりますが、これは表示ができないということではなく、実際に [?] という文字が登録されていることが確認できます。
[外] については [0x5916] になりますが、これはどちらも正常に登録されている文字ですね。
0000000000000000: 30000400 01000001 001700ee 683f0016 593f003f 0………..h?..Y?.? 0000000000000000: 30000400 01000001 001700ee 68d79d16 5942d89f 0………..h×..YBO. |
[] についてはサロゲートペアの文字となり、[0xD842] と [0xDF9F] で構成されています。
Native 形式で指定しなかった場合はサロゲートペアの 2 バイト文字× 2 で [?] (0x003F) が 2 個登録されているのが確認できますね。
0000000000000000: 30000400 01000001 001700ee 683f0016 593f003f 0………..h?..Y?.? 0000000000000000: 30000400 01000001 001700ee 68d79d16 5942d89f 0………..h×..YBO. |
最後の [る] については [0x308B] となっていますね。
0000000000000000: 30000400 01000001 001700ee 683f0016 593f003f 0………..h?..Y?.? 0000000000000000: 30000400 01000001 001700ee 68d79d16 5942d89f 0………..h×..YBO. |
実際に格納されているデータについて、書いたことがなかったなと思いメモとして。