1

对sql 交换主键值的接受答案因错误而失败Can't reopen table: 't'- 大概这与打开同一个表以写入两次有关,从而导致锁定。

是否有任何快捷方式,或者我必须同时获得两者,将其中一个设置为NULL,将第二个设置为第一个,然后将第一个设置为先前获取的第二个值?

4

2 回答 2

1

不要为此使用临时表。

手册

您不能在同一查询中多次引用 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;
于 2012-09-06T15:00:46.007 回答
0

要交换 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;

编辑:修正错误

于 2012-09-06T15:35:01.057 回答