giip
SES Proposal
SQL ServerRead-only文字セット障害対応

Missing N prefix on NVARCHAR literals silently mangles Japanese/Korean text and emoji without any error

Published 2026-08-16 · Updated 2026-08-16 · Last Verified 2026-08-16

Answer

When a string literal is assigned directly to an NVARCHAR column in SQL Server without the `N` prefix, the literal is implicitly converted to the connection's default code page before being stored as NVARCHAR. Characters that cannot be represented in that code page — Japanese, Korean, emoji, and the like — are lost, but this raises no error or warning; the value simply corrupts silently. ASCII-only test data never reveals the problem, so it is often discovered only after going to production, and the same pattern tends to recur.

Applicability of This Document

ProductSQL Server (affects Unicode string literals in general)
Verified VersionsSQL Server 2012 and later (including Azure SQL Database / Managed Instance)
EnvironmentOn-premises, EC2, Amazon RDS for SQL Server, Azure SQL
Required PermissionsDiagnostic SQL only needs SELECT on the target table. Source-code search needs read access to the repository
Execution ImpactAll diagnostics in this article are read-only. Fixing/recovering already-corrupted data separately requires an UPDATE on the affected rows
RestartNot required
Last Verified2026-08-16

Ready-to-Run Commands

Find columns that could be affected (read-only)Read-only
対象
SQL Server 2012 and later / Azure SQL Database, Managed Instance
権限
SELECT on the target table (metadata can be viewed with the public role)
変更作業
None (read-only)
Production実行
Safe
-- 対象: 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;

This list only narrows the scope of investigation — the mere existence of such a column is not itself a problem. The next step checks the actual data in each column.

Mechanically detect missing N prefixes in source code (read-only)Read-only
対象
The application / stored-procedure source-code repository
権限
Read access to the repository
変更作業
None (search only)
Production実行
Safe
# 対象: アプリケーション・ストアドプロシージャのソースコードリポジトリ
# 権限: リポジトリの読み取り権限
# 変更作業: なし(参照のみ)
# 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 .

This also catches comments and intentional non-ASCII strings (such as error-message text), so every regex hit is a "candidate to investigate," not a "confirmed bug." Check each hit individually to see whether it is an assignment into an NVARCHAR column or parameter.

When to Use This

  • Inserting data containing Japanese, Korean, or emoji raises no error, but the stored value shows "?" or different characters
  • Application tests (which use ASCII-only test data) show no problem; the issue surfaces only after going to production or loading real data
  • It only happens on write paths that go through dynamic SQL (string concatenation or sp_executesql)
  • The same symptom recurs in a different place or a different project, even in a codebase that was supposedly already "fixed"

Possible Causes (Most Likely First)

  1. 01

    The string literal is implicitly converted to the connection's default code page

    A single-quoted string literal without the N prefix is first interpreted as a non-Unicode string, then converted to the connection's default code page before being assigned to the NVARCHAR type. Characters that cannot be represented in that code page are lost during the conversion.

  2. 02

    Dynamic SQL is assembled by string concatenation without thinking about NVARCHAR

    When building SQL statements via string concatenation or sp_executesql, it is easy to forget the N prefix on the literal being embedded — especially when the value is embedded directly as a string rather than passed as a parameter.

  3. 03

    No error or warning is raised, so tests rarely catch it

    Because neither a compile-time nor a runtime error occurs, ASCII-only test data looks perfectly fine. The symptom appears only once real non-ASCII data is written.

  4. 04

    Once a character is lost, it cannot be recovered without an independent source

    A character lost to implicit conversion no longer exists anywhere inside the NVARCHAR column. Unless there is some independent source — logs in another system, a copy of the original data — the correct value can never be restored afterward.

Diagnostic Steps

  1. 1

    Enumerate the nvarchar/nchar columns on the target table

    Read-only

    Use the diagnostic SQL above to list columns that could hold non-ASCII characters.

  2. 2

    Search the source code for missing N prefixes

    Read-only

    Use grep to find suspicious string literals and places that build dynamic SQL, then check each one individually.

  3. 3

    Check existing data for signs of corruption

    Read-only

    For columns that should hold non-ASCII text, individually check whether values have been replaced by unintended characters.

  4. 4

    Check whether an independent source exists for the corrupted data

    Read-only

    Check whether some other source of truth — an external system's logs, a record from a different path — still holds the correct values.

Solutions

Low-risk action that can be done immediately

  • Add the N prefix to every NVARCHAR literal in new code

    Low

    Start with newly added or modified SQL code, and add the N prefix to existing non-ASCII string literals as well.

  • Fix the places that build dynamic SQL first

    Low

    Parts that assemble SQL via string concatenation or sp_executesql have the widest blast radius, so fix them first. Switch to parameterization where possible.

Change requiring advance review

  • Add it as a code-review checklist item

    Low

    Document, as an explicit review item, that string literals assigned to NVARCHAR columns must be checked.

  • Mechanically detect missing N prefixes in CI / pre-commit

    Medium

    Wire the grep pattern above into CI or a pre-commit hook, so detection does not depend solely on manual review.

Work requiring expert review

  • Consider recovering already-corrupted existing data

    Expert Review Required

    Recovery is only possible if an independent source exists (external logs, a backup taken through a different path, etc.). If none exists, state clearly to stakeholders that recovery is impossible, and focus effort on preventing recurrence going forward.

!Warnings

  • Adding the N prefix to new code does not automatically fix existing data that was already corrupted and stored.
  • If the application layer builds SQL strings itself, using parameterized binding instead of string concatenation avoids this problem entirely. Prefer parameterization wherever possible.
  • If test data is ASCII-only, the issue will not surface until production. Deliberately include non-ASCII characters (Japanese, Korean, emoji, etc.) in tests.
  • Even after a full sweep fix, the old pattern can creep back in through a new code path or a sample SQL snippet pulled in from elsewhere. Keep the automated detection running continuously.

Differences by Version and Environment

Azure SQL Database / Managed InstanceBehaves the same as on-premises SQL Server. Regardless of connection-string or collation settings, a literal without the N prefix is equally subject to implicit conversion.

If This Doesn't Resolve It

  • Did you search across the whole codebase for the same pattern, not just one spot?

    Fixing a single location does not rule out the same pattern existing in other stored procedures or batch jobs.

  • For columns suspected of corruption, does an independent source still exist?

    If not, design future operations on the assumption that recovery is impossible.

  • Write paths that use parameterized queries are not affected by this issue in the first place

    Confirm that paths using ORM or driver parameter binding are out of scope, so you prioritize correctly.

Basis and Limitations of This Document

Explanation based on official product documentation

That Unicode string literals require the N prefix is a specification explicitly documented by Microsoft for SQL Server. The "easy to miss" nature and tendency to recur described in this article are a generalization of patterns observed repeatedly across real operations, and do not include any specific customer's incident counts or dates.

FAQ

Does forgetting the N prefix always cause an error?

No. It causes neither a compile-time nor a runtime error. Characters that cannot be represented in the connection's default code page are silently lost, while the operation itself completes normally.

Does this also happen outside of dynamic SQL?

Yes. Any path that assigns a string literal directly into an NVARCHAR column, variable, or parameter is affected the same way, even in a plain static INSERT statement.

Does using parameterized queries prevent this?

Yes. Paths that use a driver or ORM's parameter binding have the value's type and character encoding handled correctly on the driver side, so this problem cannot occur at all.

Can corrupted data be recovered?

Only if an independent source still exists — such as logs from an external system or records captured through a different path. The original character no longer exists inside the NVARCHAR column itself, so without such a source it cannot be recovered.

Questions This Document Covers

  • Why does Japanese or Korean text get mangled in SQL Server
  • What happens with a SQL string that has no N prefix

What the Risk Labels Mean

  • Read-onlyDoes not change data or settings.
  • LowImpact is limited, but permissions and load should be checked.
  • MediumMay affect performance, locking, or cost.
  • HighMay cause an outage, data loss, or require recovery work.
  • Expert Review RequiredRequires a separate review before applying to production.

GIIP's Scope of Support

GIIP has built a review-stage check that mechanically detects missing N prefixes for any newly added SQL code. Because the same class of incident has recurred, in different forms, across multiple projects, our policy is to never rely solely on manual review and to always pair it with automated detection.

Author & Technical Review

GIIP Production Operations Team

About 30 years of experience in designing, migrating, and operating large-scale web services, SQL Server, Oracle, AWS, and Azure. Experience includes 12 sets of x12large-class AWS RDS for SQL Server environments, an Oracle environment with roughly 120,000 tables, and migrating roughly 3TB from TiDB to Aurora MySQL. AI agents and human experts currently continue to monitor and operate multiple cloud databases and about 30 web services.

Related Knowledge

Related Services

Request a sweep audit of NVARCHAR literals

If you need to repeat the same checks across multiple environments, we can discuss your entire operations setup.

Request a sweep audit of NVARCHAR literals

← Back to Knowledge Base