如何正确使用多个SqlSelect set/add where函数
How to correctly use multiple SqlSelect set/add where functions
我正在使用 SilverStripes SQLSelect class 和一些可选的(前端)过滤器拼凑一个 SQL 查询。
尝试将 addWhere()
与参数一起使用时,查询没有结果。例如:
$sql->useConjunction();
$sql->addWhere(['SiteTree.ClassName' => 'ResourcePage']);
if (self::$Filters['Tags'])
{
$sql->addLeftJoin('ResourcePage_Tags', 'ResourcePage_Tags.ResourcePageID = SiteTree.ID');
$sql->addWhere(['ResourcePage_Tags.ResourceTagID IN (?)' => implode(',', self::$Filters['Tags'])]);
}
if (self::$Filters['Types'])
{
$sql->addLeftJoin('ResourcePage_Types', 'ResourcePage_Types.ResourcePageID = SiteTree.ID');
$sql->addWhere(['ResourcePage_Types.ResourceTypeID IN (?)' => implode(',', self::$Filters['Types'])]);
}
如果我将其视为字符串,我确实会得到结果(就像我期望使用手动 SQL 进行测试一样)。例如:
$sql->useConjunction();
$sql->addWhere("SiteTree.ClassName = 'ResourcePage'");
if (self::$Filters['Tags'])
{
$sql->addLeftJoin('ResourcePage_Tags', 'ResourcePage_Tags.ResourcePageID = SiteTree.ID');
$sql->addWhere('ResourcePage_Tags.ResourceTagID IN ('.implode(',', self::$Filters['Tags']).')');
}
if (self::$Filters['Types'])
{
$sql->addLeftJoin('ResourcePage_Types', 'ResourcePage_Types.ResourcePageID = SiteTree.ID');
$sql->addWhere('ResourcePage_Types.ResourceTypeID IN ('.implode(',', self::$Filters['Types']).')');
}
使用 $sql->__toString()
找到的生成(简化)查询是:
SELECT
DISTINCT SiteTree.*
FROM
SiteTree
LEFT JOIN
"ResourcePage_Tags" ON ResourcePage_Tags.ResourcePageID = SiteTree.ID
LEFT JOIN
"ResourcePage_Types" ON ResourcePage_Types.ResourcePageID = SiteTree.ID
WHERE
(SiteTree.ClassName = ?)
AND (ResourcePage_Tags.ResourceTagID IN (?))
AND (ResourcePage_Types.ResourceTypeID IN (?))
上面输出的参数部分是一个数组:
'ResourcePage',
1 => '38'
2 => '5,4'
查询中省略的部分是一些始终存在的 MATCH AGAINST
和 LIMIT ORDER BY
子句。
在字符串和参数化版本之间获得两种不同的行为我做错了什么?
您使用 in (?)
然后传递值数组的第一个示例将无法正确执行,因为假设 ?
在使用 prepare 时是一个值。这意味着您现在查询的 ResourceTypeID
等于 array_value1,array_value2
。因此,self::$Filters['Tags']
数组中的每个项目都需要一个占位符 (?
)。
该框架确实有一个辅助方法来实现这一点:
$placeholders = DB::placeholders(self::$Filters['Tags'])
$query->addWhere([
"ResourcePage_Types.ResourceTypeID IN ($placeholders)" => self::$Filters['Tags']
]);
我正在使用 SilverStripes SQLSelect class 和一些可选的(前端)过滤器拼凑一个 SQL 查询。
尝试将 addWhere()
与参数一起使用时,查询没有结果。例如:
$sql->useConjunction();
$sql->addWhere(['SiteTree.ClassName' => 'ResourcePage']);
if (self::$Filters['Tags'])
{
$sql->addLeftJoin('ResourcePage_Tags', 'ResourcePage_Tags.ResourcePageID = SiteTree.ID');
$sql->addWhere(['ResourcePage_Tags.ResourceTagID IN (?)' => implode(',', self::$Filters['Tags'])]);
}
if (self::$Filters['Types'])
{
$sql->addLeftJoin('ResourcePage_Types', 'ResourcePage_Types.ResourcePageID = SiteTree.ID');
$sql->addWhere(['ResourcePage_Types.ResourceTypeID IN (?)' => implode(',', self::$Filters['Types'])]);
}
如果我将其视为字符串,我确实会得到结果(就像我期望使用手动 SQL 进行测试一样)。例如:
$sql->useConjunction();
$sql->addWhere("SiteTree.ClassName = 'ResourcePage'");
if (self::$Filters['Tags'])
{
$sql->addLeftJoin('ResourcePage_Tags', 'ResourcePage_Tags.ResourcePageID = SiteTree.ID');
$sql->addWhere('ResourcePage_Tags.ResourceTagID IN ('.implode(',', self::$Filters['Tags']).')');
}
if (self::$Filters['Types'])
{
$sql->addLeftJoin('ResourcePage_Types', 'ResourcePage_Types.ResourcePageID = SiteTree.ID');
$sql->addWhere('ResourcePage_Types.ResourceTypeID IN ('.implode(',', self::$Filters['Types']).')');
}
使用 $sql->__toString()
找到的生成(简化)查询是:
SELECT
DISTINCT SiteTree.*
FROM
SiteTree
LEFT JOIN
"ResourcePage_Tags" ON ResourcePage_Tags.ResourcePageID = SiteTree.ID
LEFT JOIN
"ResourcePage_Types" ON ResourcePage_Types.ResourcePageID = SiteTree.ID
WHERE
(SiteTree.ClassName = ?)
AND (ResourcePage_Tags.ResourceTagID IN (?))
AND (ResourcePage_Types.ResourceTypeID IN (?))
上面输出的参数部分是一个数组:
'ResourcePage',
1 => '38'
2 => '5,4'
查询中省略的部分是一些始终存在的 MATCH AGAINST
和 LIMIT ORDER BY
子句。
在字符串和参数化版本之间获得两种不同的行为我做错了什么?
您使用 in (?)
然后传递值数组的第一个示例将无法正确执行,因为假设 ?
在使用 prepare 时是一个值。这意味着您现在查询的 ResourceTypeID
等于 array_value1,array_value2
。因此,self::$Filters['Tags']
数组中的每个项目都需要一个占位符 (?
)。
该框架确实有一个辅助方法来实现这一点:
$placeholders = DB::placeholders(self::$Filters['Tags'])
$query->addWhere([
"ResourcePage_Types.ResourceTypeID IN ($placeholders)" => self::$Filters['Tags']
]);