My laravel eloquentはこのようなものです:
$products = Product::where('status', 1)
->where('stock', '>', 0)
->where('category_id', '=', $category_id)
->groupBy('store_id')
->orderBy('updated_at', 'desc')
->take(4)
->get();
実行すると、次のようなエラーが発生します。
SQLSTATE [42000]:構文エラーまたはアクセス違反:1055 SELECTリストの式#1がGROUP BY句になく、GROUP BY句の列に機能的に依存しない非集計列 'myshop.products.id'が含まれています。これはsql_mode = only_full_group_byと互換性がありません(SQL:select * from
products
wherestatus
= 1 andstock
> 0 andcategory_id
= 5グループstore_id
並べ替えupdated_at
説明の制限4)
どうすれば解決できますか?
同様の問題があり、データベース接続設定でmysql厳格モードを無効にすることで解決しました。
'connections' => [
'mysql' => [
// Behave like MySQL 5.6
'strict' => false,
// Behave like MySQL 5.7
'strict' => true,
]
]
Matt Staufferによるこのブログ投稿 でさらに多くの構成設定を見つけることができます。
フォルダ内でconfig => database.php確認してくださいmysql strictがfalse、このように
'mysql' => [
'driver' => 'mysql',
'Host' => env('DB_Host', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
],
strictがtrueの場合、falseにしてからcmdでこのコマンドを実行して設定キャッシュをクリアします
php artisan config:clear
「モード」オプションを追加し、有効にするモードのみを設定することでこの問題を解決しましたconfig => database.php
'mysql' => [
...
'modes' => [
'STRICT_ALL_TABLES',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_ZERO_DATE',
'NO_ZERO_IN_DATE',
'NO_AUTO_CREATE_USER',
],
],
詳細は このチュートリアル をご覧ください
MySQLの最新バージョンは、ほとんどのdbmsがgroup by
句に関して既に行っているように動作するためです。一般的なルールは
group by
を使用している場合、select
のすべての列はgroup by
に存在するか、集計関数(sum
、count
、avg
など)
現在のクエリはstore_id
でグループ化されていますが、すべてを選択しているため、上記のルールは尊重されません。
。envファイルのADD変数:_DB_STRICT=false
_。
そして、場所からファイルに置き換える:config/database.php、次のコード_'strict' => true
_ ON 'strict' => (env('DB_STRICT', 'true') === 'true' ? true : false)
。
がんばろう。
#Have the following method in your helper file
if (!function_exists('set_sql_mode')) {
/**
* @param string $mode
* @return bool
*/
function set_sql_mode($mode = '')
{
return \DB::statement("SET SQL_MODE=''");
}
}
クエリを確認します。
Product::where('status', 1)
->where('stock', '>', 0)
->where('category_id', '=', $category_id)
->groupBy('store_id')
->orderBy('updated_at', 'desc')
->take(4)
->get();
ここでは、store_id
によってデータをグループ化し、許可されていない結果セット内のすべての列をフェッチしています。解決するには、store_id
を選択するか、その関数を集約するか、システム変数sql_mode=only_full_group_by
をSET sql_mode = ''
に変更します。
セット
'strict' => false
config/database.phpファイルで。配列内connections => mysql =>
私の場合、mysql 5.7 Laravel 5.7
集約された列のみを選択するには、 Laravelが提供するrawメソッド のいずれかを使用します。例えば:
Product::selectRaw('store_id')
->where('status', 1)
->groupBy('store_id')
->get();
前述のように、strictモードをfalseに設定するとセキュリティバグが発生する可能性があります。これは一時的な変更であり、接続が閉じると(laravel requestにより)、元のsql_mode = only_full_group_by(またはそれ以上)に設定されます。
DB :: statement( "SET sql_mode = ''");
乾杯、幸せなコーディング...
ps .:そのnot laravel fault、DBでこのクエリを直接実行しようとすると、同じ結果に直面します。この回避策は、mysqlおよび最初のステートメントで動作します。永続的なものではなく、一時的なセッションの変更。
Config/database.phpファイルでモードを設定することで解決しました。
次のようにモードを設定します。
'modes' => [
'STRICT_TRANS_TABLES',
'NO_ZERO_IN_DATE',
'NO_ZERO_DATE',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_ENGINE_SUBSTITUTION',
]
mysqlドライバー用
'mysql' => [
'driver' => 'mysql',
'Host' => env('DB_Host', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
'modes' => [
'ONLY_FULL_GROUP_BY',
'STRICT_TRANS_TABLES',
'NO_ZERO_IN_DATE',
'NO_ZERO_DATE',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_ENGINE_SUBSTITUTION',
]
],