如何在laravel eloquent中解决与sql_mode = only_full_group_by不兼容的问题?

问题描述 投票:7回答:11

我的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 by store_id order by updated_at desc limit 4)

我该如何解决?

php mysql laravel-5 laravel-5.3 laravel-eloquent
11个回答
28
投票

我遇到了类似的问题,并通过在数据库连接设置中禁用mysql严格模式来解决它。

'connections' => [
    'mysql' => [
        // Behave like MySQL 5.6
        'strict' => false,

        // Behave like MySQL 5.7
        'strict' => true,
    ]
]

您可以在this blog post by Matt Stauffer中找到更多配置设置


0
投票

如上所述,将strict mode设置为false可能会给出安全漏洞,我正在做的是在需要它的查询之前将sql_mode设置为empty。请注意,这是一个TEMPORARY更改,一旦您的连接关闭(通过laravel请求),您将被设置为原始sql_mode = only_full_group_by(或更高)。

DB :: statement(“SET sql_mode =''”);

干杯,快乐的编码......

ps。:它不是laravel错误,如果你试图直接在你的数据库上执行这个查询,你将面临相同的结果。这个工作在mysql以及第一个语句中再次工作,将是一个临时的会话更改,而不是永久性的。


0
投票

我通过在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',
        ]
    ],

5
投票

这是因为最新版本的MySQL的行为与大多数dbms已经对group by条款有关;一般规则是

如果你正在使用group by,你的select中的所有列都必须存在于group by中或通过聚合函数聚合(sumcountavg等)

您当前的查询是由store_id进行分组,但由于您选择了所有内容,因此上述规则不受尊重。


5
投票

在文件夹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配置:清除


5
投票

在.env文件中的ADD变量:DB_STRICT=false

并从文件中的REPLACE位置:config / database.php,下一个代码'strict' => true ON 'strict' => (env('DB_STRICT', 'true') === 'true' ? true : false)

祝好运。


5
投票

我通过添加“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中查看更多详细信息


1
投票

'strict' => false

在config / database.php文件中。在阵列connections => mysql =>

在我的情况下,我使用的是mysql 5.7 Laravel 5.7


0
投票

检查查询:

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 = ''

Reference


0
投票

要仅选择聚合列,请使用raw methods provided by Laravel之一。例如:

Product::selectRaw('store_id')
        ->where('status', 1)
        ->groupBy('store_id')
        ->get();

0
投票
 #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=''");
}
}

Then call set_sql_mode(''); just before eloquent/query

© www.soinside.com 2019 - 2024. All rights reserved.