为什么INSERT ... ON DUPLICATE KEY UPDATE为MySQL中的键'PRIMARY'提供重复条目'x'?

时间:2016-08-04 22:59:28

标签: php mysql database pdo

我有一个表格,我正在从LDAP / AD导入数千个用户帐户,如果发现有重复,则希望它更新它们。我使用自动递增的代理键作为主键,Domain和Username作为唯一键索引。主键用作另一个表中的外键。此外,此表包含Locations表中的外键。

我已经做了大量的阅读和试​​错,试图让MySQL INSERT ... ON DUPLICATE KEY UPDATE语法工作,但没有成功。每次我尝试它,我得到相同的结果(密钥递增):重复条目'27305'键'PRIMARY'。请注意,表中没有带此键的条目。

我正在使用MySQL 5.6.30和PHP 5.6.21。

这是表结构:

- 表users

的表结构
CREATE TABLE `users` (
`Userid` bigint(20) UNSIGNED NOT NULL,
`Domain` varchar(17) NOT NULL,
`Username` varchar(25) NOT NULL,
`Firstname` varchar(25) DEFAULT NULL,
`Lastname` varchar(35) DEFAULT NULL,
`Realname` varchar(60) DEFAULT NULL,
`Dept` varchar(10) DEFAULT NULL,
`Email` varchar(50) DEFAULT NULL,
`Site` varchar(3) DEFAULT NULL,
`Location` bigint(20) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `users`
ADD PRIMARY KEY (`Userid`),
ADD UNIQUE KEY `Domain` (`Domain`,`Username`) USING BTREE,
ADD KEY `Realname` (`Realname`,`Dept`) USING BTREE,
ADD KEY `Email` (`Email`),
ADD KEY `Location` (`Location`),
ADD KEY `Firstname` (`Firstname`,`Lastname`,`Dept`) USING BTREE,
ADD KEY `Firstname_2` (`Firstname`,`Lastname`,`Location`);

ALTER TABLE `users`
MODIFY `Userid` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
AUTO_INCREMENT=27306;

ALTER TABLE `users`
ADD CONSTRAINT `Location_fk` FOREIGN KEY (`Location`) REFERENCES `locations`  
(`Locid`) ON UPDATE CASCADE;

这是我根据PHP的插入语句:

INSERT INTO `users` (`Domain`, `Username`, `Firstname`, `Lastname`,
`Realname`, `Dept`, `Email`, `Site`, `Location`) VALUES ('americas',
'JACLEAR', 'Foo', 'Bar', 'Foo Bar', 'IT', 'jlear@t-systems.com', '165', '0')
ON DUPLICATE KEY UPDATE `Userid`=LAST_INSERT_ID(`Userid`),
`Domain`=`Domain`, `Username`=`Username`, `Firstname`=VALUES(`Firstname`),
`Lastname`=VALUES(`Lastname`), `Realname`=VALUES(`Realname`),
`Dept`=VALUES(`Dept`), `Email`=VALUES(`Email`), `Site`=VALUES(`Site`),
`Location`=VALUES(`Location`);

同样,我尝试在insert语句中更改了几个东西,但它总是产生相同的错误。我已经尝试过诸如从语句的更新部分删除主键和唯一键,从唯一键中删除VALUES,从主键中删除LAST_INSERT_ID等等。我尝试将语句直接粘贴到SQL控制台但是没有'得到任何更有用的输出 - 它返回相同的消息:重复条目'27305'关键'PRIMARY'

由于在SQL控制台上运行语句返回了相同的错误,我认为它与PHP没有任何关系。我要提到我正在使用PDO-> prepare()和PDOStatement-> execute()。

看起来我必须根据SELECT结果执行SELECT然后INSERT或UPDATE,除非有人能看到我做错了什么。但这会使脚本的效率降低很多。

任何帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:1)

这是罪魁祸首:

`Userid`=LAST_INSERT_ID(`Userid`)

你不应该在这里有这个条款。此语句中的LAST_INSERT_ID()是成功执行的上一个插入语句的last_insert_id。如果不存在此类陈述。它将为零。

简而言之,mysql正在为域列找到重复内容,尝试进行更新,而更新会导致主键重复。

答案 1 :(得分:0)

我尝试在没有“ON DUPLICATE KEY UPDATE”的情况下进行INSERT,并且MySQL响应了一个实际指向REAL问题的有用错误。它告诉我,我为外键(位置)插入的值是'违规'。这种情况就是这样,因为Location表中没有关键字0的记录。我更新了我的示例插入以使用有效的Location外键并且工作正常。更新成功。

简而言之,请确保插入有效值! ;)