在数据库中存储业务逻辑

Har*_*M V 25 mysql database business-logic business-rules segment

我们希望编写一些在某些数据之上工作的业务逻辑规则来构建报告.不确定哪个最好将它们存储在数据库MySQL中.

在此输入图像描述

它可以有一系列规则,然后是结果的声明,如上所示.

Som*_*luk 18

要构建报表,您可以使用任何编程语言转换业务逻辑.并使用数据库数据生成报告.

反对存储在数据库中的业务逻辑

我高度重视表达的力量,我发现SQL空间并不具备表达能力.使用您手头上最好的工具来完成最合适的任务.摆弄逻辑和高阶概念最好在最高级别完成.因此,存储和海量数据操作最好在服务器级别完成,可能在存储过程中完成.

但这取决于.如果您有多个应用程序与一个存储机制交互,并且您希望确保它保持其完整性和工作流,那么您应该将所有逻辑卸载到数据库服务器中.或者,准备好管理多个应用程序中的并发开发.

来源:存储过程中支持/反对业务逻辑的参数

也可以看看:

  1. 数据库中的业务逻辑
  2. 存储过程中的业务逻辑
  3. 在数据库中存储条件逻辑表达式/规则


Ran*_*eed 12

模型

CREATE TABLE businessRule (
  id INT NOT NULL ,
  name VARCHAR(32) NOT NULL ,
  description VARCHAR(255) NULL ,
  statement VARCHAR(255) NOT NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB;

CREATE TABLE leftOperand (
  id INT NOT NULL ,
  value VARCHAR(255) NOT NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB;

CREATE TABLE ruleItem (
  id INT NOT NULL ,
  businessRuleId INT NOT NULL ,
  operator ENUM('if','and','or','not') NOT NULL ,
  loperand INT NOT NULL ,
  comparator ENUM('<','=','>') NOT NULL ,
  roperand VARCHAR(255) NOT NULL ,
  roperand_ispercentage TINYINT(1)  NOT NULL ,
  PRIMARY KEY (id) ,
  INDEX businessRule_FK (businessRuleId ASC) ,
  INDEX leftOperand_FK (loperand ASC) ,
  CONSTRAINT businessRule_FK
    FOREIGN KEY (businessRuleId )
    REFERENCES mydb.businessRule (id )
    ON DELETE CASCADE
    ON UPDATE RESTRICT,
  CONSTRAINT leftOperand_FK
    FOREIGN KEY (loperand )
    REFERENCES mydb.leftOperand (id )
    ON DELETE RESTRICT
    ON UPDATE RESTRICT)
ENGINE = InnoDB;
Run Code Online (Sandbox Code Playgroud)


Mat*_*ine 12

反对"软编码"业务逻辑的论据如下:http://thedailywtf.com/Articles/Soft_Coding.aspx

"我们发现自己软编码的原因是因为我们担心变化.不是正常的变革恐惧,而是担心我们编写的代码必须因业务规则的变化而改变.这是一种非常愚蠢的恐惧.软件的全部意义(因此,"软")是它可以改变它将会发生变化.将软件与业务规则更改隔离开来的唯一方法是构建一个完全通用的程序,该程序缺乏所有业务规则但是实现任何规则.哦,他们已经构建了这个工具.它叫做C++.还有Java.还有C#.还有Basic.而且,我敢说,COBOL."


Meh*_*ran 8

我能给你的只是解决这个问题的方法,而不是答案本身.

设计数据库来存储这样的复杂数据的一般方法是设计将它们作为对象保存在内存中的方式,然后相应地尝试设计数据库.毕竟,您将使用编程语言评估规则.程序如下:首先是类图

类图

然后是时候将其转换为ERD:

在此输入图像描述

一旦有了数据库结构来存储/重新加载对象,就可以简单地创建类,使每个对象负责加载/存储自身.

[UPDATE]

例如,如果要将语句存储a + b * -c到数据库中,可将其翻译为以下插入:

-- c
INSERT INTO statement (statement_id) VALUES (1);
INSERT INTO operand (statement_id, type) VALUES (1, 'double');
-- - (minus)
INSERT INTO statement (statement_id) VALUES (2);
INSERT INTO operator (statement_id, type) VALUES (2, 'minus');
-- -c
INSERT INTO binary (operator_statement_id, operand_statement_id) VALUES (2, 1);
-- b
INSERT INTO statement (statement_id) VALUES (3);
INSERT INTO operand (statement_id, type) VALUES (3, 'double');
-- * (multiply)
INSERT INTO statement (statement_id) VALUES (4);
INSERT INTO operator (statement_id, type) VALUES (4, 'multiply');
-- b * -c
INSERT INTO unary (operator_statement_id, operand_statement_id1, operand_statement_id2) VALUES (4, 3, 2);
-- a
INSERT INTO statement (statement_id) VALUES (5);
INSERT INTO operand (statement_id, type) VALUES (5, 'double');
-- + (plus)
INSERT INTO statement (statement_id) VALUES (6);
INSERT INTO operator (statement_id, type) VALUES (6, 'sum');
-- a + b * -c
INSERT INTO unary (operator_statement_id, operand_statement_id1, operand_statement_id2) VALUES (6, 5, 4);
Run Code Online (Sandbox Code Playgroud)


小智 6

我认为首先需要做的是质疑您是否应该首先将规则放入数据库中。

数据库是一个繁重的解决方案,通常根本不需要。

在处理了各种形式的规则引擎(包括数据库驱动)之后,我可以告诉您,它很快就会变得令人沮丧和无用。我见过的最大错误之一是尝试编写自己的即席规则语言,并使用该语言通过数据库驱动条件逻辑。至少要使用一种已经证明的语言(Python,javscript等)并将其嵌入其中。

甚至更好-如果规则足够复杂,我个人更喜欢使用Excel电子表格。我们用这个自动化(基于生效日期把手变量逻辑等),同时我们还编写相当复杂的保险等级的逻辑来通过Web服务接口的Perl脚本,使用本产品:http://decisionresearch.com/products/ rating.html

对比将逻辑存储在数据库中,而不是将逻辑存储在Excel电子表格中:

  1. 与Excel相比,数据库中的逻辑更难测试和开发,因为Excel提供了即时反馈。
  2. 与Excel相比,数据库的表现力更少(更少)。
  3. 您可以对代码进行颜色编码,并将各种其他视觉提示添加到Excel中,以使错误条件等真正脱颖而出。

您现在可以想象,现在当然,由Web服务驱动的Excel规则引擎并不能适应所有情况。这不是这里唯一的解决方案。

我要说的是,请确保在可用性/表达性/可测试性/性能方面做出正确的权衡。在我工作的地方,正确和有生产力比执行速度快更重要,因此我们使用Excel / Web服务。

为了扩展slavik262的评论,您最终真正希望使用规则引擎实现的是抽象和泛化,以最大程度地减少运动部件并提高可靠性,可测试性和可理解性。以我的经验,与甚至只是简单地创建基于Java的规则相比,数据库规则引擎通常是次优的。只要它们被正确地沙盒化和组织化,并且隐藏在通用且一致的界面后面,它们就可以正常工作。

在我的公司中,这取决于规则的规模以及规则随我们变化的频率而变化的频率。评级保险-Excel,毫无疑问。一些状态特定的逻辑?接口的Java规则文件就足够了。


Dav*_*e F 5

如果您不需要根据规则的组成部分执行搜索,则可以将规则存储在数据库中的两个字段中。在一个条件下执行语句,在另一个条件下执行语句。

id, name, description, condition, statement
Run Code Online (Sandbox Code Playgroud)

您的规则可以使用 JSON 或某种类似的格式存储。

我需要定义一些我将使用的术语。有原子术语、系统值与用户输入的值进行比较,评估为真/假,以及复杂术语、使用逻辑运算符组合的术语。

原子术语中,var表示系统将提供的值(例如访问者数量或唯一访问者数量)。比较确定如何根据value评估var。该是用户生成的数字或字符串。当 var 和 value 都是数字时,比较可以是“<”、“<=”、“=”、“">=”或“">”。当 var 和 value 都是字符串时,比较可以是“等于”、“开始于”、“结束于”或“包含”。原子项可以存储如下:

{ var: varName, comp: comparison, value: numberOrString }
Run Code Online (Sandbox Code Playgroud)

您可以使用以下格式存储由连词、析取和否定(和/或/不)组成的复杂术语。

// Conjunction
{ op: "and", terms: [ term, ..., term ] }

// Disjunction
{ op: "or", terms: [ term, ..., term ] }

// Negation
{ op: "not", term: term }
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用这些方法构建评估为真/假的语句。示例如下:

{ op: "and", terms: [
    {op "or", terms: [
        { field: "numVisitors", comp: ">", value: 1000 },
        { field: "numUniqueVisitors", comp: ">=" 100 }
    ]},
    { op: "not", term: {
        { field: "numVisitors", comp: "<", value: 500 }
    }}
]}
Run Code Online (Sandbox Code Playgroud)

上例中,当访客数大于 1000 或独立访客数大于等于 100,且访客数不小于 500 时,则为 true。

然后,当规则评估为 true 时,您可以执行您所说的“语句”。