CakePHP 3 在 SQL 中放置不必要的括号导致错误
CakePHP 3 putting un-necessary parentheses in SQL causing error
CakePHP 3.7。尝试使用 ORM 编写包含 MySQL COALESCE
条件的查询。
遵循了 的建议,最后不得不使用 newExpr()
手动编写它,因为这是给定的解决方案。
我的代码如下:
$TblRegulatoryAlerts = TableRegistry::getTableLocator()->get('TblRegulatoryAlerts');
$subscribed_to = $TblRegulatoryAlerts->getUserRegulations($u_id, $o_id, false);
$query = $this->find()
->contain('Filters.Groups.Regulations')
->select(['id', 'date', 'comment', 'Filters.label', 'Filters.anchor', 'Groups.label']);
$query->select($query->newExpr('COALESCE((SELECT COUNT(*)
FROM revision_filters_substances
WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances'));
$query->where(['date >=' => $date_start, 'date <=' => $date_end, 'Regulations.id' => $regulation_id, 'Filters.id IN' => $subscribed_to]);
$query->enableHydration(false)->orderDesc('date');
这会产生以下 SQL(debug($query->sql())
的输出:
SELECT RevisionFilters.id AS `RevisionFilters__id`, RevisionFilters.date AS `RevisionFilters__date`, RevisionFilters.comment AS `RevisionFilters__comment`, Filters.label AS `Filters__label`, Filters.anchor AS `Filters__anchor`, Groups.label AS `Groups__label`, (COALESCE((SELECT COUNT(*) FROM revision_filters_substances WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances) FROM revision_filters RevisionFilters INNER JOIN dev_hub_subdb.filters Filters ON Filters.id = (RevisionFilters.filter_id) INNER JOIN dev_hub_subdb.groups Groups ON Groups.id = (Filters.group_id) INNER JOIN dev_hub_subdb.regulations Regulations ON Regulations.id = (Groups.regulation_id) WHERE ...
不幸的是,这并没有执行,因为 Cake 在 COALESCE
语句周围放置了不必要的括号,这改变了 SQL.
在上面的代码中它生成:
(COALESCE((SELECT COUNT(*) FROM revision_filters_substances WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances)
而它需要省略 COALESCE
周围的括号,所以它只是:
COALESCE((SELECT COUNT(*) FROM revision_filters_substances WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances
这可能吗?
不要在表达式中指定别名,而是使用 Query::select()
方法的 key => value
语法指定别名,如下所示:
$query->select([
'count_substances' => $query->newExpr('...')
]);
它仍然会将表达式括在括号中,但这样会有效,因为它不包含别名。
也就是说,使用函数构建器 coalesque()
方法应该可以正常工作,链接问题中描述的问题也可以通过使用 key => value
语法来解决,其中值可以指定参数的种类,如 ['Nodes.value' => 'identifier']
,没有它会将值绑定为字符串。
但是您的示例不应该有任何此类问题,使用函数构建器 coalesce()
方法应该可以正常工作。
$query->select([
'count_substances' => $query->func()->coalesce($countSubquery, 1, ['integer'])
]);
type 参数是可选的,没有它它可以与大多数 DBMS 一起工作,但为了最大的兼容性,应该指定它以便正确绑定整数值,它也会自动设置 return函数的类型(转换类型)也为 integer
。
CakePHP 3.7。尝试使用 ORM 编写包含 MySQL COALESCE
条件的查询。
遵循了 newExpr()
手动编写它,因为这是给定的解决方案。
我的代码如下:
$TblRegulatoryAlerts = TableRegistry::getTableLocator()->get('TblRegulatoryAlerts');
$subscribed_to = $TblRegulatoryAlerts->getUserRegulations($u_id, $o_id, false);
$query = $this->find()
->contain('Filters.Groups.Regulations')
->select(['id', 'date', 'comment', 'Filters.label', 'Filters.anchor', 'Groups.label']);
$query->select($query->newExpr('COALESCE((SELECT COUNT(*)
FROM revision_filters_substances
WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances'));
$query->where(['date >=' => $date_start, 'date <=' => $date_end, 'Regulations.id' => $regulation_id, 'Filters.id IN' => $subscribed_to]);
$query->enableHydration(false)->orderDesc('date');
这会产生以下 SQL(debug($query->sql())
的输出:
SELECT RevisionFilters.id AS `RevisionFilters__id`, RevisionFilters.date AS `RevisionFilters__date`, RevisionFilters.comment AS `RevisionFilters__comment`, Filters.label AS `Filters__label`, Filters.anchor AS `Filters__anchor`, Groups.label AS `Groups__label`, (COALESCE((SELECT COUNT(*) FROM revision_filters_substances WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances) FROM revision_filters RevisionFilters INNER JOIN dev_hub_subdb.filters Filters ON Filters.id = (RevisionFilters.filter_id) INNER JOIN dev_hub_subdb.groups Groups ON Groups.id = (Filters.group_id) INNER JOIN dev_hub_subdb.regulations Regulations ON Regulations.id = (Groups.regulation_id) WHERE ...
不幸的是,这并没有执行,因为 Cake 在 COALESCE
语句周围放置了不必要的括号,这改变了 SQL.
在上面的代码中它生成:
(COALESCE((SELECT COUNT(*) FROM revision_filters_substances WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances)
而它需要省略 COALESCE
周围的括号,所以它只是:
COALESCE((SELECT COUNT(*) FROM revision_filters_substances WHERE revision_filter_id = RevisionFilters.id), 0) AS count_substances
这可能吗?
不要在表达式中指定别名,而是使用 Query::select()
方法的 key => value
语法指定别名,如下所示:
$query->select([
'count_substances' => $query->newExpr('...')
]);
它仍然会将表达式括在括号中,但这样会有效,因为它不包含别名。
也就是说,使用函数构建器 coalesque()
方法应该可以正常工作,链接问题中描述的问题也可以通过使用 key => value
语法来解决,其中值可以指定参数的种类,如 ['Nodes.value' => 'identifier']
,没有它会将值绑定为字符串。
但是您的示例不应该有任何此类问题,使用函数构建器 coalesce()
方法应该可以正常工作。
$query->select([
'count_substances' => $query->func()->coalesce($countSubquery, 1, ['integer'])
]);
type 参数是可选的,没有它它可以与大多数 DBMS 一起工作,但为了最大的兼容性,应该指定它以便正确绑定整数值,它也会自动设置 return函数的类型(转换类型)也为 integer
。