2013.4.29追記: 2番の limit の件について、コメント欄でのご指摘にもとづいて最新の状況を追記しました。開発中の CodeIgniter 3 では、このあたりの修正が不要なように改善されています。
2011.10.24追記: この記事では、CodeIgniter 2.0.3について書いています。
今年のはじめくらいから、仕事でCodeIgniterを使い始めている。
CodeIgniterを選んだ理由はいろいろあるけど、
理由のひとつは「MySQLも、SQL Serverもサポートしている」ということだった。
これは、ユーザーガイドにもしっかり書いてある。
http://codeigniter.com/user_guide/general/requirements.html
ところが、SQL Serverというのはそれなりにクセがあるデータベースで、
CodeIgniterが実際にちゃんとSQL Serverを扱えるか、というところでは
くだらないところではあるけど、多少の問題を感じた。
いくつか、備忘録として書いておこう。
1. 日本語環境でmssqlドライバーは使うべきでないケースが多い。
慣れてる人には当たり前のことなんだろうけど
mssqlドライバーはPHPのmssql関数を使ったドライバーで、
出てくる日本語文字データはShift-JISのみ。
SQL Serverは内部的にはUnicode(UCS-2)で扱っているにも関わらず、だ。
UTF-8が使いたければsqlsrvドライバーを使うしかないんだけど、
CodeIgniterにsqlsrvドライバーが追加されたのは割と最近の話だったのだ...。
2. 実は Active Record で limit が使えない。
普通にページネーションできるだろー、と思ってたら
なぜかできない。
調べてみたら、limitの処理が超適当。
system/database/drivers/mssql/mssql_driver.php Line 640-645
system/database/drivers/sqlsrv/sqlsrv_driver.php Line 572-577
function _limit($sql, $limit, $offset)
{
$i = $limit + $offset;return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);
}
いやいやいやいや! それoffsetがoffsetになってないから!
これにはがっかりした...
具体的な対策としては、limitを使う時のみ、
SQL Server 2008 R2 までであれば、 row_number関数を含むサブクエリーを出して
その結果から切り出すようなSQL文字列を作るように
_limit関数の中をいじればOK。
SQL Server 2012 であれば、 OFFSET FETCH でもっとシンプルに記述できます。
http://msdn.microsoft.com/ja-jp/library/ms188385(v=sql.110).aspx
3. sqlsrvドライバーで文字列はUTF-8に指定してるのに、エラーメッセージがShift-JISで帰ってくる。
これは別にCodeIgniterのせいじゃないんだけど、
ドライバーの_error_message関数をアレしてコレするだけで回避できるレベルです。
これ以外の点については、
CodeIgniterは学習コストがすごく低い、良いフレームワークだと思うので
みんなもっとガンガン使うと良いと思います。
でもSQL Serverといっしょに使う時は気をつけましょうね。
t-v
SQL Server 2012以降から、OFFSET FETCHが使えるようになったので、この点の対応は非常に楽になりました。
戸田 広からt-vへの返信
おお、本当ですね! ありがとうございます!
CodeIgniter も、開発中のバージョン 3 のコードで、 SQL Server 2012 であれば OFFSET FETCH を使うようになっているようです。