2012-09-06 40 views
1

接受的答案sql swap primary key values失败,出现错误Can't reopen table: 't' - 大概这与打开同一张表进行两次写入有关,导致锁定。MySQL交换主键值

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

回答

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; 

编辑:固定的错误

+1

这只会导致ID 1变为0并且ID 2不会更改... –

+0

@Kolink:我在一个InnoDB表上测试过,你是对的。该声明在MyISAM表上工作。我建议使用三种语句方法,这些方法应该在MyISAM,InnoDB和临时(也是MyISAM)表上工作。实际上,我使用InnoDB进行的测试显示1变为0,2变为1,然后1再变回2 ......用MyISAM测试会得到不同的结果。 – spencer7593

1

请勿为此使用临时表。

manual

您不能引用到一个临时表不止一次在相同的查询。 例如,下面不工作:

mysql> SELECT * FROM temp_table, temp_table AS t2; 
ERROR 1137: Can't reopen table: 'temp_table' 

此错误,如果你还指临时表中的多个 次在不同的别名存储功能,即使 引用发生在发生函数中的不同语句。

UPDATE:

很抱歉,如果我没有得到它的权利,但为什么一个简单的三路交流不行?

像这样:

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 [email protected]_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; 
+0

提到谁'TEMPORARY'表? – eggyal

+1

@eggyal我通过我发布的错误消息间接地做了。 –

+0

那么,使用一个非临时表,我得到错误“重复输入密钥”。 –