我能够绑定int
,str
,bool
和null
类型的值,但我无法绑定数组类型。
我尝试了两种功能,即bindValue
和bindParam
,但它们都没有奏效。
我怎么能做到这一点?
// a helper function to map Sqlite data type
function getArgType($arg) {
switch (gettype($arg)) {
case 'double': return SQLITE3_FLOAT;
case 'integer': return SQLITE3_INTEGER;
case 'boolean': return SQLITE3_INTEGER;
case 'NULL': return SQLITE3_NULL;
case 'string': return SQLITE3_TEXT;
default:
throw new \InvalidArgumentException('Argument is of invalid type '.gettype($arg));
}
}
$sql = "SELECT * FROM table_name WHERE id IN (?)";
$params = [[10, 9, 6]]; // array of array
$dbpath = '/path/to/sqlite.sqlite';
$db = new SQLite3($dbPath, SQLITE3_OPEN_READONLY);
$stmt = $db->prepare($sql);
try {
foreach ($params as $index => $val) {
if (is_array($val)) {
/************* I am stuck here *************/
$ok = $stmt->bindParam($index + 1, $val);
// Using bindValue also didn't worked!
} else {
$ok = $stmt->bindValue($index + 1, $val, getArgType($val));
}
if (!$ok) {
throw new Exception("Unable to bind param: $val");
}
}
} catch (Exception $ex) {
// NO exception is thrown from bindValue() or bindParam()
$reason = "Error in binding statement. " . $ex->getMessage();
die($reason);
}
$result = $stmt->execute();
$data = [];
while ($row = $result->fetchArray($mode)) {
$data[] = $row;
}
var_dump($data);
编辑:我已经尝试用param数组中所需数量的问号替换单个?
,但只有当我的数组小于 1000时才能正常工作价值!我认为这是对PHP中SQLite3中语句编写方式的限制。
答案 0 :(得分:9)
不幸的是,不可能!你不能绑定一个数组。
对您来说最简单的解决方案如下:
?
)的SQL查询
但还有另一种选择(例如子SELECT)
More information here(即使它是一个Java问题,它几乎是相同的主题/问题,因为数据库类型在这种情况下并不重要)
编辑:通常,绑定参数的SQL限制设置为999
,但您can change it if you need to。
答案 1 :(得分:2)
您无法将数组绑定为IN (?)
子句的列表。 IN
列表中的每个值都必须获得其独特的占位符。
要使其动态化,首先确定值数组,然后动态构建SQL。
这将是您的代码:
$arrayParam = [10, 9, 6];
$placeHolders = implode(',', array_fill(0, count($arrayParam), '?'));
$sql = "SELECT * FROM table_name WHERE id IN ($placeHolders) AND name = ?";
// Merge the "array" parameter values with any other parameter values
// into one non-nested array:
$params = array_merge($arrayParam, ['myname']);
// ...
foreach ($params as $index => $val) {
// No sub arrays allowed:
$ok = $stmt->bindValue($index + 1, $val, getArgType($val));
// ... etc
答案 2 :(得分:2)
(警告:这个答案是在'mysql'标签被删除之前写的;我不知道addslashes
是否适用于sqlite3。)
在PHP中,将$ list作为发往IN列表的值数组:
$list = array(1, 2, 'abcd', 'double quote: "', "apostrophe: don't");
$ins = implode(', ', array_map(
function($a) {
return "'" . addslashes($a) . "'";
}, $list));
echo $sql = "... IN ($ins) ...";;
产量
... IN ('1', '2', 'abcd', 'double quote: \"', 'apostrophe: don\'t') ...
(是的,这可以通过正常的for
循环完成,而不使用array_map
和“匿名函数”。)
别担心;对于数字列,数字('123'
)的引号是正常的。
答案 3 :(得分:2)
我建议你尝试做一些解决方法。将查询结果传递给临时表。
// a helper function to map Sqlite data type
function getArgType($arg) {
switch (gettype($arg)) {
case 'double': return SQLITE3_FLOAT;
case 'integer': return SQLITE3_INTEGER;
case 'boolean': return SQLITE3_INTEGER;
case 'NULL': return SQLITE3_NULL;
case 'string': return SQLITE3_TEXT;
default:
throw new \InvalidArgumentException('Argument is of invalid type '.gettype($arg));
}
}
function getTempValues() {
$sql = "SELECT * FROM `myTemp`";
$params = [$in]; // array of array
$dbpath = '/path/to/sqlite.sqlite';
$db = new SQLite3($dbPath, SQLITE3_OPEN_READONLY);
$stmt = $db->prepare($sql);
$result = $stmt->execute();
$data = [];
while ($row = $result->fetchArray($mode)) {
$data[] = $row;
}
return $data;
}
function addToTemp($in) {
$sql = "SELECT * INTO `myTemp` FROM `table_name` WHERE `id` = ?";
$params = [$in]; // array of array
$dbpath = '/path/to/sqlite.sqlite';
$db = new SQLite3($dbPath, SQLITE3_OPEN_READONLY);
$stmt = $db->prepare($sql);
if(is_array($in)) {
foreach($in as $newValue) {
addToTemp($newValue);
}
} else {
try {
foreach ($params as $index => $val) {
$ok = $stmt->bindValue($index + 1, $val, getArgType($val));
if (!$ok) {
throw new Exception("Unable to bind param: $val");
}
}
} catch (Exception $ex) {
// NO exception is thrown from bindValue() or bindParam()
$reason = "Error in binding statement. " . $ex->getMessage();
die($reason);
}
$stmt->execute();
}
return getTempValues();
}
print_r(addToTemp([10,9,6]));
答案 4 :(得分:1)
你可以添加吗?占位符与数组中的项目数一样多
Select * from table_a where field in (?,?,?,?,?,?,?,.....)
如果它们大于1000,则将它们分成两个或多个查询。