Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 神秘的插入更新错误_Php_Mysql - Fatal编程技术网

Php 神秘的插入更新错误

Php 神秘的插入更新错误,php,mysql,Php,Mysql,我有一个表,看起来像是减去了不相关的列: PRIMARY KEY(AUTO-INCREMENT,INT), CLIENTID(INT), CLIENTENTRYID(INT), COUNT1(INT), COUNT2(INT) 现在,CLIENTID和CLIENTENTRYID是一个独特的组合索引,用于防止重复 我使用PHP post输入到服务器。我的查询如下所示: $stmt = $sql->prepare('INSERT INTO table (COUNT1,COUNT2,C

我有一个表,看起来像是减去了不相关的列:

PRIMARY KEY(AUTO-INCREMENT,INT), 
CLIENTID(INT), 
CLIENTENTRYID(INT), 
COUNT1(INT), 
COUNT2(INT)
现在,CLIENTID和CLIENTENTRYID是一个独特的组合索引,用于防止重复

我使用PHP post输入到服务器。我的查询如下所示:

$stmt = $sql->prepare('INSERT INTO table (COUNT1,COUNT2,CLIENTID,CLIENTENTRYID) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE COUNT1=VALUES(COUNT1),COUNT2=VALUES(COUNT2)');

$stmt->bind_param("iiii",$value,$value,$clientid,$cliententryid);
SQL对象已启用自动提交。值变量被重用为COUNT1中的值,COUNT2应始终相同

好的-大多数情况下,这很好,但是随机的,我不知道为什么,它会在COUNT2中发布0-对于一个完全不同的行

你知道怎么会这样吗?我看不到一个模式,它在一次失败的尝试后不会发生,这就是唯一索引存在的原因,这样一次新的尝试就不会导致重复。这似乎是完全随机的

在重复密钥更新中是否有我误解的地方?非常奇怪的是,它错误地更新了另一行,而不是您插入的那一行


我意识到其他因素可能会影响这一点,但现在我试图排除我的SQL逻辑作为错误源的可能性。

我认为问题在于您正在使用UPDATE COUNT1=valuescont1、COUNT2=valuescont2中的值尝试这样使用 在重复密钥更新时,COUNT1=$v1,COUNT2=$v2

看看MySQL,它说给定一个insert语句

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
如果列a和b是唯一的,则insert相当于update语句,其中WHERE子句包含OR而不是and:

引用文件中的话

如果a=1或b=2匹配多行,则只更新一行。在里面 一般情况下,应尽量避免使用重复密钥更新 子句,用于具有多个唯一索引的表

希望这有帮助

更新:


根据进一步的讨论,OP将考虑。OP还有另一个具有类似多个唯一索引规范的表,但通过使用INSERT IGNORE没有相同的问题。

除了自动增量列上的主键之外,表中只定义了一个唯一键,这是在CLIENTID、CLIENTENTRYID上定义的,对吗

表上没有定义触发器,对吗

显然,您使用的是带有绑定占位符的预处理语句

这两列CLIENTID和CLIENTENTRYID是否定义为NOTNULL并不重要;MySQL将允许多行具有空值;这不会违反由唯一约束强制的唯一性。这与Oracle处理空值唯一性的方式相同,但与SQL Server强制执行空值唯一性的方式不同

我只是看不出你的陈述有什么不同,那就是:

INSERT INTO `mytable` (COUNT1,COUNT2,CLIENTID,CLIENTENTRYID) VALUES (?,?,?,?)
ON DUPLICATE KEY 
UPDATE COUNT1 = VALUES(COUNT1)
     , COUNT2 = VALUES(COUNT2)
。。。这不会导致表中的其他行被更新

要么插入操作成功,要么引发重复密钥异常。如果引发重复密钥异常,则语句将捕获该异常,并执行更新操作

鉴于CLIENTID、CLIENTENTRYID是表上除auto_increment列之外的唯一唯一键,且未被此语句引用,更新操作将等效于此语句:

UPDATE `mytable`
   SET COUNT1        = ?
     , COUNT2        = ?
 WHERE CLIENTID      = ?
   AND CLIENTENTRYID = ?
。。。使用INSERT语句的values子句中提供的值

总之,OP向我们展示的任何东西都没有问题。逻辑是正确的。除了这个SQL语句之外,还有其他一些事情在进行

OP代码显示为在bind_param调用中使用标量而不是数组元素作为参数,所以通过引用传递的混乱性不应该成为问题

根据OP告诉我们和展示给我们的一切,OP展示的SQL语句没有问题。报告的问题必须不是SQL语句。

我找到了答案

这里的每个人都正确地指出,这是另一回事。出于某种完全奇怪的原因,我用来打开“添加新条目”的按钮在与按钮无关的表视图中的选定对象上以某种方式发布,以设置Arrized=0

这一定是我故事板中某个地方的UI链接


对不起,我浪费了你们这么多时间。至少我学到了一些关于SQL和索引的知识。

在ON DUPLICATE KEY UPDATE中使用值是正确的。请参阅:这将如何更改其他行中的值?我不明白。它是有效的,并且更倾向于像OP一样使用特殊值函数。VALUES函数的这种用法并没有导致OP报告的问题。在我看来,您的逻辑和SQL都很好。我怀疑是其他因素在改变数据。如果INSERT语句偏离了轨道,以至于改变了一个完全不同的行中的值,那么您将遇到比某些PHP代码更大的问题。所以是的,不是那样的。你诊断这个问题的逻辑相当于每次我启动我的车,我邻居的搅拌机就会打开。我意识到了这一点。我只是想找出唯一索引是否会导致这种情况。假设另一个客户机为与o不同的行发送相同的唯一索引
您正在尝试更新。然后像这样奇怪的事情可能会发生。不,真的不会。您不会更新其他行。假设您没有使用MySQL的一些非常旧的版本,或者类似的东西?最新的社区版本。如果客户机发送一个已经存在的唯一索引以及count2的值x和0,那么这将更新一个不同的行,但与上面的查询无关。但是我不+1吗?如果不使用多个唯一索引,我应该怎么做?你的最后一句话有点破坏了我的整个数据库建设。这是一台发布信息的iPad。CLIENTID不会更改,但每次操作CLIENTENTRYID都会增加1,因此相同的更新尝试不会导致重复条目。奇怪的是,在一次失败的尝试后,这种情况并没有发生。@nickdnk是的,我讨厌成为坏消息的传递者。您真的必须使CLIENTID和CLIENTENTRYID都成为唯一索引吗?我看到你的表中已经有了一个PK。这个想法是,组合使条目独一无二。客户端无法知道PK,因为它只是一个自动增量值。这是一个组合的唯一索引,它们不是单独唯一的。这样,任何客户端都不能发布相同的客户端ClientEntryId组合,因为这在逻辑上是不可能的。@nickdnk为什么您的客户端需要知道PK?是否可以更新insert语句以插入表ID、COUNT1、COUNT2、CLIENTID、CLIENTERTYID值默认值、、、?、?,?,?,?在重复密钥更新时,COUNT1=valuescont1,COUNT2=valuescont2';为了确保每次操作都插入自动递增PK?我不知道如何打开聊天。但是:我刚刚尝试为更新前定义一个触发器,该触发器将我添加的一个名为MODIFIED的列更改为NOW-如果我有意从SQL提示符输入一个重复的条目,它会起作用-并且值也会正确更新。当我看到错误发生时,修改的值没有改变,对于一个随机行,COUNT2只是跳到零。是的,这是除了PK之外唯一一个独特的专栏。就OP提供的信息而言,这是公认的最全面、最正确的答案。
UPDATE `mytable`
   SET COUNT1        = ?
     , COUNT2        = ?
 WHERE CLIENTID      = ?
   AND CLIENTENTRYID = ?