我有一张表
(ID INT auto_incrment primary key,
tag VARCHAR unique)
我想在一个插入多个标签。像这样:
INSERT INTO tags (tag) VALUES ("java"), ("php"), ("phyton");
如果我执行此操作,并且“java”已经在表中,我收到错误。它不添加“php”和“phyton”。
如果我这样做:
INSERT INTO tags (tag) VALUES ("java"), ("php"), ("phyton")
ON DUPLICATE KEY UPDATE tag = VALUES(tag)
它会在没有错误的情况下添加,但会在ID字段中跳过2个值。
示例:我使用ID = 1
的Java并运行查询。然后PHP将是3和Phyton 4.有没有办法执行此查询而不跳过ID?
我不希望他们之间有大的空间。我也试过INSERT IGNORE
。
谢谢!
答案 0 :(得分:0)
参见" SQL#1"在http://mysql.rjweb.org/doc.php/staging_table#normalization。它更复杂,但避免燃烧' IDS。它具有在另一个表中需要标签的潜在缺点。该链接的摘录:
# This should not be in the main transaction, and it should be
# done with autocommit = ON
# In fact, it could lead to strange errors if this were part
# of the main transaction and it ROLLBACKed.
INSERT IGNORE INTO Hosts (host_name)
SELECT DISTINCT s.host_name
FROM Staging AS s
LEFT JOIN Hosts AS n ON n.host_name = s.host_name
WHERE n.host_id IS NULL;
通过将其隔离为自己的事务,我们可以快速完成它,从而最大限度地减少阻塞。通过说IGNORE
,我们并不关心其他线程是否同时“关注”。插入相同的host_names。 (如果您没有其他帖子执行此类INSERTs
,则可以抛出IGNORE
。
(然后继续讨论IODKU。)
答案 1 :(得分:0)
INNODB 引擎其主要特点是支持 ACID 类型的事务。
我指出的通常不是“问题”,而是引擎会在知道它是否重复之前“保留”ID。 这是一个解决方案,但它取决于您的表,如果我们谈论的是一个非常大的表,您应该先做一些测试,因为 AUTO_INCREMENT 函数可以帮助您遵循 id 的顺序。
我会给你一些例子:
INSERT INTO tags (java,php,python) VALUES ("val1"), ("val2"), ("val3")
ON DUPLICATE KEY UPDATE java = VALUES(java), id = LAST_INSERT_ID(id);
SELECT LAST_INSERT_ID();
ALTER TABLE tags AUTO_INCREMENT = 1;
注意:我给你添加了 LAST_INSERT_ID() 因为每次你插入或更新它总是给你一个插入或保留的 id。 每次调用 INSERT INTO 时,都必须遵循 AUTO_INCREMNT。