トップ  > メモ一覧  > カテゴリ「細かい注意点」の絞り込み結果 : 1件

1件中 1 〜 1 表示  1 

No.1956 末尾の空白が消える@@

「末尾がspaceになり得るデータ」(テキスト及び純粋なバイナリデータ)には、CHARやVARCHARは使ってはならない。BLOB系に入れるようにする。
  • CHARやVARCHARは、末尾がspaceだった場合、どの段階でかは忘れたが、自動的に除去されるので、保存したデータを比較する際に不一致と判定されたり、バイナリデータの場合、破損する可能性がある。

とのこと・・・
ユニーク制約カラムに「hoge」と「hoge 」は両方は入らない

CHAR型とVARCHAR型

ここでは文字列型の中でもCHAR型とVARCHAR型について確認していきます。

CHAR(M)
  固定長文字列
  Mは文字数を指定。0から255文字
  別名:CHAR(M)はCHARACTER(M)の別名

VARCHAR(M)
  可変長文字列
  Mはバイト数を指定。0から65535バイト
  別名:VARCHAR(M)はCHARACTER VARYING(M)の別名

CHAR型は指定した文字数以下の文字を格納した場合には文字列の末尾に空白を必要なだけ付け加えて指定の長さの文字列として格納します。ただし値を取得する場合は末尾にある空白は全て削除された上で取得されますし比較される時も同様です。

それに対してVARCHAR型は末尾に空白を付けるようなことはしません。また現行のバージョンでは末尾に空白がある文字列であっても空白が付いたまま格 納されます。取得する時も空白付きで取得しますが、WHERE句で比較する時だけ末尾の空白を削除した上で比較されます。

それではCHAR(5)型のカラムとVARCHAR(5)型のカラムを持つテーブルを作成してみます。

CHAR型とVARCHAR型

ではデータを追加した後でテーブルのデータを取得してみます。

CHAR型とVARCHAR型

CHAR(5)型は常に5文字の長さになるように空白を使って足りない分を埋めて格納されますが、格納されたデータを取得すると文字列の末尾に付いている空白は削除された上で取得されます。よって今回の場合は同じ結果を取得します。

では今度は各カラムに格納する文字列の最後に空白を加えたデータを追加してみます。

CHAR型とVARCHAR型

MySQL5.1ではVARCHAR型のカラムに末尾に空白を含む文字列を格納しても末尾の空白は削除されずに格納されます。CHAR型の場合は取得する 時に末尾についた空白は削除された上で取得されますが、VARCHAR型の場合は取得する時に末尾についた空白はそのまま取得します。

ただしVARCHAR型のカラムに格納された値であっても、WHERE句で比較する場合は末尾の空白を削除した上で比較されますので注意して下さい。

CHAR型とVARCHAR型



MySQLのカラム切り捨て脆弱性

WordPress 2.6.2で修正された「mt_srand and not so random numbers」と「MySQL and SQL Column Truncation Vulnerabilities」のうち、MySQLの方は他のアプリケーションでも影響しているものがありそうな感じがする。セキュリティ上の問題まで行かなくても、意図しない挙動になっていたりしないだろうか。

この問題はMySQLの以下の2つの挙動によって起る。

  • INSERT、UPDATE文でカラムの長さ以上の文字列を挿入しても、エラーにせず文字列末尾を切り捨てたものを挿入する
  • WHERE句での文字列の比較は、文字列末尾のスペースを切り捨てたもので行われる

論理削除を行えるようにした場合、カラムに一意制約を付けられないため、アプリケーション側で一意性チェックを行うことで、一意性が保証されるよう にすることがある。が、この2つの挙動を利用すると、データ登録時の一意性チェックをすり抜けることが出来てしまう。 まず、重複させようとする値の末尾にカラムの最大長までスペースを付け、その後ろにスペースでない文字を付けたものを用意する。一意性チェックでは、テー ブルを検索して同じ値がないことを確認する訳だが、スペースではないものは切り捨てられないので、この文字列は既存の値とはマッチしない。一意でないこと が確認できたので、この文字列はテーブルに挿入される。すると末尾の文字が切り捨てられ、末尾はスペースのみになる。MySQLは末尾のスペースを無視し て検索するので、データを取り出す時には、スペース有り無しの両方がマッチしてしまう。1件しかマッチしないという前提で作られた処理がどうなるかは実装 次第だ。

入力時に文字列の長さチェックを行っている場合、末尾の切り捨てが起るような文字列が挿入されることがないため、この問題はかろうじて回避されている。根本的な解決方法は、MySQLのSQLモードに STRICT_ALL_TABLESかSTRICT_TRANS_TABLESを指定して、カラムに不正値を挿入した時にエラーになるようにすることであ る。その他のMySQL独特の挙動を抑制するためにTRADITIONALを指定する方が良い感じではあるが、アプリケーションがその挙動に依存している 可能性もあるので、変更するのは難しいかもしれない。

ちなみにカラム切り捨ての方は、文字コードを指定せずにテーブルを作った場合に問題になる場合がある。たとえばMobavle Typeのエントリータイトルに255文字以上入力して保存すると、末尾の文字が化けてしまう場合がある。これはMovable Type側はUTF-8の文字列を送っているが、MySQL側はISO-8859-1として扱うので、UTF-8の途中のバイトで切り捨てられてしまうた めである。


引用元

更新:2010/01/05 15:08 カテゴリ: MySQL  > 細かい注意点 ▲トップ
1件中 1 〜 1 表示  1 

FuelPHP

Mac

web開発

プロマネ

マネタイズ

プレゼン

webサービス運用

webサービス

Linux

サーバ管理

MySQL

ソース・開発

svn・git

PHP

HTML・CSS

JavaScript

ツール, ライブラリ

ビジネス

テンプレート

負荷・チューニング

Windows

メール

メール・手紙文例

CodeIgniter

オブジェクト指向

UI・フロントエンド

cloud

マークアップ・テキスト

Flash

デザイン

DBその他

Ruby

PostgreSQL

ユーティリティ・ソフト

Firefox

ハードウェア

Google

symfony

OpenPNE全般

OpenPNE2

Hack(賢コツ)

OpenPNE3

リンク

個人開発

その他

未確認

KVS

ubuntu

Android

負荷試験

オープンソース

社会

便利ツール

マネー

Twig

食品宅配

WEB設計

オーディオ

一般常識

アプリ開発

サイトマップ

うずら技術ブログ

たませんSNS

rss2.0