DB Design用于存储表的自定义字段

时间:2010-05-27 18:59:48

标签: database oracle database-design

根据我对该问题的回答,提出了这个问题 Getting weird issue with TO_NUMBER function in Oracle

正如大家都建议将数值存储在VARCHAR2列中并不是一个好习惯(我完全同意),我想知道我们团队的基本设计选择以及是否有更好的设计方法。

问题陈述:我们有许多表格,我们希望提供一定数量的自定义字段。所需的自定义字段数已知,但用户可以使用哪种属性映射到该列

E.g。我在下面假设了一个假设情景

假设您有一台笔记本电脑,可为每条笔记本电脑记录存储50个属性值。每个笔记本电脑属性都是由创建笔记本电脑的管理员创建的。

用户创建的笔记本电脑产品让我们说带有属性字符串,字符串,数字,数字,字符串

的lap1

第二位用户使用属性String,numeric,String,String,numeric

创建了laptop2

目前我们设计中的数据会保持如下状态

Laptop Table
Id Name field1  field2 field3  field4 field5
1  lap1 lappy   lappy  12      13     lappy
2  lap2 lappy2  13     lappy2  lapp2  12

这个例子模拟了我们的要求和我们的设计

现在在这里,如果有人在第2场比赛中查看lap2表的记录,我们需要申请TO_NUMBER。

select * from laptop 
where name='lap2'  
and TO_NUMBER(field2) < 15
在某些情况下,当查询计划决定首先应用to_number而不是其他过滤器时,

TO_NUMBER失败。

问题
这是一个有效的设计吗? 解决这个问题的其他替代方法是什么? 我们的一位队友建议为这些案例动态创建表格。这是个好主意吗? 流行的ORM工具如何提供自定义字段或弹性字段处理?

我希望我能够在这个问题上有意义。

抱歉这么长的文字..

这会导致我们在queryio

时使用TO_NUMBER

4 个答案:

答案 0 :(得分:4)

这是一个常见问题,并没有完美的解决方案。几个解决方案:

<强> 1  定义varchar2类型的X字段,类型为number的Y字段和date类型的Z字段。这可能是自定义字段数量的3倍,但您将永远不会遇到任何转换问题。

你的例子就是这样的:

Id Name field_char1  field2_char2 field_char3 ... field_num1 field_num2 ...
1  lap1 lappy        lappy        lappy       ... 12         13     
2  lap2 lappy2       lappy2       lapp2       ... 13         12

在您的示例中,两行上的数值和字符值都相同,但不一定是这样:例如,第三行可能没有数字字段。

<强> 2  定义varchar2类型的X字段,并将一个双射函数应用于存储数字或日期字段(例如,Date可以存储为YYYYMMDDHH24miss)。您还需要一个额外的字段来定义行的上下文。只有在行类型良好时才应用to_numberto_char函数。

你的例子:

Id Name context field1  field2 field3  field4 field5
1  lap1 type A  lappy   lappy  12      13     lappy
2  lap2 type B  lappy2  13     lappy2  lapp2  12

您可以使用DECODE或CASE查询表:

SELECT * 
  FROM laptop
 WHERE CASE WHEN context = 'TYPE A' THEN to_number(field3) END = 12

第二种设计是Oracle Financials ERP(以及其他)中使用的设计。上下文允许您使用此设计定义CHECK约束(例如CHECK (CASE WHEN context = 'TYPE A' THEN to_number(field3) > 0)以确保完整性。

答案 1 :(得分:3)

这是收缩包装应用程序的常见场景,它代表了自定义数据模型的唯一机会。但从纯粹主义的角度来看,这是不好的做法。因为如果列可以包含'27 -MAY-2010'或178.50或'Red badger',那么显然它依赖于数据库外部的某些东西来赋予它意义。

但是使用XMLType会更糟糕,因为你失去了你所拥有的小结构。查询灵活列变得困难。仍有一些场景,这是适当的解决方案:主要是当我们对单个元素不感兴趣时​​,只对属性集合感兴趣。

那么,处理它的最佳方法是什么?自定义功能与自定义列一起使用:

SQL> create or replace function get_number
  2      ( p_str in varchar2 )
  3      return number
  4      deterministic
  5  is
  6      return_value number;
  7  begin
  8      begin
  9          return_value := to_number(trim(p_str));
 10      exception
 11          when others then
 12              return_value := null;
 13      end;
 14      return return_value;
 15  end;
 16  /

Function created.

SQL>

我们可以根据此列构建一个基于函数的函数:

SQL> create index t42_flex_idx on t42 ( get_number( flex_col))
  2  /

Index created.

SQL>

所以给出了这个测试数据......

SQL> select * from t42
  2  /

        ID FLEX_COL
---------- ------------------------------
         1 27-MAY-2010
         2 138.50
         3 Red badger
         2 23

SQL>

......这是它的工作原理:

SQL> select * from t42
  2  where get_number(flex_col) < 50
  3  /

        ID FLEX_COL
---------- ------------------------------
         2 23

SQL>

答案 2 :(得分:0)

如果在创建表时决定了所有列类型,那么动态生成表对我来说听起来不错。

但是,如果两个用户使用具有不同字段的同一个表,则可以仅为自定义字段创建新表并将它们连接到主表。这更像是一种面向对象的方法。

答案 3 :(得分:0)

您是否可以在代码层中创建XML图并将其存储在SYS.XMLTYPE字段类型中?

http://www.oracle-base.com/articles/9i/XMLTypeDatatype.php

这将允许您强烈键入(在XML中)您的值并保留有意义的结构。