簡體   English   中英

用於支持動態屬性的模式

[英]Schema to support dynamic properties

我正在開發一個編輯器,使用戶能夠實時創建“對象”定義。 定義可以包含零個或多個屬性。 屬性的名稱類型。 創建定義后,用戶可以創建該定義的對象並設置該對象的屬性值。

因此,通過單擊鼠標按鈕,用戶應該是。 能夠創建一個名為“Bicycle”的新定義,並添加“Numeric”類型的屬性“Size”。 然后是另一個名為“Text”的屬性,名為“Text”,然后是另一個名為“Price”的屬性,類型為“Numeric”。 完成后,用戶應該能夠創建一些“自行車”對象,並填寫每輛自行車的“名稱”和“價格”屬性值。

現在,我已經在幾個軟件產品中看到過這個功能,所以它必須是一個眾所周知的概念。 當我坐下來試圖想出一個DB模式來支持這個數據結構時,我的問題就開始了,因為我希望使用適當的列類型來存儲屬性值。 IE瀏覽器。 數字屬性值存儲為數據庫中的INT,文本屬性值存儲為VARCHAR。

首先,我需要一個包含所有對象定義的表:

Table obj_defs

id | name      |
----------------
 1 | "Bicycle" |
 2 | "Book"    |

然后我需要一個表來保存每個對象定義應該具有的屬性類型:

Table prop_defs

id | obj_def_id | name      | type |
------------------------------------
 1 |          1 | "Size"    |    ? |
 2 |          1 | "Name"    |    ? |
 3 |          1 | "Price"   |    ? |
 4 |          2 | "Title"   |    ? |
 5 |          2 | "Author"  |    ? |
 6 |          2 | "ISBN"    |    ? |

我還需要一個包含每個對象的表:

Table objects

id | created    | updated    |
------------------------------
 1 | 2011-05-14 | 2011-06-15 |
 2 | 2011-05-14 | 2011-06-15 |
 3 | 2011-05-14 | 2011-06-15 |

最后,我需要一個表來保存每個對象的實際屬性值,並且該表的一個解決方案是為每個可能的值類型都有一個列,例如:

Table prop_vals

id | prop_def_id | object_id | numeric | textual | boolean |
------------------------------------------------------------
 1 |           1 |         1 |      27 |         |         |
 2 |           2 |         1 |         |  "Trek" |         |
 3 |           3 |         1 |    1249 |         |         |
 4 |           1 |         2 |      26 |         |         |
 5 |           2 |         2 |         |    "GT" |         |
 6 |           3 |         2 |     159 |         |         |
 7 |           4 |         3 |         |    "It" |         |
 8 |           5 |         3 |         |  "King" |         |
 9 |           6 |         4 |       9 |         |         |

如果我實現了這個模式,prop_defs表的“type”列會保持什么? 每個映射到列名的整數,varchars只是保存列名? 還有其他可能嗎? 存儲過程會以某種方式幫助我嗎? 用於獲取對象2的“name”屬性的SQL是什么樣的?

您正在實現名為Entity-Attribute-Value模型的內容http://en.wikipedia.org/wiki/Entity-attribute-value_model

很多人都會說這是一個壞主意(通常我就是其中之一),因為你最后一個問題的答案是“SQL取出的內容......”往往是“厚厚的毛茸茸,令人討厭,並且變得更糟。”

一旦允許用戶開始在其他對象中嵌套對象,這些批評就會持續存在,如果你不允許這樣做,情況將保持可控。

對於你的第一個問題,“prop_defs表的”類型“列是什么”,如果你有一個包含{“numeric”,“Any Number”},{“textual”的類型和描述的表,一切都會更簡單,“String”}等。第一個值是主鍵。 然后在prop_defs中,您的列“type”是該表的外鍵並保存值“numeric”,“textual”等。有些人會錯誤地告訴您總是使用整數鍵,因為它們加速更快,但如果您使用值“數字“,”文本“等你不必加入 ,最快的加入是你不做的。

獲取單個值的查詢將具有CASE語句:

SELECT case when pd.type = "numeric" then pv.numeric
            when pd.type = "textual" then pv.textual
            when pd.type = "boolean" then pv.boolean
  from prov_vals pv 
  JOIN prop_defs pd ON pv.prop_def_id = pv.id
 WHERE pv.object_id = 2
   AND pd.name = "Name"

您必須接受關系數據庫不擅長提供此類功能。 他們可以提供它,但不擅長它。 (我希望我錯了)。 關系數據庫更適合定義的接口,而不是更改接口。

--EAV表提供動態字段,但性能很差。 很糟糕的索引。 查詢很復雜。 它可以在很多情況下完成工作,但是在大桌面上可能會崩潰,很多用戶都會遇到系統。

- 具有多個占位符列的“常規”表格可以提高性能,但是您獲得了非描述性的列名稱,並且可以“添加”列數限制。 它也不支持子類型分離。

- 通常在開發時創建/修改表,而不是運行時。 我們真的應該歧視在運行時修改數據庫嗎? 也許,也許不是。 在運行時創建新表,外鍵和列可以實現真正的動態對象,同時提供“常規”表的性能優勢。 但是您必須查詢數據庫的模式,然后動態生成所有查詢。 那會很糟糕。 它完全打破了表作為接口的概念。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM