giip
SES案件登録
SQL Server参照のみ文字セット障害対応

NVARCHARリテラルのNプレフィックス漏れで日本語・絵文字がエラーなく文字化けする

公開日 2026-08-16 · 更新日 2026-08-16 · 最終検証日 2026-08-16

結論

SQL ServerでNVARCHAR列に文字列リテラルを直接代入する際、`N` プレフィックスを付け忘れると、リテラルは接続の既定コードページへ暗黙的に変換されてからNVARCHAR型に格納されます。日本語・韓国語・絵文字などそのコードページで表現できない文字は失われますが、これはエラーにも警告にもならず、値が黙って壊れるだけです。ASCIIのみのテストデータでは気づけず、本番投入後に発覚することが多く、同じパターンが繰り返し発生しがちです。

この文書の適用条件

対象製品SQL Server(Unicode文字列リテラル全般に影響)
確認バージョンSQL Server 2012 以降(Azure SQL Database・Managed Instance を含む)
適用環境オンプレミス、EC2、Amazon RDS for SQL Server、Azure SQL
必要権限診断SQLは対象テーブルのSELECT権限のみ。ソースコード検索はリポジトリの読み取り権限
実行影響本記事の診断はすべて参照専用。既存の破損データの修正・復旧は別途対象行のUPDATEを伴う
再起動不要
最終検証日2026-08-16

そのまま実行できるコマンド

対象になり得る列を洗い出す(参照専用)参照のみ
対象
SQL Server 2012 以降 / Azure SQL Database・Managed Instance
権限
対象テーブルのSELECT権限(メタデータの参照はpublicロールで可)
変更作業
なし(参照のみ)
Production実行
可能
-- 対象: SQL Server 2012 以降 / Azure SQL Database・Managed Instance
-- 権限: メタデータの参照はpublicロールで可。個々のデータ確認には対象テーブルのSELECT権限が必要
-- 変更作業: なし(参照のみ)
-- Production実行: 可能
-- 非ASCII文字を保持しうる nvarchar / nchar 列を一覧化する(調査対象の絞り込み用)
SELECT
    t.name AS table_name,
    c.name AS column_name,
    ty.name AS type_name,
    c.max_length
FROM sys.columns AS c
INNER JOIN sys.tables AS t
        ON t.object_id = c.object_id
INNER JOIN sys.types AS ty
        ON ty.user_type_id = c.user_type_id
WHERE ty.name IN ('nvarchar', 'nchar')
ORDER BY t.name, c.column_id;

この一覧はあくまで調査範囲を絞るためのもので、列が存在すること自体は問題ではない。次の手順で個々の列のデータを確認する。

ソースコード内のNプレフィックス漏れを機械的に検出する(参照専用)参照のみ
対象
アプリケーション・ストアドプロシージャのソースコードリポジトリ
権限
リポジトリの読み取り権限
変更作業
なし(参照のみ)
Production実行
可能
# 対象: アプリケーション・ストアドプロシージャのソースコードリポジトリ
# 権限: リポジトリの読み取り権限
# 変更作業: なし(参照のみ)
# Production実行: 可能
#
# .sql ファイル内で、Nプレフィックスの無いシングルクォート文字列リテラルのうち
# 非ASCII文字を含むものを検出する(正規表現なので誤検知はあり、ヒット箇所は目視確認が前提)
grep -RnoP "(?<![Nn])'[^']*[^\x00-\x7F][^']*'" --include=*.sql .

# 文字列結合や sp_executesql で動的SQLを組み立てている箇所も洗い出す
grep -RniE "(sp_executesql|EXEC\(|exec\()" --include=*.sql --include=*.cs --include=*.ts .

コメントや意図的な非ASCII文字列(エラーメッセージ文言など)も拾うため、正規表現のヒットはすべて「調査対象」であって「確定した不具合」ではない。1件ずつNVARCHAR列・パラメータへの代入かどうかを確認する。

こういう状況で使います

  • 日本語・韓国語・絵文字を含むデータを登録すると、エラーは出ないのに保存後の値が「?」や別の文字に置き換わっている
  • アプリケーションのテスト(ASCIIのみのテストデータ)では問題が起きず、本番投入後や実データ投入後に初めて発覚する
  • 動的SQL(文字列結合やsp_executesql)を経由する書き込み経路でだけ発生する
  • 一度「直した」はずのコードベースで、別の箇所・別のプロジェクトで同じ症状が再発する

考えられる原因(可能性の高い順)

  1. 01

    文字列リテラルが接続の既定コードページへ暗黙変換される

    Nプレフィックスの無いシングルクォート文字列リテラルは、まず非Unicodeの文字列として解釈され、接続の既定コードページに変換されたうえでNVARCHAR型に代入される。そのコードページで表現できない文字は変換時に失われる。

  2. 02

    動的SQLの組み立てでNVARCHARを意識せずに文字列結合している

    文字列結合やsp_executesqlでSQL文を組み立てる際、埋め込む値の文字列リテラルにNプレフィックスを付け忘れやすい。特に値がパラメータではなく文字列として直接埋め込まれている場合に起きやすい。

  3. 03

    エラーも警告も出ないため、テストで気づきにくい

    コンパイルエラーにも実行時エラーにもならないため、ASCIIのみのテストデータでは正常に見える。実際の非ASCIIデータが入って初めて症状が現れる。

  4. 04

    一度失われた文字は、独立した参照元がなければ復旧できない

    暗黙変換で失われた文字はNVARCHAR列の中には残っていない。別システムのログや元データの控えなど、独立した参照元が別に無い限り、後から正しい値を復元することはできない。

確認手順

  1. 1

    対象テーブルのnvarchar/nchar列を洗い出す

    参照のみ

    上記の診断SQLで、非ASCII文字を保持しうる列を一覧化する。

  2. 2

    ソースコード内のNプレフィックス漏れを検索する

    参照のみ

    grepで疑わしい文字列リテラルと動的SQL構築箇所を洗い出し、1件ずつ確認する。

  3. 3

    既存データの破損兆候を確認する

    参照のみ

    本来非ASCIIのはずの列で、意図しない文字への置き換わりが無いか個別に確認する。

  4. 4

    破損データの独立した参照元があるか確認する

    参照のみ

    外部システムのログや別経路の記録など、正しい値を持つ別の情報源が残っているかを確認する。

対応方法

すぐに実施できる低リスクの対応

  • 新規コードのNVARCHARリテラルすべてにNプレフィックスを付ける

    新規追加・修正するSQLコードから着手し、既存の非ASCII文字列リテラルにNプレフィックスを付ける。

  • 動的SQL生成箇所を優先的に修正する

    文字列結合やsp_executesqlで組み立てる箇所は影響範囲が広いため優先的に修正する。可能ならパラメータ化に置き換える。

事前検討が必要な変更

  • コードレビューのチェック項目に追加する

    NVARCHAR列への文字列リテラル代入をレビュー時に確認する項目として明文化する。

  • CI・pre-commitでNプレフィックス漏れを機械的に検出する

    上記のgrepパターンをCIやpre-commitフックに組み込み、目視レビューだけに頼らない仕組みにする。

専門家のレビューが必要な作業

  • 既に破損した既存データの復旧を検討する

    専門家レビュー必須

    独立した参照元(外部ログ、別経路のバックアップ等)がある場合のみ復旧できる。無い場合は復旧できないことを関係者に明示したうえで、今後の再発防止に注力する。

!注意事項

  • Nプレフィックスを新規コードに付けても、既に破損して保存された既存データは自動的には直らない。
  • アプリケーション層でSQL文字列を組み立てている場合、文字列結合ではなくパラメータ化されたバインドを使えば、この問題自体を回避できる。可能な限りパラメータ化を優先する。
  • テストデータがASCIIのみだと本番投入まで気づけない。テストには意図的に非ASCII文字(日本語・韓国語・絵文字等)を含める。
  • 一度全面修正しても、新しいコードパスや外部から取り込んだサンプルSQLに古い書き方が紛れ込むと再発する。機械的な検出を継続する。

バージョン・環境による違い

Azure SQL Database・Managed InstanceオンプレミスのSQL Serverと同じ挙動。接続文字列や照合順序の設定に関わらず、Nプレフィックスの無いリテラルは同様に暗黙変換の対象になる。

これで解決しない場合に確認すること

  • 自分たちのコードベースで同じパターンが他にないか横断的に検索したか

    1箇所直しただけでは、同種の書き方が他のストアドプロシージャやバッチ処理に残っている可能性がある。

  • 破損が疑われる列について、独立した参照元が別に残っているか

    無い場合、復旧できないことを前提に今後の運用を設計する。

  • パラメータ化されたクエリ経由の書き込み経路は、そもそもこの問題の影響を受けない

    ORMやドライバのパラメータバインドを使っている経路は対象外であることを確認し、優先度を正しく判断する。

この文書の根拠と限界

製品の公式ドキュメントに基づく説明

Unicode文字列リテラルにNプレフィックスが必要であることはSQL Serverの公式ドキュメントに明記された仕様です。この文書で説明する「気づきにくさ」と再発しやすさは、実際の運用で複数回観測された傾向を一般化したものであり、特定顧客の事例・件数・日時は含みません。

よくある質問

Nプレフィックスを忘れると必ずエラーになりますか?

いいえ。コンパイルエラーにも実行時エラーにもなりません。接続の既定コードページで表現できない文字が黙って失われるだけで、処理自体は正常終了します。

動的SQL以外でも起きますか?

はい。文字列リテラルを直接NVARCHAR型の列・変数・パラメータに代入する経路であれば、静的なINSERT文でも同様に発生します。

パラメータ化クエリを使えば防げますか?

はい。ドライバやORMのパラメータバインドを使う経路では、値の型と文字コードがドライバ側で正しく扱われるため、この問題自体が発生しません。

破損したデータは復旧できますか?

独立した参照元(外部システムのログや別経路の記録など)が別に残っている場合のみ復旧できます。NVARCHAR列の中には元の文字が残っていないため、参照元が無ければ復旧できません。

この文書がカバーする質問

  • SQL Serverで日本語や絵文字が文字化けする原因
  • NプレフィックスなしのSQL文字列で何が起きるか

リスク表示の意味

  • 参照のみデータと設定を変更しません。
  • 影響は限定的ですが、権限と負荷の確認が必要です。
  • 性能・ロック・コストに影響する可能性があります。
  • 障害・データ損失・復旧作業が発生する可能性があります。
  • 専門家レビュー必須本番適用前に別途レビューが必須です。

GIIPの対応範囲

GIIPでは新規に追加するSQLコードに対して、Nプレフィックス漏れを機械的に検出するチェックをレビュー工程に組み込んでいます。同じパターンの事故が複数のプロジェクトで形を変えて再発した経験から、レビューでの目視確認だけに頼らず、機械的な検出を必ず併用する方針としています。

執筆・技術検証

GIIP プロダクション運用チーム

大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。

関連するナレッジ

関連サービス

NVARCHARリテラルの一斉点検を依頼する

同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。

NVARCHARリテラルの一斉点検を依頼する

ナレッジベース一覧へ