将条件逻辑表达式/规则存储在数据库中

15

如何使用RDBMS存储逻辑表达式?

我标记对象并希望能够基于这些标记构建真值语句。(这些可能被视为虚拟标记。)

标记
new
for_sale
used
offer

规则
second_hand_goods = (!new or used) and for_sale
new_offer = new and offer
second_hand_offer = second_hand_goods and offer

  • 规则应该能够引用标记和其他规则。
  • 最好能够轻松访问Hibernate可以访问的模式。
  • 最好能够在一个select/call中检索整个规则?

你们如何在数据库中存储表达式和业务规则?

提前致谢。

更新
明确一下,这些规则不是供数据库内部使用的,而是由需要持久化这些标记和规则的外部应用程序创建和使用。谢谢。

5个回答

6
从实用的角度来看,如果计算所需的所有列都存在于同一张表中,您可以在数据库上创建计算字段 - 计算字段只能从单个记录中工作。大多数现代DBMS平台都对此功能提供了一定的支持。
从理论上讲,您正在涉足语义数据建模。最好的论文是 Hammer 和 MacLeods 的 Ruritanian Oil Tankers 论文,该论文描述了一种名为 SDM 的语义数据建模符号化表示法。SDM使用结构化英语类型的符号化表示法来标记您描述的数据库规则。如果您想要通用性并且不介意为SDM编写解析器,则可以创建一个规则引擎,其中可以配置这种逻辑。这种类型的模型也应该可以适应与O / R映射器良好地协作。
在负面方面,制作这种工具需要花费相当长的时间,因此只有在您对管理数据语义的需求非常大时才值得进行。 对于您提到的示例,它可以轻松地适合过度杀伤领域,但如果您的问题更大,建立类似于此的东西可能是值得的。 如果您不想编写解析器,可以为标记SDM类似语言制作XML模式。

5

管理嵌套和括号可能变得非常复杂且容易出错。我过去处理这个问题的方式是使用XML来定义逻辑,因为它可以很好地处理嵌套。使用SQL Server 2005或更高版本,您也可以将其存储在单个表中。

您的二手货逻辑可以存储为...

<logic type="and">
    <logic type="or">
        <logic type="not">
            <value type="new" />
        </logic>
        <value type="used" />
    </logic>
    <value type="for_sale" />
</logic>

很抱歉,这并不是对你问题的实际回答,而只是另一种做事情的替代方式。我过去发现它对我有用。


6
根据我的经验,我只能说尝试使用XML作为编程语言的感觉很糟糕。 - Anton Gogolev
我完全同意,不过这仅用于存储基于逻辑的公式。主要观点是,与其在数据库中构建此机制,我更愿意使用XML的现成嵌套能力。 - Robin Day
嘿,我有一个类似的情况,正在考虑使用这样的设计...(一个SqlXml字段)。更重要的是,整个表达式只是我系统中一个非常微不足道的功能,只是想问一下这在设计方面是否“可以”?因为像上面的人们一样,许多人都有一些复杂的方法来存储它而不使用xml在数据库中。@anton - gideon
@RobinDay,看起来就是我正在寻找的东西。谢谢! 你能否给出一些如何将这个XML解析为PHP表达式的想法? - Denis O.
@DenisO。我知道已经晚了几年,但这里有一些我编写的PHP代码可以处理类似的问题——它实现了and、or、at least、at most和sum等方法。https://gist.github.com/bravadomizzou/b16d12d6e0f8994526468dc2d9937a47 - Ray

1
作为默认设置,除非我已经充分理解问题并找到解决方案,否则我不会将业务规则存储在数据库中。这些规则应该放在代码中。当然,任何规则都有例外,您可以使用RDBMS的存储过程和/或函数来封装这些规则(如果您的数据库支持)。但是,正如我所说的,理想情况下,您应该在代码中以有意义的方式解释数据。
更新:
抱歉,我意识到我没有回答你的问题。如果您的数据库支持,您可以使用函数,允许您传递参数并返回标量值,或者使用存储过程。您可能每个表达式有一个存储过程,并且有一个更大的过程来组合这些表达式。

如果您有一个没有用户界面的ETL应用程序,那么“代码”将放在哪里? - adolf garlic

0

这样怎么样:

Tables:
 tags( id, name )
 goods ( id, ... )
 goods_tags_mm ( tag_id, good_id )
 rules ( id, name )
 rules_cnf ( id, rule_id )
 rules_cnf_terms ( rules_cnf_id, tag_id )

0

我会使用一个表格

tags(id,name,type,expression,order)
  • 类型会显示标签是否为普通或计算的。
  • 顺序会重新排序,如果你添加了新的计算标签,则它指定这些标签的计算顺序...
  • 表达式将在插入行之前解析和检查,也可以使用 GUI 构建(类似于 Oracle Discoverer 如何处理这些事情)。
  • 你只需将普通标签链接到项目即可。

对于您的示例“二手商品”,需要在“二手报价”之前计算出所有其他内容都可以不依赖于其他内容进行计算。

1,'new',1,'',NULL
2,'for_sale',1,'',NULL
3,'used',1,'',NULL
4,'offer',1,'',NULL
5,'second_hand_goods',2,'(!new or used) and for_sale',1
6,'new_offer',2,'new and offer',1
7,'second_hand_offer',2,'second_hand_goods and offer',2

一个项目只能被标记为 for_sale,计算将会得到:
second_hand_goods,second_hand_offer

我需要一个函数,可以列出该项的所有标签列表,包括直接标签和计算标签:
for_sale,second_hand_goods,second_hand_offer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接