“违反完整性约束:1062 重复条目”-但没有重复行

Posted

技术标签:

【中文标题】“违反完整性约束:1062 重复条目”-但没有重复行【英文标题】:"Integrity constraint violation: 1062 Duplicate entry" - but no duplicate rows 【发布时间】:2014-12-17 16:05:15 【问题描述】:

我正在将应用程序从本地 mysqli 调用转换为 PDO。尝试将行插入具有外键约束的表时遇到错误。

注意:这是一个简化的测试用例,不应复制/粘贴到生产环境中。

信息 php 5.3、MySQL 5.4

首先,这是表格:

CREATE TABLE `z_one` (
  `customer_id` int(10) unsigned NOT NULL DEFAULT '0',
  `name_last` varchar(255) DEFAULT NULL,
  `name_first` varchar(255) DEFAULT NULL,
  `dateadded` datetime DEFAULT NULL,
  PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `z_one` VALUES (1,'Khan','Ghengis','2014-12-17 10:43:01');

CREATE TABLE `z_many` (
  `order_id` varchar(15) NOT NULL DEFAULT '',
  `customer_id` int(10) unsigned DEFAULT NULL,
  `dateadded` datetime DEFAULT NULL,
  PRIMARY KEY (`order_id`),
  KEY `order_index` (`customer_id`,`order_id`),
  CONSTRAINT `z_many_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `z_one` (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

或者如果你愿意,

mysql> describe z_one;
+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| customer_id | int(10) unsigned | NO   | PRI | 0       |       |
| name_last   | varchar(255)     | YES  |     | NULL    |       |
| name_first  | varchar(255)     | YES  |     | NULL    |       |
| dateadded   | datetime         | YES  |     | NULL    |       |
+-------------+------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)


mysql> describe z_many;
+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| order_id    | varchar(15)      | NO   | PRI |         |       |
| customer_id | int(10) unsigned | YES  | MUL | NULL    |       |
| dateadded   | datetime         | YES  |     | NULL    |       |
+-------------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

接下来,这里是查询:

    $order_id = '22BD24';
    $customer_id = 1;

    try 
    
        $q = "
            INSERT INTO 
                z_many 
                (
                    order_id,
                    customer_id,
                    dateadded
                )
            VALUES 
                (
                    :order_id,
                    :customer_id,
                    NOW()
                )
        ";
        $stmt = $dbx_pdo->prepare($q);
        $stmt->bindValue(':order_id', $order_id, PDO::PARAM_STR);
        $stmt->bindValue(':customer_id', $customer_id, PDO::PARAM_INT);
        $stmt->execute();

     catch(PDOException $err) 
        // test case only.  do not echo sql errors to end users.
        echo $err->getMessage();
       

这会导致以下 PDO 错误:

SQLSTATE[23000]:违反完整性约束:1062 重复条目 键 'PRIMARY' 的 '22BD24'

mysqli 处理相同的查询可以正常工作。当没有找到任何重复项时,为什么 PDO 会拒绝带有“重复条目”消息的 INSERT?

【问题讨论】:

您的支票是多余的。除了为主键选择错误的数据类型外,您不必检查是否存在具有特定 id 的订单。你可以插入。如果插入失败,则检查它是否因为违反完整性约束而失败,这意味着具有该 PK 的记录存在。 @Pow-lan 那是 SQL DDL,与 PDO 无关。 @Pow-lan KEYINDEX 在 MySQL 中是同义词。在任何情况下,它都不是 unique 约束,因此不太可能与此错误有关。 在网络服务器之外运行代码和/或添加一些调试输出(到日志文件,而不是 echo 等)。我很确定插入被执行了两次。 所以我想对此进行测试并复制 sql 以创建一个表,在 phpmyadmin 中运行它并准确复制代码。添加了一行以创建新的 pdo 连接,其他所有内容都复制/粘贴完全相同。运行页面,它按预期创建了一行,没有错误。刷新并得到与预期相同的完整性约束错误。这是 php 5.4.12 和 mysql 5.6。所以像大多数其他人一样,我会回去检查它是否不止一次运行。该页面是否包含在另一个脚本中?这是在函数中还是从框架中调用? 【参考方案1】:

由于并非所有代码都可用(从 php 端),以防万一您的查询处于某种循环中,因此最快(可能是部分)解决方案如下:

$order_id = '22BD24';
$customer_id = 1;

try 
    $q = "INSERT INTO `z_many` (`order_id`,`customer_id`,`dateadded`)
        VALUES (:order_id,:customer_id,NOW())
        ON DUPLICATE KEY UPDATE `dateadded`=NOW()";

    $stmt = $dbx_pdo->prepare($q);
    $stmt->bindValue(':order_id', $order_id, PDO::PARAM_STR);
    $stmt->bindValue(':customer_id', $customer_id, PDO::PARAM_INT);
    $stmt->execute();

 catch(PDOException $err) 

    // test case only.  do not echo sql errors to end users.
    echo $err->getMessage();


【讨论】:

【参考方案2】:

我已经复制了您在我的 mysql DB 上提供的 SQL 模式并添加了脚本代码,但在开始时使用了 PDO 初始化: $dbx_pdo = new PDO('mysql:host=127.0.0.1;dbname=test12;charset=utf8','root','');

.. 它工作正常,但我的设置是 php 5.5.9 和 mysql 5.6.16

所以我认为您的代码执行了两次,并且可能是在事务内部,所以您会得到回滚。需要了解更多上下文

【讨论】:

hm,然后我需要在日志文件中添加更多调试输出。我没有看到任何证据表明此页面可能会重新加载,但我会找出并更新。【参考方案3】:

请删除主键列的默认值。也使用构造

INSERT INTO (`field1`, `field2`, `...`) values (val1, val2, val3);

如果您告诉插入的默认值是什么 - 某些 mysql 版本在插入时会出现错误。这就是为什么你应该使用自动增量或根本不使用默认值。

【讨论】:

【参考方案4】:

只是在黑暗中拍摄。我仅通过 bindParam() 将 PDO 与 ORACLE PL/SQL 一起使用。如果它是PARAM_STR 值,请查看第四个参数,15。所以试试这个,希望它有帮助。

   $stmt->bindParam(':order_id', $order_id, PDO::PARAM_STR, 15);
   $stmt->bindParam(':customer_id', $customer_id, PDO::PARAM_INT);

这 15 描述了您表中 order_id 的(缓冲)长度。

【讨论】:

以上是关于“违反完整性约束:1062 重复条目”-但没有重复行的主要内容,如果未能解决你的问题,请参考以下文章

Gradle“条目.classpath是重复的,但没有设置重复处理策略”

Selenium 尽管没有使用或调用 WebElement,但没有此类元素异常 [重复]

我的 SonarQube C++ 扫描成功,但结果只标记重复,没有其他标记

没有抛出错误,但数据没有插入数据库(PHP PDO)[重复]

Django重定向:没有错误,但没有重定向[重复]

个别情节有效,但一旦添加子情节,啥都没有出现[重复]