这是我第一篇文章的EDITED版本,因为第一篇文章似乎不够清楚。
我希望根据SELECT查询结果插入或更新(如果存在)。这是我的代码以标准方式工作:
$query = "SELECT * FROM table1 WHERE id1 =".$id1." AND id2=".$id2;
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) > 0) {
$query = "UPDATE table1 SET id3=".$id3." WHERE id1 =".$id1." AND id2 = ".$id2." LIMIT 1";
$result = mysqli_query($conn, $query);
} else {
$query = "INSERT INTO table1 (id1, id2, id3) VALUES ($id1, $id2, $id3)";
$result = mysqli_query($conn, $query);
}
id1,id2,id2值可以重复但在一个条件下(id1和id2不能同时重复。
例如:
只能在以下情况下插入新行 :
如果这个已存在于table1
中 id0=0 id1=5 id2=10 id3=15
然后下一个将是:
id0=1 id1=6 id2=10 id3=15
或
id0=1 id1=5 id2=11 id3=15
行会更新
如果这个已存在于table1
中 id0=0 id1=5 id2=10 id3=15
,下一个是:
id0=1 id1=5 id2=10 id3=20
因为你注意到id1和id2与表中已有的相同,所以id3会更新。
我的 table1看起来像这样:
CREATE TABLE table1 (
`id0` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id1` int(11) NOT NULL,
`id2` int(11) NOT NULL,
`id3` int(11) NOT NULL
) ENGINE=InnoDB;
我的问题是:是否可以使用“在重复密钥更新时插入”或其他任何方式将上述3个查询合并为一个?
答案 0 :(得分:3)
首先,您需要将密钥id1和id2设置为一个(组合是唯一的)
CREATE TABLE table1 (
`id0` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id1` int(11) NOT NULL,
`id2` int(11) NOT NULL,
`id3` int(11) NOT NULL,
UNIQUE KEY `KeyName` (`id1`,`id2`) # <------
) ENGINE=InnoDB;
这样,您无法添加包含相同“id1”和“id2”的两行,然后才能使用以下命令。
INSERT INTO table1 (id1, id2, id3)
VALUES ($id1, $id2,$id3)
ON DUPLICATE KEY UPDATE id3 = $id3;
<强>更新强>
当我们在innoDB
表上执行此方法时,有一个错误会在AUTO_INCREMENT
如果我们使用InnoDB
CREATE TABLE table1 (
`id0` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id1` int(11) NOT NULL,
`id2` int(11) NOT NULL,
`id3` int(11) NOT NULL,
UNIQUE KEY `KeyName` (`id1`,`id2`) # <------
) ENGINE=InnoDB;
INSERT INTO table1 (id1, id2, id3)
VALUES (5, 10,1)
ON DUPLICATE KEY UPDATE id3 = 1;
INSERT INTO table1 (id1, id2, id3)
VALUES (5, 10,2)
ON DUPLICATE KEY UPDATE id3 = 2;
INSERT INTO table1 (id1, id2, id3)
VALUES (6, 10,1)
ON DUPLICATE KEY UPDATE id3 = 1;
得出以下结果:
+-----+-----+-----+-----+
| id0 | id1 | id2 | id3 |
+-----+-----+-----+-----+
| 1 | 5 | 10 | 2 |
+-----+-----+-----+-----+
| 3 | 6 | 10 | 1 |
+-----+-----+-----+-----+
但是如果我们使用Myisam
CREATE TABLE table2 (
`id0` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id1` int(11) NOT NULL,
`id2` int(11) NOT NULL,
`id3` int(11) NOT NULL,
UNIQUE KEY `KeyName` (`id1`,`id2`) # <------
) ENGINE=Myisam;
INSERT INTO table2 (id1, id2, id3)
VALUES (5, 10,1)
ON DUPLICATE KEY UPDATE id3 = 1;
INSERT INTO table2 (id1, id2, id3)
VALUES (5, 10,2)
ON DUPLICATE KEY UPDATE id3 = 2;
INSERT INTO table2 (id1, id2, id3)
VALUES (6, 10,1)
ON DUPLICATE KEY UPDATE id3 = 1;
得出以下结果:
+-----+-----+-----+-----+
| id0 | id1 | id2 | id3 |
+-----+-----+-----+-----+
| 1 | 5 | 10 | 2 |
+-----+-----+-----+-----+
| 2 | 6 | 10 | 1 |
+-----+-----+-----+-----+
但是这个错误不应该令人讨厌,如果有必要使用InnoDB,这只会对行重新编号,程序应该知道存在间隙,这与删除行的效果相同。
虽然,它可以通过php执行,但只会在服务器上产生更多负载。
答案 1 :(得分:2)
我可以给你3个例子:
1)处理重复键事件:
INSERT INTO table1 (id1, id2, id3) VALUES ('".$id1."', '".$id2."','".$id3."')
ON DUPLICATE KEY UPDATE id3='".$id3."'";
2) 替换为:
REPLACE INTO table1 (id1, id2, id3) VALUES ('".$id1."', '".$id2."','".$id3."');
3)同时插入忽略更新:
$q = "INSERT IGNORE INTO table1 (id1, id2, id3) VALUES ('".$id1."', '".$id2."','".$id3."');
UPDATE table1 SET id3 = ".$id3." WHERE id1=".$id1." AND id2 = ".$id2." LIMIT 1;";
P.S。确保您已使用id1和id2
设置了正确的组合索引如果这些例子都不起作用:
$query = "SELECT 1 FROM table1 WHERE id1 =".(int)$id1." AND id2=".(int)$id2." LIMIT 1";
$result = mysqli_query($conn, $query);
$query = (mysqli_num_rows($result) > 0) ?
"UPDATE table1 SET id3=".$id3." WHERE id1 =".$id1." AND id2 = ".$id2." LIMIT 1" :
"INSERT INTO table1 (id1, id2, id3) VALUES (".(int)$id1.", ".(int)$id2.", ".(int)$id3.")";
mysqli_query($conn, $query);