我有一个MySQL表。我必须能够为速度添加唯一的INT值,而不是AUTO_INCREMENT列。
CREATE TABLE ki
(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT
, comp_id INT(10) UNSIGNED NOT NULL
, speed INT(4) UNSIGNED NOT NULL DEFAULT 0
, position INT(4) UNSIGNED NOT NULL DEFAULT 0
, PRIMARY KEY (id)
, UNIQUE INDEX (comp_id, speed, position)
, INDEX (comp_id)
, FOREIGN KEY (comp_id)
REFERENCES competitions (id)
ON DELETE NO ACTION
ON UPDATE CASCADE
) ENGINE=InnoDB CHARACTER SET latin1 COLLATE latin1_swedish_ci;
我想插入新行。
INSERT INTO ki (comp_id, speed, position) VALUES (1, 1, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (1, 2, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (1, 3, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (1, 3, 0) -- error
INSERT INTO ki (comp_id, speed, position) VALUES (2, 1, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (2, 3, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (2, 2, 0)
对于每个comp_id,速度值从1开始。速度值应始终为comp_id的最大速度值+ 1。
如果(1, 3, 0)
已存在,则插入内容应为(1, max(speed) where comp_id = 1, 0)
。换句话说,(1, 4, 0)
。
我不想修改现有的行。
我怎样才能在SQL查询中执行此操作?据说,速度必须是唯一的,如果同时有几个插入,这必须有效。
如果同时有多个插入,以下方式是否可以起作用并保证一个独特的速度值(从1开始的值)?
INSERT INTO ki (comp_id, speed, position)
VALUES (
1,
COALESCE((SELECT MAX(ki2.speed)
FROM ki AS ki2
WHERE ki2.comp_id = 1
), 1) + 1,
0
)
答案 0 :(得分:1)
使用INSERT INTO ... SELECT
声明:
INSERT INTO ki(comp_id, position, speed)
SELECT 1, 0, max(speed)+1
FROM ki
小心!这至少有两个陷阱:
AUTO_INCREMENT
来解决导致插入失败时出现间隙的问题虽然通过coalesce(max(speed),0)+1
包装陷阱很容易处理,但第二个陷阱是一个真正的危险,通常你需要考虑到这一点,或者只是创建UNIQUE INDEX
在speed
列上,并且赛车查询在任何尝试失败,但首先使用相同的值。
答案 1 :(得分:0)
我假设你不能使用自动增量,因为你已经有了其中之一?如果速度必须是唯一的,那么为什么它不是表上的PK并且摆脱自动增量列和自动增量速度反而?
但是,如果Speed应具有意义并在插入时定义,那么您有一个不同的问题。在这种情况下,您可以定义速度的唯一索引,如果值已经存在,则在插入时失败。或者,如果速度不存在,则编写存储过程以插入,如果存在,则更新记录。您选择的是数据含义和业务规则的函数。