在数据库中存储的业务逻辑(Storing Business Logic in Database)

2019-07-30 08:05发布

我们想写一些关于某些数据来建立报告基础上工作的业务逻辑规则。 不知道这是最好将它们存储在数据库中的MySQL。

它可以有规则的链,然后一个语句的结果,如上所示。

Answer 1:

对于建筑物的报告,你可以在任何编程语言转换业务逻辑。 并利用数据库中的数据来生成报告。

对业务逻辑存储在数据库

我放在表达能力较高的价值,我没有找到SQL的空间,所有的表现力。 用你手头上最好的工具为最合适的任务。 用逻辑和高阶概念摆弄最好在最高级别上完成的。 因此,存储和海量数据处理,最好在服务器级别在存储过程中完成的,大概。

但是这取决于。 如果你有多个应用程序与一个存储机制的相互作用,并要确保它保持其完整性和工作流程,那么你应该卸载所有的逻辑到数据库服务器。 或者,准备在多个应用程序来管理并行开发。

来源: 存储过程中参数为/侵犯商业逻辑

也可以看看:

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


Answer 2:

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;


Answer 3:

针对这样的“软编码”的经营逻辑的争论: http://thedailywtf.com/Articles/Soft_Coding.aspx

“我们发现自己软编码的原因是因为我们害怕改变。在不改变正常的恐惧,但令人担心的是,我们写的代码将不得不改变业务规则变化的结果,这是一个非常愚蠢的恐惧有。该软件的整点(因此,“软”)是可以改变它将会改变。从业务规则改变隔离你的软件的唯一途径是建立一个完全通用的程序是没有的所有业务规则还可以实施任何规则。哦,他们已经建立了一个工具,这就是所谓的C ++,和Java。和C#,而且基本的。而且,我敢说,COBOL。”



Answer 4:

我可以给你的是,你应该解决这个问题的方法,而不是答案本身。

一般的方法来设计一个数据库来存储复杂的数据像这样的设计,你会保留在内存中的对象,然后尝试,并相应地设计数据库的方式。 您将在编程语言后,所有被评估的规则。 该过程将是如下:第一类图

然后,是时候把它转换成一个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);


Answer 5:

我认为需要做的事情首先是问题,你是否不应该把规则在数据库中开始。

数据库是一个重手的解决方案 ,也常常只是没有必要的。

已经处理了各种形式,包括数据库驱动,我可以告诉你,它可以得到真正令人沮丧和非生产性的规则引擎,真的很快。 一个我见过发生大的失误的尝试写自己的ad-hoc规则语言并使用通过数据库驱动条件逻辑。 最起码,使用已经证明了的语言(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规则文件就足够了就好了。



Answer 6:

所以,如果我理解正确,你正在寻找使用前端,让人们以动态创建将被应用到(其中在运行时的条款基础上正在使用的规则动态地建)查询逻辑是什么?

如果是这样的话,你将需要相当具体什么条件,他们可以在自己的规则来选择(在什么样的价值(列变化),因此他们只能有针对存在于您从报告数据集列条件规则)。

如果我正确理解你的问题,我会被映射出你希望他们能够选择针对条件,表/列开始。 这将是你的控件的网页设计的规则。

但是,如果你只是问如何存储规则一旦他们在数据库中选择,我建议将其存储在包含单个表:

ID  |  RuleSetName         |  Table     |  Column      |  Comparison  |  Value   |  Percentage  |  Notes  |  CreatedDate  |  Created By
1   |  'VisitorAnalytics'  |  Visitors  |  SUM(Views)  |  >           |  null    |  10          |  n/a    |  1/1/2012     |  JohnDoe

然后,一旦创建了这些记录,你会被表注入from子句中使用它们,列到你的动态sql的where子句。

我知道这听起来令人困惑,但你问是一个相当复杂的解决方案。 但最终你只是想一起存储规则一个地方,你可以遍历动态构建,然后执行一个SQL生成报告。 希望这点你在正确的方向。



Answer 7:

我猜测规则的目的是从现有的数据库表名计算字段(或表)。 否则,仅仅是报告的目的,你可以转储数据到Excel,让用户使用Excel函数和数据透视表为他们的目的。

关键的问题是你怎么到的规则转化为行动。 如果目的是只存储业务规则,这样你就可以创建业务规则的报告,然后在SQL一个简单的数据结构就足够了。

但是,如果要打开的规则转换成代码,你需要考虑其中的代码将运行。 当数据被存储在SQL中,你有几种选择:

  • 创建SQL代码,将提取“业务规则”的结果。
  • 创建用户定义的函数,将解析并执行业务规则。
  • 提取数据到另一个环境,例如C ++或C#,并运行该代码在那里。

我朝第一的这些偏差。 主要的原因是,它限制了工具之一:SQL。

我不知道你的规则正在做的; 关键是“陈述”部分做了什么。 让我假定这是一个恒定的或可以计算上的数据的表达。 在这种情况下,你的规则开始看起来很像一个case语句。 一个需要注意的是,该声明可能需要在数据表看多行(处理随时间的变化)。

我的建议是将这些规则存储在数据库中。 这种存储将允许您从使用SQL编码业务规则的序列构造查询。 MySQL允许动态SQL(现在)。 不知道多一点对基本表和规则,这是很难给出更多的信息。

我可以说,我设计了用于情景分析一个更复杂的系统。 该方案自身储存在电子表格中,并在一系列表格,常量,等等 - 就像你的业务规则。 通过使用SQL(和一些Excel)中工作的系统改造方案的电子表格表示成(巨)查询。 然后,它可以运行查询,生成相关报表。 该系统已被证明灵活,高性能,功能强大。



Answer 8:

如果您不需要进行基于对规则的组件搜索,那么你可以存储在数据库中的两个字段的规则。 根据该声明得到一个执行的条件和在另一个执行该语句。

id, name, description, condition, statement

你的规则可以使用JSON或一些类似的格式存储。

我需要定义,我会使用一些术语。 有原子而言 ,与通过计算结果为真/假,和复杂的术语用户输入的值的系统值,术语使用逻辑运算符相结合。

原子术语 ,VAR表示一个值,该系统将提供(如访客或唯一访问者数的数目)。 比较确定的VAR是如何对价值进行评估。 该是一个数字或字符串,用户产生。 当var和值都是数字,比较可以是 “<”, “<=”, “=”, “> =”,或 “>”。 当var和值都是字符串,比较可能是“平等”,“开始”,“结尾”,或者“含有”。 原子能方面可以存储如下:

{ var: varName, comp: comparison, value: numberOrString }

你可以存储由连词,析取的复杂条款,否定(和/或/不)使用以下格式。

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

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

// Negation
{ op: "not", term: term }

然后,您可以建立一个评估为真/假使用这些方法的声明。 一个例子如下:

{ op: "and", terms: [
    {op "or", terms: [
        { field: "numVisitors", comp: ">", value: 1000 },
        { field: "numUniqueVisitors", comp: ">=" 100 }
    ]},
    { op: "not", term: {
        { field: "numVisitors", comp: "<", value: 500 }
    }}
]}

上面的例子等同于真正当访问者的数量大于1000或唯一访问者的数量大于或等于100,和访问者的数量不小于500。

然后,您可以执行你提到的一个“说法”是什么时候的规则计算结果为true。



Answer 9:

一个简单的方法来做到这一点是使用面向对象数据库。 还有,方法被封装用槽为对象,并且它们甚至可以在数据库(例如触发器)来执行。

现在,如果你坚持一个SQL数据库,你可以做的是使用一种动态编程语言,并有一个表来存储代码,可能关联到其他表或行。

几年前,我看到了阿尔及利亚政府的税务系统,其中他们计划来存储业务规则(税收规则),如RDBMS Visual Basic代码招标。

你可以选择,你可以很容易地嵌入解释您的应用程序(Common Lisp的任何语言http://ecls.sourceforge.net ;或http://common-lisp.net/project/armedbear/如果你写在你的应用JAVA),Lua中,使用Javascript,计划等。

它会倾向于Common Lisp的或计划,因为这些语言,你可以很容易地编写为业务规则的DSL。

给出的示例可以写成一个符号表达式如:

(rule :name "RuleName"
      :description "Some description"
      :body (if (and (< (change-in total-visitor)   (percent 10))
                     (> (change-in unique-visitors) (percent 2)))
                (do-something)))

在这样口齿不清符号表达可以可读地与打印或打印到字符串的运营商进行打印,这样就可以插入此表达到SQL数据库:

insert into rules (id,expression) values (42,"(rule :name \"RuleName\"
      :description \"Some description\"
      :body (if (and (< (change-in total-visitor)   (percent 10))
                     (> (change-in unique-visitors) (percent 2)))
                (do-something)))");

你可以从SQL拿回来,用口齿不清READ读取它作为一个象征性的表达或读FROM-STRING运营商,然后用正确的DSL,您可以用口齿不清EVAL运营商对其进行评估:

;; with the right DSL written:
(eval (read-from-string (sql-select (expression) :where (= id 42))))


Answer 10:

使用存储过程的唯一可能的好处是使用不同的技术,比如Python和Java应用程序访问数据库的可能性。



Answer 11:

我想,你已经对现有业务逻辑的规则和要求记录在案?..这是为你的设计方案,选择最佳的客户端开发工具和设计自己的客户端程序和过程的最重要因素。 我这样做是为了我的典当行管理程序。 应用程序的功能是完全表驱动。 它具有控制表中,管理员可以以修改系统的工作方式改变有效参数。 当与结构化编程技术相结合,这最小化的编程代码的修改的量。 银行应用程序也具有复杂的业务规则一个很好的例子。



文章来源: Storing Business Logic in Database