PDO 等效于 mysql_num_rows 或 mssql_num_rows [重复]
Posted
技术标签:
【中文标题】PDO 等效于 mysql_num_rows 或 mssql_num_rows [重复]【英文标题】:PDO equivalent of mysql_num_rows or mssql_num_rows [duplicate] 【发布时间】:2015-10-12 17:09:10 【问题描述】:我知道以前有人问过这个问题,但似乎解决方案是针对所提出的问题的。
我有一个代码库,其中包含数百个使用 mssql_num_rows 的实例。
代码示例:
$db->execute($sql);
if ($db->getRowsAffected() > 0)
$total = $db->fetch();
在 db 类中:
$this->rowsaffected = mssql_num_rows($this->query_result);
我无法创建通用 SELECT count(*) FROM table
查询,因为我有太多特定的选择语句。
我可以运行 preg_replace
来删除 SELECT and FROM
之间的所有内容,然后替换为 COUNT(*)
并运行第二个查询,但这假设所有查询都以某种方式设置。
我可以先fetchAll
然后count()
结果,但这意味着升级 if 语句的所有实例。
如果人们将他们的代码更新为 PDO,那么最好的替代 *_num_rows 函数的方法是什么。不是解决特定问题的东西,而是替代 *_num_rows 功能的东西。如果这是不可能的,是什么让它成为可能?
【问题讨论】:
我将它用于 INSERT、DELETE 或 UPDATE 语句。但是: PDOStatement::rowCount() 返回受相应 PDOStatement 对象执行的最后一个 DELETE、INSERT 或 UPDATE 语句影响的行数。如果关联的 PDOStatement 执行的最后一条 SQL 语句是 SELECT 语句,则某些数据库可能会返回该语句返回的行数。然而,这种行为并不能保证适用于所有数据库,并且不应依赖于可移植应用程序。 为什么需要SELECT COUNT(*)
?我看不出问题出在哪里,一旦查询完成,您就无法计算包含数据库记录的数组的大小,因为这会涉及更改太多 ifs?技术债务处于最佳状态。
@N.B.如果你总是选择最好的方法,即使需要更长的时间,你也会在其他地方浪费时间。这个系统很快就会过时。我需要一种快速替换单个功能而不是系统大修的方法。
我同意你的观点,自然是过时的系统和快速修复 - 我理解你的观点。但是,请记住,许多访问此站点的人与我们有类似的问题,并且为了未来的代码和项目 - 我们提到了最佳解决方案。通常,最佳解决方案也是实现某事的最短和最简单的方法,因此一个好主意是否也是最佳解决方案以及最短的可能方法在很大程度上取决于上下文和方法。 IMO,您提出的解决方案不是解决问题的最快方法。
我问这个特定问题的原因是为了找到一个答案,为什么没有像 *_num_rows 那样的精确解决方案。我最终确实通过杰伊布兰查德得到了答案,基本上没有等价物。到那时,问题就转移到了改变代码工作方式的最佳方法上。我希望杰伊的评论实际上是一个答案,因为我希望它位于顶部。许多人要求使用 *_num_rows 的等价物,因为他们习惯使用它,而真正的答案是没有等价物,所以这里有一些更好的编写代码的方法。
【参考方案1】:
如果您想计算行数,可以使用 PDO:
$sql = 'select * from users';
$data = $conn->query($sql);
$rows = $data->fetchAll();
$num_rows = count($rows);
如docs 中所述,使用带有 PDO 的 SELECT
语句时,无法直接计算行数。
PDOStatement::rowCount() 返回受相应的最后执行的 DELETE、INSERT 或 UPDATE 语句影响的行数PDOStatement 对象。
仅在绝对需要计数时才进行行计数,否则您可以验证查询是否与其他方法一起使用。如果您希望从表中返回数千行,则也不应使用此方法,而应在查询中使用 COUNT()
函数来执行计数。
【讨论】:
那么在以前的 mysql 连接中起作用的情况下,PDO 阻止从 SELECT 语句中计算行数的原因是什么? 这是/曾经是 php-DEV 团队一直在努力解决的问题。在大多数讨论中,计算行数不被认为是正常,因为 SQL 具有内置功能。您可以对我提供的内容进行功能化(我已经这样做了),这样您所要做的就是调用一个函数,但在大多数情况下,这将是矫枉过正。 好吧,现在你让我开始思考了。我很幸运,getrowsaffected() 函数已经存在,所以我已经内置了一段代码,删除了 SELECT 和 FROM 之间的所有内容,然后用 count(*) 替换它,然后运行它给我一个总数行使用与上一条语句相同的内容。它并不优雅,但很有效。【参考方案2】:所以在大家的帮助下,这就是我所构建的。
function getRowsAffected()
$rawStatement = explode(" ", $this->query);
$statement = strtoupper($rawStatement[0]);
if ($statement == 'SELECT' || $statement == 'SHOW')
$countQuery = preg_replace('/(SELECT|SHOW)(.*)FROM/i', "SELECT count(*) FROM", $this->query);
$countsth = $this->pdo->prepare($countQuery);
if ($countsth->execute())
$this->rowsaffected = $countsth->fetchColumn();
else
$this->rowsaffected = 0;
return $this->rowsaffected;
如果语句是带有 $sth->rowCount() 的 INSERT、UPDATE 或 DELETE,则 $this->rowsaffected 已在执行阶段更新,因此我只需要在 SELECT 和 SHOWS 上运行第二个查询。
if ($statement == 'INSERT' || $statement == 'UPDATE' || $statement == 'DELETE')
$this->rowsaffected = $this->sth->rowCount();
但我感觉很糟糕,因为正如我在问题中提到的那样,我正在寻找一个整体解决方案,但我似乎偶然发现了一个适合我的特定解决方案,因为代码已经使用功能。如果代码是这样做的:
if (mysql_num_rows($result) > 0)
那么此解决方案仍将创建更新所有实例以使用该自定义功能的工作。
【讨论】:
您的方法名称具有误导性。你为什么要数数?这太贵了。您已经收到受影响的行 - 受影响的内容是更改的内容。选择没有任何改变。此外,当您选择某物时,只需数数即可。 您显然没有正确阅读我的问题。 “我有一个代码库,其中包含数百个使用 mssql_num_rows 的实例。”我不是在尝试创建最佳方法,而是在尝试升级代码库而不必重写所有内容。我在第 3 点提到了这一点:“我可以先 fetchAll 然后 count() 结果,但这意味着升级 if 语句的所有实例。”我没有通过数小时的代码获得报酬。你真的需要回去再读一遍这个问题。 我在评论您的解决方案,而不是您提出它的原因。我理解你的推理,你在那部分是正确的。但是,当我评论您的解决方案时,您不能不同意我的看法。如果您必须从头开始一个项目,您会使用这种方法还是想出一些更简单且更有意义的方法?如果您以任何方式受到冒犯,我很抱歉,但我不会对您个人、您的能力、技能或任何其他财产发表评论。我评论代码和方法,我坚持我的话。我会和你争论,正确的方法会减少工作量。 解决方案不仅仅是最适合代码的方法。我正在查看大约 250 个调用此 getrowsaffected 函数的实例,我想创建一个可以放入该函数的解决方案,而不必在它所在的任何地方进行更新。该函数内部最初是一个 mssql_num_rows 调用,我想替换它,因此我不必花费数小时替换每个引用 getrowsaffected 的 if 语句。 回复:误导性名称。我从来没有命名这个函数,我同意这是一个误导性的名字。它最初用于插入和选择样式查询,所以我认为他们将其命名并仅用于两者。以上是关于PDO 等效于 mysql_num_rows 或 mssql_num_rows [重复]的主要内容,如果未能解决你的问题,请参考以下文章
旧 mysql 函数的 PDO 等价物,如 fetch assoc [重复]
pdo 相对于 mysql_* 或 mysqli_* 的优势 [重复]
SQLite 等效于 ISNULL()、NVL()、IFNULL() 或 COALESCE()