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

2024-09-29 23:09:00
admin
原创
92
摘要:问题描述:这是我的代码的快照:$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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用