如何在 LIMIT 子句中应用 bindValue 方法?

2024-09-29 23:09:00
admin
原创
176
摘要:问题描述:这是我的代码的快照:$fetchPictures = $PDO->prepare("SELECT * FROM pictures WHERE album = :albumId ORDER BY id ASC LIMIT :skip, :...

问题描述:

这是我的代码的快照:

$fetchPictures = $PDO->prepare("SELECT * 
    FROM pictures 
    WHERE album = :albumId 
    ORDER BY id ASC 
    LIMIT :skip, :max");

$fetchPictures->bindValue(':albumId', $_GET['albumid'], PDO::PARAM_INT);

if(isset($_GET['skip'])) {
    $fetchPictures->bindValue(':skip', trim($_GET['skip']), PDO::PARAM_INT);    
} else {
    $fetchPictures->bindValue(':skip', 0, PDO::PARAM_INT);  
}

$fetchPictures->bindValue(':max', $max, PDO::PARAM_INT);
$fetchPictures->execute() or die(print_r($fetchPictures->errorInfo()));
$pictures = $fetchPictures->fetchAll(PDO::FETCH_ASSOC);

我明白了

您的 SQL 语法有错误;请查阅与您的 MySQL 服务器版本相对应的手册,以了解在第 1 行 ''15', 15' 附近使用的正确语法

似乎 PDO 在 SQL 代码的 LIMIT 部分为我的变量添加了单引号。我查找了一下,发现了这个我认为相关的错误:
http://bugs.php.net/bug.php ?id=44639

这就是我所看到的吗?这个错误自 2008 年 4 月以来就一直存在!我们在此期间应该做什么?

我需要建立一些分页,并且在发送 SQL 语句之前需要确保数据是干净的、SQL 注入安全的。


解决方案 1:

我记得以前遇到过这个问题。将值转换为整数,然后再将其传递给 bind 函数。我认为这可以解决问题。

$fetchPictures->bindValue(':skip', (int) trim($_GET['skip']), PDO::PARAM_INT);

解决方案 2:

最简单的解决方案是关闭模拟模式。只需添加以下行即可

$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

此外,创建 PDO 连接时可以将此模式设置为构造函数参数。这可能是一个更好的解决方案,因为有些人报告他们的驱动程序不支持该setAttribute()功能。

它不仅可以解决绑定问题,还可以让你直接将值发送到execute(),这将大大缩短你的代码。假设已经设置了模拟模式,整个过程将需要多达六行代码

$skip = isset($_GET['skip']) ? (int)trim($_GET['skip']) : 0;
$sql  = "SELECT * FROM pictures WHERE album = ? ORDER BY id LIMIT ?, ?";
$stmt  = $PDO->prepare($sql);
$stmt->execute([$_GET['albumid'], $skip, $max]);
$pictures = $stmt->fetchAll(PDO::FETCH_ASSOC);

解决方案 3:

查看错误报告,以下内容可能有效:

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

$fetchPictures->bindValue(':skip', (int)trim($_GET['skip']), PDO::PARAM_INT);  

但您确定传入的数据正确吗?因为在错误消息中,数字后面似乎只有一个引号(而不是整个数字都括在引号中)。这也可能是传入数据有误。您可以执行操作print_r($_GET);来找出原因吗?

解决方案 4:

这只是总结。

有四个选项可以参数化 LIMIT/OFFSET 值:

  1. PDO::ATTR_EMULATE_PREPARES按照上面所述禁用。

这会阻止传递的值->execute([...])始终显示为字符串。

  1. 切换到手动->bindValue(..., ..., PDO::PARAM_INT)参数填充。

但是它不如 ->execute list[] 方便。

  1. 只需在这里做出例外,并在准备 SQL 查询时插入纯整数即可。

 $limit = intval($limit);
 $s = $pdo->prepare("SELECT * FROM tbl LIMIT {$limit}");

选角很重要。通常->prepare(sprintf("SELECT ... LIMIT %d", $num))用于此类目的。

  1. 如果您不使用 MySQL,而是使用 SQLite 或 Postgres;您也可以直接在 SQL 中转换绑定参数。

 SELECT * FROM tbl LIMIT (1 * :limit)

再次强调,MySQL/MariaDB 不支持 LIMIT 子句中的表达式。目前还不支持。

解决方案 5:

为了LIMIT :init, :end

您需要以那种方式进行绑定。如果您有类似的东西$req->execute(Array());,它将无法工作,因为它将转换PDO::PARAM_STR为数组中的所有变量,并且LIMIT您绝对需要一个 Integer。bindValue 或 BindParam 随你便。

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

解决方案 6:

由于没有人解释为什么会发生这种情况,所以我要添加一个答案。它之所以出现这种情况,是因为您正在使用trim()。如果您查看 PHP 手册trim,返回类型是string。然后您尝试将其作为传递PDO::PARAM_INT。解决此问题的几种方法是:

  1. 用于filter_var($integer, FILTER_VALIDATE_NUMBER_INT)确保您传递的是一个整数。

  2. 正如其他人所说,使用intval()

  3. 铸造(int)

  4. 检查它是否是一个整数is_int()

还有很多方法,但这基本上是根本原因。

解决方案 7:

使用 PDO::PARAM_INT 绑定值偏移和限制,它将起作用

解决方案 8:

//之前(当前错误)$query = " .... LIMIT :p1, 30;"; ... $stmt->bindParam(':p1', $limiteInferior);

//AFTER(错误已更正)$query = " .... LIMIT :p1, 30;"; ... $limiteInferior = (int)$limiteInferior; $stmt->bindParam(':p1', $limiteInferior, PDO::PARAM_INT);

解决方案 9:

PDO::ATTR_EMULATE_PREPARES给了我

驱动程序不支持该功能:该驱动程序不支持设置属性的错误。

我的解决方法是将变量设置$limit为字符串,然后将其组合到准备语句中,如下例所示:

$limit = ' LIMIT ' . $from . ', ' . $max_results;
$stmt = $pdo->prepare( 'SELECT * FROM users WHERE company_id = :cid ORDER BY name ASC' . $limit . ';' );
try {
    $stmt->execute( array( ':cid' => $company_id ) );
    ...
}
catch ( Exception $e ) {
    ...
}

解决方案 10:

不同版本的 PHP 和 PDO 之间存在很多问题。我尝试了 3 或 4 种方法,但无法使 LIMIT 正常工作。

我的建议是使用字符串格式化/连接和intval()过滤器:

$sql = 'SELECT * FROM `table` LIMIT ' . intval($limitstart) . ' , ' . intval($num).';';

使用 intval() 来防止 SQL 注入非常重要,特别是当您从 $_GET 或类似方法获取限制时。 如果您这样做,这是使 LIMIT 正常工作的最简单方法。

关于“PDO 中的 LIMIT 问题”有很多讨论,但我的想法是,PDO 参数从未用于 LIMIT,因为它们始终是整数,快速过滤器可以工作。不过,这有点误导,因为哲学一直是不要自己做任何 SQL 注入过滤,而是“让 PDO 处理它”。

解决方案 11:

请尝试以下操作:

$sql2 = "SELECT  * FROM tab ORDER BY id DESC limit 2
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1041  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   34  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   31  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   23  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   26  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用