Mysql

使用外鍵快速插入/刪除的表結構

  • December 7, 2012

目前情況

我們有一個名為cca300,000 行。在此表中,我們儲存了特定產品的競爭對手。

例子:

編號 | 競爭對手 | 關於競爭對手的一些資訊 | 產品 
---------------------------------------------------------------
1 | C_1 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | P_1 
2 | C_2 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | P_1 
3 | C_3 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | P_1 
4 | C_1 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | P_2 
5 | C_4 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | P_2 

我們每 30 分鐘閱讀一次新的競爭對手。為此,我們首先刪除具有特定產品 (P_1) 的每個人,然後插入新產品。因此,我們的數據庫中永遠不會有競爭對手,目前該產品還沒有列出。

當我們得到新資訊時,我們會對產品進行某種研究。

(我們還有一個名為pca. 100,000 行的表。在該表中,我們儲存有關產品的資訊。)

所以回到研究過程。我們遍歷每一種產品,必須讓競爭對手獲得他們的資訊。為此,我們確實做了一個 mysql 請求,例如SELECT * FROM c WHERE product LIKE "P_1";. 並不是說這不是很好的表現。

我想要實現的目標p是,只需一個查詢,我就可以從相同的競爭對手c那裡product id。這樣這些資訊就會儲存在這樣的數組中:

[0]['id'] => '2'  
[0]['product_identifier'] => 'P_1'  
[0]['c'][0]['competitors'] => 'C_1'  
[0]['c'][1]['competitors'] => 'C_2'  
[0]['c'][3]['competitors'] => 'C_3'

可能的解決方案

為了通過一個查詢獲得所需的資訊,我想出了這個解決方案。

在表c中,產品行包含一個連結到p表的外鍵。這很容易實現。但我問自己是否可以輕鬆刪除cp行。我從來沒有這麼密集地使用外鍵——在我看來總是會產生一些錯誤。

而且我還想知道我是否可以那麼容易地加入,因為我想從p相關競爭對手那裡獲得,而不是相反。你知道我的意思?不確定我是否可以這樣做。如果可以的話,如何處理這個外鍵。為了不弄亂不干淨的數據庫,我要尋找什麼。

範例

我們將使用c上面的表,其中c.product儲存了表的外鍵p.product_identifier。像這樣:

編號 | 產品標識符 | 關於產品的一些資訊 
---------------------------------------------------------------
1 | P_1 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
2 | P_2 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
3 | P_3 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 

我不確定這是如何工作的,或者它是否是一個好主意,但我的查詢看起來如何?如果我想從SELECT每個產品p以及他們的競爭對手那裡獲得c

首先,如果您的表是 InnoDB,並且 columnc.P_ID是 column 的引用p.P_ID(注意實際的列名可能不同),那麼您絕對應該使用外鍵來避免孤兒,但要知道您必須明確聲明ON DELETE CASCADE,因為預設值為ON DELETE SET NULL,保留孤兒。

但這與選擇競爭對手的產品和資訊的“單一查詢”沒有任何關係。

達到:

我想實現,只需一個查詢,我就從 p 獲得了產品資訊,還從 c 獲得了競爭對手的產品資訊,其中產品 ID 相同。

您的查詢將使用連接:

SELECT products.P_ID, products.product_name, competitors.info
FROM products
LEFT JOIN competitors ON competitors.P_ID=products.P_ID

這將使您獲得產品的重複資訊(競爭對手資訊會有所不同)。然後您將使用您的應用程序將該資訊解析為您需要的數組。

如果您想要產品的單行,您可以使用GROUP_CONCAT競爭對手的功能:

SELECT products.P_ID, products.product_name, 
 GROUP_CONCAT(competitors.info SEPARATOR ',') as competitor_info
FROM products
LEFT JOIN competitors ON competitors.P_ID=products.P_ID
GROUP BY products.P_ID;

您應該注意的一個主要警告:ON UPDATE|DELETE CASCADE不會在級聯刪除/更新的行上觸發觸發器:

筆記

目前,級聯外鍵操作不啟動觸發器。

CASCADE如果您想刪除孤立行,這不應該阻止您使用。但你應該意識到這一點。

引用自:https://dba.stackexchange.com/questions/29872