職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

テーブル名と照合順序

古めのPHPから SQL Server のデータベースに接続するアプリケーションをメンテナンスすることになり、環境構築している途中でハマったのでメモ。

三行まとめ

  • DBの照合順序がLatin系だと、テーブル名が日本語になっているテーブルはPHPから見えなくなる。
  • でも、SSMSからはテーブル作れるし、見える。
  • なんで?

以下、本文。

環境構築で、やったこと

SSMS (SQL Server Management Console) でデータベースを新規作成し、事前に用意しておいた create table 文をゴソっと流し込んだ。このとき、デフォルトだとLatin系の照合順序でデータベースが作成されてしまうが、しばらく気付かなかった。
作ったテーブルの中には、テーブル名にもカラム名にも日本語が含まれるが、SSMSからは create table, insert, select いずれも問題なく実行できた。

どれくらい古いPHP環境なのか?

SQL Server に接続するのに、PDOを使わない世代のPHPだ。PHP7で削除されてしまった機能を使って接続する。昔はMySQLとかにもこんな感じで接続してた訳だし、大昔からPHP書いてた人たちにとっては馴染みがあるかも。

遭遇した現象

from句に日本語のテーブル名を入れたクエリを実行すると、mssql_get_last_message関数Invalid object nameというエラーを返してくる。これは、存在しないテーブル名を指定した時と同じメッセージであるから、恐らくテーブルが見えていないのだろう。

原因究明のためにやったこと

PHPから、テーブルの一覧を取得してみた。参考:SQL Server テーブル一覧取得いろいろ - Qiita

SELECT * FROM sysobjects WHERE xtype = 'u'

すると、日本語テーブル名のテーブル名は文字化けしてしまっていた。PHPから接続するときのエンコーディングを色々と変えながら試しても同じ化け方だったので、これはPHPMSSQLとの通信の過程で発生した文字化けではないことが推測された。
その後、データベースの設定を改めて確認していたところ、データベースの照合順序がLatinになっていることに気付き、これが原因であることを突き止めた。

疑問

データベースの照合順序がLatin系のときに、select文のfrom句に書いた日本語テーブル名がマッチしなくてテーブル見つからない状態になるのは、わかる。
でも、SSMSからクエリを発行するときは、なぜ普通に操作できるんだろう?
謎すぎる…
(SSMSからも作成・操作できなかったら、もっと早く気付いてたかなー)

さいごに

文字コードの話を真面目に書き始めると、とんでもない長さになってしまうので、今日はこの辺で。

環境情報

  • PHP 5.3.x(もちろん、これからPHP7移行するからね!!)
  • SQL Server 2014 on AWS RDS