我的laravel雄辩是这样的:
$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子句中,并且包含非聚合列'myshop.products.id',它在功能上不依赖于GROUP BY子句中的列;这与sql_mode = only_full_group_by不兼容(SQL:select * from
products
,其中status
= 1,stock
> 0,category_id
= 5 group bystore_id
order byupdated_at
desc limit 4)
我该如何解决?
我遇到了类似的问题,并通过在数据库连接设置中禁用mysql严格模式来解决它。
'connections' => [
'mysql' => [
// Behave like MySQL 5.6
'strict' => false,
// Behave like MySQL 5.7
'strict' => true,
]
]
您可以在this blog post by Matt Stauffer中找到更多配置设置
如上所述,将strict mode设置为false可能会给出安全漏洞,我正在做的是在需要它的查询之前将sql_mode设置为empty。请注意,这是一个TEMPORARY更改,一旦您的连接关闭(通过laravel请求),您将被设置为原始sql_mode = only_full_group_by(或更高)。
DB :: statement(“SET sql_mode =''”);
干杯,快乐的编码......
ps。:它不是laravel错误,如果你试图直接在你的数据库上执行这个查询,你将面临相同的结果。这个工作在mysql以及第一个语句中再次工作,将是一个临时的会话更改,而不是永久性的。
我通过在config / database.php文件中设置模式来解决它。
设置模式如下:
'modes' => [
'ONLY_FULL_GROUP_BY',
'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',
]
],
这是因为最新版本的MySQL的行为与大多数dbms已经对group by
条款有关;一般规则是
如果你正在使用
group by
,你的select
中的所有列都必须存在于group by
中或通过聚合函数聚合(sum
,count
,avg
等)
您当前的查询是由store_id
进行分组,但由于您选择了所有内容,因此上述规则不受尊重。
在文件夹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中运行此命令清除config cash
php artisan配置:清除
在.env文件中的ADD变量:DB_STRICT=false
。
并从文件中的REPLACE位置:config / database.php,下一个代码'strict' => true
ON 'strict' => (env('DB_STRICT', 'true') === 'true' ? true : false)
。
祝好运。
我通过添加“modes”选项并在config => database.php中仅设置我想要启用的模式来解决了这个问题
'mysql' => [
...
'modes' => [
'STRICT_ALL_TABLES',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_ZERO_DATE',
'NO_ZERO_IN_DATE',
'NO_AUTO_CREATE_USER',
],
],
在this tutorial中查看更多详细信息
组
'strict' => false
在config / database.php文件中。在阵列connections => mysql =>
在我的情况下,我使用的是mysql 5.7 Laravel 5.7
检查查询:
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 = ''
。
要仅选择聚合列,请使用raw methods provided by Laravel之一。例如:
Product::selectRaw('store_id')
->where('status', 1)
->groupBy('store_id')
->get();
#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=''");
}
}