古めのPHPから SQL Server のデータベースに接続するアプリケーションをメンテナンスすることになり、環境構築している途中でハマったのでメモ。
環境構築で、やったこと
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から接続するときのエンコーディングを色々と変えながら試しても同じ化け方だったので、これはPHPとMSSQLとの通信の過程で発生した文字化けではないことが推測された。
その後、データベースの設定を改めて確認していたところ、データベースの照合順序がLatinになっていることに気付き、これが原因であることを突き止めた。
疑問
データベースの照合順序がLatin系のときに、select
文のfrom
句に書いた日本語テーブル名がマッチしなくてテーブル見つからない状態になるのは、わかる。
でも、SSMSからクエリを発行するときは、なぜ普通に操作できるんだろう?
謎すぎる…
(SSMSからも作成・操作できなかったら、もっと早く気付いてたかなー)
さいごに
文字コードの話を真面目に書き始めると、とんでもない長さになってしまうので、今日はこの辺で。
参考資料
環境情報
- PHP 5.3.x(もちろん、これからPHP7移行するからね!!)
- SQL Server 2014 on AWS RDS