2011-05-24 66 views
1

我有一個使用CCK內容字段來存儲大部分數據的drupal站點。如何更新複合主鍵的一部分?

我想手動更改一些數據以指向不同的節點版本。

UPDATE content_field_table SET vid = '1234' WHERE nid = '12' AND vid = '123'; 

的問題是,content_field_table有

PRIMARY KEY (`vid`,`delta`) 

複合主鍵,以便當我運行的更新語句,我得到以下錯誤:

錯誤代碼:1062 重複條目'52979-0'爲'PRIMARY'鍵'

如何根據需要更新vid?

回答

4

主鍵必須是唯一的。因此,您無法更改一條記錄以獲得與現有記錄相同的PK

例如,如果您從下面的SQL中獲取任何記錄,則無法完成要執行的更新。您需要首先進行其他更改或刪除記錄或刪除PK

SELECT SOURCE.delta, 
     SOURCE.vid, 
     TARGET.delta, 
     TARGET.vid 
FROM content_field_table SOURCE 
     INNER JOIN content_field_table TARGET 
     ON SOURCE.delta = TARGET.delta 
WHERE SOURCE.vid = '123' 
     AND TARGET.vid = '1234' 
+1

這讓我指出了正確的方向。我發現有一條記錄在行中相撞,但我沒有正確檢查PK的三角部分。 – fafnirbcrow 2011-05-24 17:33:23

2

不要更改您的主鍵。也請儘可能不要使用複合主鍵。 MySQL(和其他數據庫)按PK順序將記錄存儲在頁面中。在爲每個頁面分配空間之前,MySQL會填充每個頁面15/16,並在那裏插入更多的數據。

化合物PK的問題或改變你的PK是碎片。我不是指磁盤碎片,我的意思是索引碎片。隨着PK的移動,數據必須在磁盤周圍進行混洗才能保持正確的順序。取決於數據集MySQL可能需要移動許多物理行來執行此操作。

更新你的PK也是一樣。更改PK會更改磁盤上的順序,並需要移動許多行。如果可能的話,使用自動遞增PK,或者不使用PK,讓MySQL爲你創建一個內部PK。

你想要的是將新行添加到磁盤上的最後一個空閒頁面,該頁面既快速又便宜。

+0

你是對的,可變的PK是一個壞主意,但如果你會原諒一些狡辯。數據庫通常以集羣索引順序存儲數據。確實,PK's通常也是聚集索引,但它們不一定是。還有一些情況下,對INSERT或UPDATE的性能損失可能是對SELECT的合理折衷,所以並不總是需要優化新行速度 – 2011-05-24 17:20:24

+0

我認爲MySQL 5.x分支聚簇索引必須是PK。我認爲對於SELECT流量很大,這可能是一個有價值的折中,正如你所說。 – FoneyOp 2011-05-24 17:51:51

+0

是的,你是對的MySQL如此+1。 [docs say](http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html)如果你定義了一個PK,那麼它將是聚集索引。 – 2011-05-24 18:17:02

相關問題