2012-09-06 58 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

那麼,使用一個非臨時表,我得到錯誤「重複輸入密鑰」。 –