给定一组id $galleries = array(1,2,5)
我想要一个SQL查询,它在WHERE子句中使用数组的值,如:
SELECT *
FROM galleries
WHERE id = /* values of array $galleries... eg. (1 || 2 || 5) */
Run Code Online (Sandbox Code Playgroud)
如何生成此查询字符串以用于MySQL?
Fla*_*tef 322
谨防!此答案包含严重的SQL注入漏洞.请勿使用此处提供的代码示例,而不确保清除任何外部输入.
$ids = join("','",$galleries);
$sql = "SELECT * FROM galleries WHERE id IN ('$ids')";
Run Code Online (Sandbox Code Playgroud)
Lev*_*son 299
使用PDO:[1]
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
$statement = $pdo->prepare($select);
$statement->execute($ids);
Run Code Online (Sandbox Code Playgroud)
使用MySQLi [2]
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
$statement = $mysqli->prepare($select);
$statement->bind_param(str_repeat('i', count($ids)), ...$ids);
$statement->execute();
$result = $statement->get_result();
Run Code Online (Sandbox Code Playgroud)
说明:
IN()
运算符检查给定列表中是否存在值.一般来说,它看起来像这样:
expr IN (value,...)
Run Code Online (Sandbox Code Playgroud)
我们可以构建一个表达式来放置在()
数组中.请注意,括号内必须至少有一个值,否则MySQL将返回错误; 这相当于确保我们的输入数组至少有一个值.为了帮助防止SQL注入攻击,首先?
为每个输入项生成一个以创建参数化查询.这里我假设包含你的id的数组被调用$ids
:
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
Run Code Online (Sandbox Code Playgroud)
给定三个项目的输入数组$select
将如下所示:
SELECT *
FROM galleries
WHERE id IN (?, ?, ?)
Run Code Online (Sandbox Code Playgroud)
再次注意,?
输入数组中的每个项都有一个.然后我们将使用PDO或MySQLi来准备和执行上述查询.
IN()
带字符串的运算符由于绑定参数,很容易在字符串和整数之间进行更改.对于PDO,不需要进行任何更改; 对于MySQLi str_repeat('i',
,str_repeat('s',
如果需要检查字符串,则更改为.
[1]:为简洁起见,我省略了一些错误检查.您需要检查每个数据库方法的常见错误(或将数据库驱动程序设置为抛出异常).
[2]:需要PHP 5.6或更高版本.为了简洁起见,我省略了一些错误检查.
小智 56
整型:
$query = "SELECT * FROM `$table` WHERE `$column` IN(".implode(',',$array).")";
Run Code Online (Sandbox Code Playgroud)
字符串:
$query = "SELECT * FROM `$table` WHERE `$column` IN('".implode("','",$array)."')";
Run Code Online (Sandbox Code Playgroud)
Ava*_*ava 28
假设你事先正确消毒你的输入......
$matches = implode(',', $galleries);
Run Code Online (Sandbox Code Playgroud)
然后只需调整您的查询:
SELECT *
FROM galleries
WHERE id IN ( $matches )
Run Code Online (Sandbox Code Playgroud)
根据您的数据集适当地引用值.
Mat*_*hen 11
使用:
select id from galleries where id in (1, 2, 5);
Run Code Online (Sandbox Code Playgroud)
一个简单的for each
循环将起作用.
Flavius/AvatarKava的方式更好,但要确保没有数组值包含逗号.
小智 9
正如Flavius Stef的回答,您可以使用intval()
以确保所有id
都是int值:
$ids = join(',', array_map('intval', $galleries));
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
Run Code Online (Sandbox Code Playgroud)
小智 8
对于具有转义功能的MySQLi:
$ids = array_map(function($a) use($mysqli) {
return is_string($a) ? "'".$mysqli->real_escape_string($a)."'" : $a;
}, $ids);
$ids = join(',', $ids);
$result = $mysqli->query("SELECT * FROM galleries WHERE id IN ($ids)");
Run Code Online (Sandbox Code Playgroud)
对于准备好声明的PDO:
$qmarks = implode(',', array_fill(0, count($ids), '?'));
$sth = $dbh->prepare("SELECT * FROM galleries WHERE id IN ($qmarks)");
$sth->execute($ids);
Run Code Online (Sandbox Code Playgroud)
我们应该注意SQL注入漏洞和空条件.我打算如下处理.
对于纯数字数组,使用适当类型的转换即intval
或floatval
或doubleval
在每个元件.对于字符串类型mysqli_real_escape_string()
,如果您愿意,也可以应用于数值.MySQL允许数字和日期变体作为字符串.
要在传递给查询之前适当地转义值,请创建一个类似于的函数:
function escape($string)
{
// Assuming $db is a link identifier returned by mysqli_connect() or mysqli_init()
return mysqli_real_escape_string($db, $string);
}
Run Code Online (Sandbox Code Playgroud)
这样的功能很可能已经在您的应用程序中可用,或者您已经创建了一个.
清理字符串数组,如:
$values = array_map('escape', $gallaries);
Run Code Online (Sandbox Code Playgroud)
的数字数组可以使用消毒intval
或floatval
或doubleval
代替作为合适的:
$values = array_map('intval', $gallaries);
Run Code Online (Sandbox Code Playgroud)
然后最后构建查询条件
$where = count($values) ? "`id` = '" . implode("' OR `id` = '", $values) . "'" : 0;
Run Code Online (Sandbox Code Playgroud)
要么
$where = count($values) ? "`id` IN ('" . implode("', '", $values) . "')" : 0;
Run Code Online (Sandbox Code Playgroud)
由于数组有时也可能是空的,$galleries = array();
因此我们应该注意IN ()
不允许空列表.也可以使用OR
,但问题仍然存在.所以上面的检查,count($values)
是确保相同的.
并将其添加到最终查询:
$query = 'SELECT * FROM `galleries` WHERE ' . $where;
Run Code Online (Sandbox Code Playgroud)
提示:如果要在空数组的情况下显示所有记录(无过滤)而不是隐藏所有行,只需在三元组的false部分中将0替换为1即可.
没有 PDO 的安全方法:
$ids = array_filter(array_unique(array_map('intval', (array)$ids)));
if ($ids) {
$query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
}
Run Code Online (Sandbox Code Playgroud)
(array)$ids
将$ids
变量转换为数组array_map
将所有数组值转换为整数array_unique
删除重复值array_filter
删除零值implode
将所有值加入 IN 选择小智 5
更安全.
$galleries = array(1,2,5);
array_walk($galleries , 'intval');
$ids = implode(',', $galleries);
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
Run Code Online (Sandbox Code Playgroud)
如果我们正确地过滤输入数组,我们可以使用这个"WHERE id IN"子句.像这样的东西:
$galleries = array();
foreach ($_REQUEST['gallery_id'] as $key => $val) {
$galleries[$key] = filter_var($val, FILTER_SANITIZE_NUMBER_INT);
}
Run Code Online (Sandbox Code Playgroud)
如下例所示:
$galleryIds = implode(',', $galleries);
Run Code Online (Sandbox Code Playgroud)
即现在你应该安全使用 $query = "SELECT * FROM galleries WHERE id IN ({$galleryIds})";
Col. Shrapnel的PHP SafeMySQL库在其参数化查询中提供了带类型提示的占位符,并包括几个方便的用于处理数组的占位符。该?a
占位符膨胀出的阵列,以逗号分隔的转义字符串*的列表。
例如:
$someArray = [1, 2, 5];
$galleries = $db->getAll("SELECT * FROM galleries WHERE id IN (?a)", $someArray);
Run Code Online (Sandbox Code Playgroud)
*请注意,由于MySQL执行自动类型强制,因此SafeMySQL将上面的id转换为字符串并不重要-您仍将获得正确的结果。
归档时间: |
|
查看次数: |
535096 次 |
最近记录: |