将参数绑定到部分 SQL 语句

Bind parameters to partial SQL statement

我正在处理一个旧的 PHP 应用程序,并负责确保所有区域都使用准备好的语句。目前它使用 sprintf 在执行之前构建大部分查询。

下面是当前实现的一些示例代码:

$queryString = "SELECT count(user.uid) as count
              FROM user
              LEFT JOIN voucher
                ON user.voucher_uid = voucher.uid
              LEFT JOIN affiliation
                ON voucher.uid = affiliation.voucher_uid
                  @affiliation
              LEFT JOIN account
                ON affiliation.account_uid = account.uid
              WHERE affiliation.account_uid IN (@accounts)
                @active
                @search
                @template
                @onlyown
                AND voucher.template NOT LIKE 'api_%'
                AND user.role != 'superadmin'";
$sql = replace_tokens(
  $queryString,
  array(
    'accounts' => implode(', ', array_fill(0, count($accounts), '?')),
    'template' => $template,
    'search' => $search,
    'onlyown' => $onlyown,
    'affiliation' => $affiliation,
    'active' => $active
  )
);

return array_get(self::queryFetchOne($sql, $accounts), 'count', 0);

replace_tokens函数将前面用@声明的"variables"替换为sql。下面是如何构建 @search 变量的示例。

if (is_string($search) && !empty($search)) {
  $search = sprintf('AND (voucher.code LIKE "%%%s%%" OR user.email LIKE "%%%s%%" OR user.salutation LIKE "%%%s%%")', $search, $search, $search);
} else {
  $search = '';
}

现在,我想通过将 %%%s%% 更改为 :search 并简单地使用命名参数来解决搜索问题。但是,$accounts 变量是一个帐户名称数组,并在 in 语句中使用问号参数。

我的问题的答案可能是否定的,但我想解决这个问题而不必只使用问号参数,这需要我跟踪构建数组时为所有参数保留的顺序。

是否有任何好的方法将参数绑定到部分语句或解决使用我上面描述的大量问号参数的问题?

这是工程错误。

我的推荐;包含与参数相关的变量的数组。 例如

$sql1 = "select * from Apples where a=? and b=?"

$sql2 = " or c=?;"

均由函数 gen_sql1()gen_sql2() 生成。

只需gen_sql1return数组的前半部分:1, 2。有gen_sql2return下半场:3.

最后,组合数组,你就有了一个数组,把它们插入“?”参数顺序:

$fullsql = "select * from Apples where a=1 and b=2 or c=3"

我通过构建两个变量来解决这个问题:一个是查询字符串,另一个是查询参数的哈希数组。

if (is_string($search) && !empty($search)) {
  $search = 'AND (voucher.code LIKE :code OR user.email LIKE :email OR user.salutation LIKE :salutation)';
  $params['code'] = "%%$search%%";
  $params['email'] = "%%$search%%";
  $params['salutation'] = "%%$search%%";
} else {
  $search = '';
}

当你完成所有条件代码时,你有一个查询参数的哈希数组,你可以将其传递给 PDO execute()

但是你必须确保你所有的命名参数都是唯一的。如果您在不同的条件搜索词中使用相同的名称,就会出现混乱。在这种情况下,位置参数具有优势。