WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

パラメータ化の副次的な効用

by WebSurfer 4. June 2016 15:12

パラメータ化クエリを使用するというセキュリティ対策として普通にやるべきことをやっていれば、照合順序の違いによる文字化けに悩むことはなさそうという話を書きます。

元は MSDN Forum の「nvarcharに日本語を入力すると?????????になる」という表題のスレッドでの話です。

上の MSDN Forum のスレッドの問題は、簡単に書くと、SQL Azure の照合順序のデフォルトは SQL_Latin1_General_CP1_CI_AS となっていて、それに例えば以下のように 'あいうえお' というように N プレフィックスをつけないリテラルを INSERT すると文字化けするという話です。

INSERT INTO [Table] ([Name]) VALUES ('あいうえお')

(何故文字化けするかは MSDN Blog の記事「Unicode型列(NCHAR/NVARCHAR) に格納されるデータが “?” になる」に説明されていますので、そちらを見てください。手抜きでスミマセン)

クエリをパラメータ化して ADO.NET + SqlClient 経由で INSERT, UPDATE をかければ、照合順序が Japanese_CI_AS(デフォルト)でも SQL_Latin1_General_CP1_CI_AS(SQL Azure のデフォルトらしい)でも文字化けはしません。

パラメータ化あり / なしでどう違うかの例を以下に書きます。

まず、サンプルとして SQL Server 2008 Express に照合順序が SQL_Latin1_General_CP1_CI_AS のデータベースを作りました。以下の画像の通りです。

照合順序

それに以下のコードで INSERT してみます。上のクエリがパラメータ化なし、下のクエリがパラメータ化ありです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      string connString = @"接続文字列";

      using(SqlConnection conn = new SqlConnection(connString))
      {
        conn.Open();
        string query = 
          "INSERT INTO [Table] ([Name]) VALUES ('あいうえお')";
        using(SqlCommand cmd = new SqlCommand(query, conn))
        {
          cmd.ExecuteNonQuery();
        }

        query ="INSERT INTO [Table] ([Name]) VALUES (@Name)";
        using(SqlCommand cmd = new SqlCommand(query, conn))
        {
          cmd.Parameters.Add(
            new SqlParameter("@Name", SqlDbType.NVarChar, 50));
          cmd.Parameters["@Name"].Value = "かきくけこ";
          cmd.ExecuteNonQuery();
        }
      } 
    }
  }
}

結果は以下の通りです。赤枠で囲ったものがパラメータ化なし、青枠で囲ったものがパラメータ化ありです。

INSERT 結果

何故パラメータ化クエリを使うと文字化けの問題がなくなるのかと言うと、TechNet の記事「第 4 回 アドホック クエリのパラメータ化」の下の方に書いてあるように "SqlParameter クラスを利用すると、内部的には sp_executesql に変換されて実行されるようになり"、 その際以下のように N プレフィックスが付与されるからです。

exec sp_executesql 
    N'INSERT INTO [Table] ([Name]) VALUES (@Name)',
    N'@Name nvarchar(5)',
    @Name=N'かきくけこ'

というわけで、クエリをパラメータ化して ADO.NET + SqlClient を使えば(普通のやり方をしていれば)、照合順序の違いによって文字化けに悩むことはなさそうです。

Tags: ,

ADO.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  November 2020  >>
MoTuWeThFrSaSu
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

View posts in large calendar