我很好奇是否有可能使用PDO将值数组绑定到占位符。这里的用例试图传递一个值数组,以便与IN()条件一起使用。
我希望能够这样做:
<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN(:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>
并让PDO绑定并引用数组中的所有值。
目前我正在做:
<?php
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
foreach($ids as &$val)
$val=$db->quote($val); //iterate through array and quote
$in = implode(',',$ids); //create comma separated list
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN('.$in.')'
);
$stmt->execute();
?>
这当然是工作,但只是想知道是否有一个内置的解决方案,我错过了?
在MySQL和PDO中,我们可以使用JSON数组和JSON_CONTAINS() (https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains)进行搜索。
$ids = [123, 234, 345, 456]; // Array of users I search
$ids = json_encode($ids); // JSON conversion
$sql = <<<SQL
SELECT ALL user_id, user_login
FROM users
-- Cast is mandatory beaucause JSON_CONTAINS() waits JSON doc candidate
WHERE JSON_CONTAINS(:ids, CAST(user_id AS JSON))
SQL;
$search = $pdo->prepare($sql);
$search->execute([':ids' => $ids]);
$users = $search->fetchAll();
我们也可以使用JSON_TABLE() (https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table)进行更复杂的情况和JSON数据探索:
$users = [
['id' => 123, 'bday' => ..., 'address' => ...],
['id' => 234, 'bday' => ..., 'address' => ...],
['id' => 345, 'bday' => ..., 'address' => ...],
]; // I'd like to know their login
$users = json_encode($users);
$sql = <<<SQL
SELECT ALL user_id, user_login
FROM users
WHERE user_id IN (
SELECT ALL user_id
FROM JSON_TABLE(:users, '$[*]' COLUMNS (
-- Data exploration...
-- (if needed I can explore really deeply with NESTED kword)
user_id INT PATH '$.id',
-- I could skip these :
user_bday DATE PATH '$.bday',
user_address TINYTEXT PATH '$.address'
)) AS _
)
SQL;
$search = $pdo->prepare($sql);
$search->execute([':users' => $users]);
...
在MySQL和PDO中,我们可以使用JSON数组和JSON_CONTAINS() (https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains)进行搜索。
$ids = [123, 234, 345, 456]; // Array of users I search
$ids = json_encode($ids); // JSON conversion
$sql = <<<SQL
SELECT ALL user_id, user_login
FROM users
-- Cast is mandatory beaucause JSON_CONTAINS() waits JSON doc candidate
WHERE JSON_CONTAINS(:ids, CAST(user_id AS JSON))
SQL;
$search = $pdo->prepare($sql);
$search->execute([':ids' => $ids]);
$users = $search->fetchAll();
我们也可以使用JSON_TABLE() (https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table)进行更复杂的情况和JSON数据探索:
$users = [
['id' => 123, 'bday' => ..., 'address' => ...],
['id' => 234, 'bday' => ..., 'address' => ...],
['id' => 345, 'bday' => ..., 'address' => ...],
]; // I'd like to know their login
$users = json_encode($users);
$sql = <<<SQL
SELECT ALL user_id, user_login
FROM users
WHERE user_id IN (
SELECT ALL user_id
FROM JSON_TABLE(:users, '$[*]' COLUMNS (
-- Data exploration...
-- (if needed I can explore really deeply with NESTED kword)
user_id INT PATH '$.id',
-- I could skip these :
user_bday DATE PATH '$.bday',
user_address TINYTEXT PATH '$.address'
)) AS _
)
SQL;
$search = $pdo->prepare($sql);
$search->execute([':users' => $users]);
...
你可以这样转换:
$stmt = $db->prepare('SELECT * FROM table WHERE id IN('.$in.')');
在此:
$stmt = $db->prepare('SELECT * FROM table WHERE id IN(:id1, :id2, :id3, :id7, :id8, :id9)');
然后用这个数组执行它:
$stmt->execute(array(
:id1 =>1, :id2 =>2, :id3 =>3, :id7 =>7, :id8 =>8, :id9 => 9
)
);
因此:
$in = array();
$consultaParam = array();
foreach($ids as $k => $v){
$in[] = ':id'.$v;
$consultaParam[':id'.$v] = $v;
}
最后的代码:
$ids = array(1,2,3,7,8,9);
$db = new PDO(...);
$in = array();
$consultaParam = array();
foreach($ids as $k => $v){
$in[] = ':id'.$v;
$consultaParam[':id'.$v] = $v;
}
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN('.$in.')'
);
$stmt->execute($consultaParam);
您使用的是什么数据库?在PostgreSQL中,我喜欢使用ANY(数组)。重复一下你的例子:
<?php
$ids=array(1,2,3,7,8,9);
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id = ANY (:an_array)'
);
$stmt->bindParam('an_array',$ids);
$stmt->execute();
?>
不幸的是,这是非常不可移植的。
在其他数据库中,您将需要像其他人提到的那样,创建自己的魔法。当然,您需要将该逻辑放入类/函数中,以使其在整个程序中可重用。看看PHP mysql_query页面上的注释。关于这个主题的更多想法和这个场景的示例。
您必须构造查询字符串。
<?php
$ids = array(1, 2, 3, 7, 8, 9);
$inQuery = implode(',', array_fill(0, count($ids), '?'));
$db = new PDO(...);
$stmt = $db->prepare(
'SELECT *
FROM table
WHERE id IN(' . $inQuery . ')'
);
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
$stmt->bindValue(($k+1), $id);
$stmt->execute();
?>
chris(评论)和一些人都有麻烦了,建议foreach-loop…
(...)
// bindvalue is 1-indexed, so $k+1
foreach ($ids as $k => $id)
$stmt->bindValue(($k+1), $id);
$stmt->execute();
... 可能是多余的,因此foreach循环和$stmt->执行可以被替换为…
<?php
(...)
$stmt->execute($ids);