2012-06-26 63 views
2

我爲我的公司創建了一個數據庫,它將存儲許多不同類型的信息。類別包括亮度,對比度,色度等。每個類別都有一些我公司希望開始存儲的數據點。不一致數據的數據庫結構

通常,我會爲每個類別創建一個表來存儲相應的數據。 (這是我學會如何做到的)。但是,有時這些類別具有「子數據」,這會改變每個表格中所需的字段數量。

我的問題是,人們在構建數據庫時如何處理數據的不一致?他們是否只是爲額外的數據添加更多的表格還是完全不同?

+0

您是否考慮過NoSQL解決方案? –

+0

當然,最好的方法是提前計劃並準確瞭解您的要求。除此之外,當然,添加表格或列是解決問題的方法之一。 – Jason

+0

有什麼不對?只需添加字段 – Sebas

回答

1

有幾個(和謝天謝地只有一些)關於關係數據庫模型的不可違反的規則。其中之一是,如果你不知道什麼要存儲,你很難存儲它。有機會,你將有一個更難的時間檢索它。

也就是說,商業規則的現實往往不如數據庫設計的象牙塔清晰。最重要的是,您可能需要或甚至需要一種方法來引入新屬性而不更改模式。

這裏有兩個feasable方法去這個:

  1. 使用的數據存儲,專門從事鬆動或inexistant模式 (NoSQL的朋友)。詳細解釋這是一個CS 論文的主題,而不是一個stackoverflow的答案。
  2. 我的建議:使用一個單獨的屬性表 - 這裏是如何 這個雲:

假設爲參數的緣故,你的產品八方通有(唯一的字符串)name,(整數)idbrightnesscontrastchromaticity有時(整數)foo和(串)bar,考慮這些表

CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT, 
    name VARCHAR(50) NOT NULL, 
    brightness INT, 
    contrast INT, 
    chromaticity INT, 
    UNIQUE INDEX(name) 
); 

CREATE TABLE properties (
    id INT PRIMARY KEY AUTO_INCREMENT, 
    name VARCHAR(50) NOT NULL, 
    proptype ENUM('null','int','string') NOT NULL default 'null', 
    UNIQUE INDEX(name) 
); 

INSERT INTO properties VALUES 
    (0,'foo','int'), 
    (0,'bar','string'); 

CREATE TABLE product_properties (
    id INT PRIMARY KEY AUTO_INCREMENT, 
    products_id INT NOT NULL, 
    properties_id INT NOT NULL, 
    intvalue INT NOT NULL, 
    stringvalue VARCHAR(250) NOT NULL, 
    UNIQUE INDEX(products_id,properties_id) 
); 

現在您的「標準」屬性將像往常一樣位於products表中,而「可選」屬性將存儲在一行product_properties中,該行引用產品ID和屬性ID,值爲intvaluestringvalue

選擇產品,包括他們的foo如果有的話會是什麼樣子

SELECT 
    products.*, 
    product_properties.intvalue AS foo 
FROM products 
    LEFT JOIN product_properties 
    ON products.id=product_properties.product_id 
    AND product_properties.property_id=1 

甚至

SELECT 
    products.*, 
    product_properties.intvalue AS foo 
FROM products 
    LEFT JOIN product_properties 
    ON products.id=product_properties.product_id 
    LEFT JOIN properties 
    ON product_properties.property_id=properties.id 
WHERE properties.name='foo' OR properties.name IS NULL 

請您理解,這會帶來性能上的損失 - 事實上你交易對靈活性的表現:添加另一個財產不過是INSERT連續在properties,架構保持不變。

+0

嗯,這是一個有趣的解決方案。我以前從未見過類似的東西。非常感謝。我會給它一個旋轉 –

0

如果你沒有綁定mysql,那麼其他數據庫有table inheritancearrays來解決某些特定的情況。Postgresql是一個非常好的數據庫,可以像mysql一樣輕鬆自由地使用。

與MySQL你可以:

  1. 改變你的表,添加額外列,並允許在你不需要的子類數據NULL。這樣可以檢查完整性,因爲您仍然可以對列進行約束。除非你真的有子類別列的很多這種方式,我建議這一點,否則選項3.

  2. 店子類別的數據動態地在一個單獨的表,具有CATEGORY_ID,category_row_id,子類標識符(=類型子類別)和值列:通過這種方式,您可以通過鏈接它通過category_id(確定表)和category_row_id(原始類別錶行的PK鏈接)來檢索數據。壞事:你不能正確使用外鍵或約束來強制執行完整性,你需要編寫多毛的插入/更新觸發器,以便在那裏控制一些控制權,從而僅僅在客戶端上完成完整性檢查和參照檢查。 (在這種情況下,你最好走NoSQL路線)總之,我不會推薦這個。

  3. 您可以爲每個類別表創建一個獨立的子類別表,可以通過值列或可選子類別標識符固定或變量列,仍然可以使用外鍵,最好保持完整性是固定的,因爲您會您可以使用各種各樣的限制條件。如果你有一個很多的子類別的列,否則希望混亂你的常規子類別表,然後我建議使用這與固定的列。就像之前的選項一樣,我絕不會建議對任何事情都進行動態處理,除了一次性數據。

或者,如果你的子類別是非常多變和不穩定:使用NoSQL與文檔數據庫,如mongodb,你要知道,你可以保持在一個適當的RDBMS所有常規數據和剛剛storeside數據文檔數據庫儘管這可能不被推薦。

如果您的子類數據處於已知的固定狀態並且不容易發生變化,我只需將額外的列添加到特定的類別表中。請記住,正確的數據庫管理系統的主要特點是通過檢查和約束來保護數據的完整性,消除這種情況從來不是一個好主意。

0

如果您不限於MySQL,您可以考慮使用Microsoft SQL Server並使用Sparse Columns這將允許您擴展您的模式以包含您想要的多列,而不會導致對不適合給定行。