ここで紹介する内容は、弊社で確認した一例です。
本ページを参考に作業をされ、何らかのトラブルや損失・損害等が発生しましても一切責任を負えません。自己責任でお願いします。

MySQL 5.7でエラーが発生するようになった

今までは、MySQLのバージョン5.5を利用していたのだが、レンタルサーバー業者の都合で、バージョン5.7のみが利用できる状況になってしまった。
すると、バージョン5.5では発生していなかったのに、バージョン5.7では、

Error: SQLSTATE[HY000]: General error: 3065 Expression #1 of ORDER BY clause is not in SELECT list, references column 'xxxxxxxxx.Category.order' which is not in SELECT list; this is incompatible with DISTINCT

のエラーが発生してしまった。
DISTINCT しているにもかかわらず SELECT 句に存在していないカラムでソートをしてはいけないというエラーなのだが、バージョン5.5では正常に動作していた。この状態で問題が発生しないことが分かっているので、エラーが出ないようにする方法を探ってみた。

バージョン5.5 との違い

次の SQL コマンドを実行してみると、

mysql> SELECT @@GLOBAL.sql_mode;

バージョン5.5では、空であるのに対して、バージョン5.7では、

ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

といった値が返ってきた。
このうち、

ONLY_FULL_GROUP_BY

がエラーを発生させている設定らしい。
ならば接続時に、

SET sql_mode = 'NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

といった SQL コマンドを実行できれば良いのではないだろうか。

CakePHP 2 で接続時に実行するSQLをカスタマイズする

CakePHP ではデータベースの接続に関する設定を、app/Config/database.php で行うようになっています。
デフォルトでは、

class DATABASE_CONFIG {

	public $default = array(
		'datasource' => 'Database/Mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'user',
		'password' => 'password',
		'database' => 'database_name',
		'prefix' => '',
		//'encoding' => 'utf8',
	);

 のようになっています。
ここに、「settings」キーを追加します。
今回は、

class DATABASE_CONFIG {

	public $default = array(
		'datasource' => 'Database/Mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'user',
		'password' => 'password',
		'database' => 'database_name',
		'prefix' => '',
		//'encoding' => 'utf8',
		'settings' => array(
			"'NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'",
		),
	);

としました。
これで、上記のエラーは発生しなくなりました。