【问题标题】:Not adding 1, but 2, 3 or 4 when UPDATEing mysql with PHP使用 PHP 更新 mysql 时不加 1,而是加 2、3 或 4
【发布时间】:2014-12-29 21:42:05
【问题描述】:

我有这张表叫classes:

+------------+----------+------+-----+----------------+
| Field      | Type     | Null | Key | Extra          |
+------------+----------+------+-----+----------------+
| class_id   | int(3)   | NO   | PRI | auto_increment |
| class_level| int(1)   | YES  |     |                |
| class_name | char(1)  | YES  |     |                |
+------------+----------+------+-----+----------------+

里面的数据是这样的:

+----------+-------------+------------+
| class_id | class_level | class_name |
+----------+-------------+------------+
| 1        | 0           | N          |
| 2        | 1           | A          |
| 3        | 1           | B          |
| 4        | 2           | C          |
| 5        | 2           | D          |
| 6        | 3           | E          |
| 7        | 3           | F          |
+----------+-------------+------------+

使用 PHP,我想增加 class_level 内的所有值,但 0 除外。 所以我做了这个 PHP/MySQL 函数:

mysql_query("UPDATE classes SET class_level = (class_level + 1) WHERE class_level != 0") or die(mysql_error());

这(奇怪的是)不会给每个class_level 加1,除了等于0 之外,而是加2 或3 或4!我还没有找到一个规则,这个脚本会添加 2 或 3 或 4。这是随机选择的。也没有输出错误。

它所做的一切都是随机添加 2 或 3 或 4 到每一行。

所以,为了调试它,我做了这个 PHP 代码来一一添加:

$query = mysql_query("SELECT * FROM `classes` WHERE `class_level` != 0");

while ($row = mysql_fetch_assoc($query)) {
    $class_id = $row['class_id'];

    $class_level = $row['class_level'];
    $class_level = $class_level + 1;
    var_dump($class_level);

    mysql_query("UPDATE `classes` SET `class_level` = '$class_level' WHERE `class_id` = '$class_id'") or die(mysql_error());
}

var_dump 的输出是:

int(2) int(2) int(3) int(3) int(4) int(4)

但在表中的数据库中,我得到以下结果:

+----------+-------------+------------+
| class_id | class_level | class_name |
+----------+-------------+------------+
| 1        | 0           | N          |
| 2        | 4           | A          |
| 3        | 4           | B          |
| 3        | 5           | C          |
| 4        | 5           | D          |
| 5        | 6           | E          |
| 6        | 6           | F          |
+----------+-------------+------------+

这是一个空文件,只有 MySQL 连接和上面的代码,所以上面没有循环。

这是我的版本信息:PHP 版本:5.2.12,MySQL Client API 版本 5.1.44。请注意,我无法安装 mysqli 或 PDO。

编辑:

在执行 MySQL 查询后,我从表中输出了数据,结果应该是这样。但是在表本身(或仅用于输出的代码刷新)中添加了 3 个,而不是 1 个!

编辑 2:

我尝试从命令行(又名用于 SQL 命令的 Webmin 工具)执行这个 MySQL 查询,结果应该是:添加了 1。

【问题讨论】:

  • don't use mysql_* functions 使用新代码。它们不再被维护并且是officially deprecated。改为了解prepared statements,并使用PDOMySQLi
  • 听起来你的脚本被执行了多次。你在使用url重写吗?也许像favicon.ico 这样的请求会被重写到您的脚本中。
  • 看起来你的UPDATE/loop 嵌套在一个外部循环中,所以它被运行了多次。
  • 1.我既不能使用 mysqli 也不能使用 PDO,因为它不是我的服务器,我不能在上面安装任何东西。 2.它不在ANY循环中,因为它是一个空文件,只有这段代码和与mysql的连接
  • 如果你有时间看看尝试使用redbeanphp.com。这很简单。你不应该考虑 pdo ,mysql ,mysqli 它会处理一切。

标签: php mysql sql-update add


【解决方案1】:

编辑

已添加SQL Fiddle demonstration: http://sqlfiddle.com/#!9/efa05b/1

create table classes 
( class_id    int(3) not null auto_increment primary key comment 'pk'
, class_level int(1)
, class_name  char(1)
)
;
insert into classes (class_id,class_level,class_name) values
 ('1','0','N')
,('2','1','A')
,('3','1','B')
,('4','2','C')
,('5','2','D')
,('6','3','E')
,('7','3','F')
;
update classes set class_level = (class_level + 1) where class_level != 0
;

查询验证是否返回了预期结果。每行(class_level=0 除外)都已更新,class_level 恰好递增 1。

select * from classes order by class_id

class_id class_level class_name
-------- ----------- ----------
1        0           N
2        2           A
3        2           B
4        3           C
5        3           D
6        4           E
7        4           F

原始答案

假设正在执行的 SQL 语句,表上没有 BEFORE/AFTER UPDATE 触发器:

UPDATE classes SET class_level = (class_level + 1) WHERE class_level != 0

对该行为最合乎逻辑的解释是该SQL语句在函数内被多次执行,或者该函数被多次调用。

要验证这一点,您可以暂时打开 MySQL 常规日志,运行测试,禁用常规日志,然后查看……您会发现该语句的多次执行。如果您无权访问 MySQL 服务器,那么最好在语句执行之前立即回显一行;你会看到那条线重复了很多次。

这极不可能是 MySQL 数据库中的错误。 (验证表上没有定义 TRIGGER。)

另外,使用不同的客户端测试该语句,例如客户端或 phpmyadmin 之类的 mysql 命令。并验证语句是否正常工作。


跟进

鉴于您从不同客户端对 SQL 语句的测试给出了预期结果,我认为这表明这不是 MySQL 数据库或 SQL 语句的问题。

由于某种原因,该 SQL 语句被多次执行。作为调试的下一步,我将添加更多代码。我会使用 MyISAM 引擎临时创建一个“日志”表,其中包含一个 auto_increment id、一个日期时间列和一个信息字符串:

 CREATE TABLE debug_log
 ( id   INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
 , dt   DATETIME
 , info VARCHAR(40)
 ) Engine=MyISAM

然后在您的函数中添加另一个 SQL 语句,以便在执行 UPDATE 语句之前和/或之后立即向该表插入一行

INSERT INTO debug_log (dt, info) VALUES (SYSDATE(), 'my function before update')

然后,运行测试,看看有多少行被插入到 debug_log 表中。

要在此语句执行多次时引发错误,请为 id 列提供一个固定值,例如

INSERT INTO debug_log (id, dt, info) 
VALUES (123, SYSDATE(), 'my function before update')

使用固定的 id 值,如果该语句被第二次调用,那么 MySQL 将抛出重复键异常。

正如我之前提到的,根据提供的信息,我怀疑您的函数被多次调用。 (我没有足够的信息来做出这个决定;这只是一种预感。)

【讨论】:

  • 回显'1'; mysql_query ...;回声“2”;输出: 12 ,所以它肯定不会循环。关于mysql的通用日志我会尝试,但是由于管理员的原因很难访问服务器文件...
  • 用 WEBMIN 工具(又名命令行)对其进行了测试,结果应该是这样。只添加了 1.. 另请参阅我的问题中的新编辑部分。
  • 如前所述,SQL 很好,通过命令行可以完美运行。唯一的问题是 PHP 执行它。我假设这个 mysql_ PHP 库中有一个错误,虽然它非常奇怪,不是吗?
【解决方案2】:

下面是简单的解决方案

<?php
  print("<h1>BEFORE</h1>");
  $q =mysql_query("select *from classes ");
  while($row=mysql_fetch_array($q)){
  print("$row['class_id'] - $row['class_level'] - row[$class_name] <br/>");
  }

 mysql_query("UPDATE classes SET class_level = class_level+1 WHERE class_level>0") or die(mysql_error()); 


 print("<h1>AFTER</h1>");

  $q =mysql_query("select *from classes ");
  while($row=mysql_fetch_array($q)){
  print("$row['class_id'] - $row['class_level'] - row[$class_name] <br/>");
  }


?>

你不需要编写任何一个 php 行来做你真正想做的事情。

好的,我已经更新了代码尝试这种方式。首先它将获取数据并显示。其次,它会更新数据。最后,显示数据。试试这个方法希望你能找到你的问题。

【讨论】:

  • 检查问题中的第一行代码。这正是 OP 正在做的事情。
  • 我已经做到了,它也是如此。我写道,PHP 代码只是为了调试!
  • 好吧。看来你可能会刷新不止一次
  • 每次我尝试刷新 3 次?
  • 可以试试我给你的新代码。它将为您提供实际的调试场景。
【解决方案3】:

我通过简单地做这样的事情来解决这个问题:

mysql_query("UPDATE classes SET class_level = 2 WHERE class_level = 1");
mysql_query("UPDATE classes SET class_level = 3 WHERE class_level = 2");
mysql_query("UPDATE classes SET class_level = 4 WHERE class_level = 3");

我只有这三个类,所以它可以完成工作。

这不是我想要的方式,但它确实有效。这个错误真的很奇怪,我宁愿不回去。我希望这对某人有所帮助。


附:一开始我怎么可能没想到呢XD

【讨论】:

    猜你喜欢
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多