对sql 交换主键值的接受答案因错误而失败Can't reopen table: 't'
- 大概这与打开同一个表以写入两次有关,从而导致锁定。
是否有任何快捷方式,或者我必须同时获得两者,将其中一个设置为NULL
,将第二个设置为第一个,然后将第一个设置为先前获取的第二个值?
对sql 交换主键值的接受答案因错误而失败Can't reopen table: 't'
- 大概这与打开同一个表以写入两次有关,从而导致锁定。
是否有任何快捷方式,或者我必须同时获得两者,将其中一个设置为NULL
,将第二个设置为第一个,然后将第一个设置为先前获取的第二个值?
不要为此使用临时表。
从手册:
您不能在同一查询中多次引用 TEMPORARY 表。例如,以下内容不起作用:
mysql> SELECT * FROM temp_table, temp_table AS t2;
ERROR 1137: Can't reopen table: 'temp_table'
如果您在存储函数中以不同别名多次引用临时表,也会发生此错误,即使引用发生在函数内的不同语句中也是如此。
更新:
对不起,如果我没有做对,但为什么简单的三路交换不起作用?
像这样:
create table yourTable(id int auto_increment, b int, primary key(id));
insert into yourTable(b) values(1), (2);
select * from yourTable;
DELIMITER $$
create procedure pkswap(IN a int, IN b int)
BEGIN
select @max_id:=max(id) + 1 from yourTable;
update yourTableset id=@max_id where id = a;
update yourTableset id=a where id = b;
update yourTableset id=b where id = @max_id;
END $$
DELIMITER ;
call pkswap(1, 2);
select * from yourTable;
要交换 1 和 2 的 id 值,我会使用如下 SQL 语句:
编辑:根据我的测试,这不适用于 InnoDB 表,仅适用于 MyISAM 表。
UPDATE mytable a
JOIN mytable b ON a.id = 1 AND b.id = 2
JOIN mytable c ON c.id = a.id
SET a.id = 0
, b.id = 1
, c.id = 2
要使此语句起作用,表中不能存在 0 的 id 值,任何未使用的值都适合...但是要使其在单个 SQL 语句中起作用,您需要(暂时)使用第三个 id 值.
此解决方案适用于常规 MyISAM 表,而不适用于临时表。我错过了这是在临时表上执行的,我对您报告的错误消息感到困惑Can't reopen table:
。
要在临时表中交换 id 值 1 和 2,我将再次运行三个单独的语句,使用临时占位符值 0:
UPDATE mytable a SET a.id = 0 WHERE a.id = 1;
UPDATE mytable b SET b.id = 1 WHERE b.id = 2;
UPDATE mytable c SET c.id = 2 WHERE c.id = 0;
编辑:修正错误