在 Oracle 中执行业务规则

发布于 2024-09-10 22:08:43 字数 198 浏览 9 评论 0原文

我有一张名为 Book 的桌子。该表有 3 列,即 ID、价格和折扣。如果价格大于 200,则折扣应为 20%。在 Book 表中插入数据时,应根据价格值更新折扣值。在 Book 表中插入或更新数据时如何处理?

请提供所有可能的解决方案。我不想执行存储过程。让我们假设当用户在 Book 表中插入/更新数据时,他不会执行函数或过程。

请提供解决方案。

I have a table called Book. This table has 3 columns viz id, price and discount. If price is greater than 200 then discount should be 20%. While inserting data in Book table the discount value should be updated based on price value. How can this be handled when data is inserted or updated in Book table?

Please provide all possible solutions. I don't want to execute a stored procedure. Let us suppose when user is inserting/updatng data in Book table so he does not execute a function or procedure.

Please provide solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

Bonjour°[大白 2024-09-17 22:08:43

如果您不想使用存储过程,那么唯一的其他选择就是触发器。

create or replace trigger book_discount_rule
    before insert, update on BOOK
    for each row
begin
    if :new.price > 200 
    then
       :new.discount := 20;
    else
       :new.discount := 0;            
    end if;
end;

我个人不喜欢这个解决方案,正是因为触发器是不可见的。也就是说,如果用户运行这个插入语句……

insert into book 
     values (book_id_seq.nextval, 250, 30)
/

他们可能会感到困惑为什么存储的DISCOUNT与他们提交的值不同。我宁愿使用存储过程来执行业务规则。

不管怎样,在现实生活中,我更愿意通过 API 来实现规则,而不是对值进行硬编码。但这是一个品味问题。


正如 Jeffrey 指出的那样,最好在表上使用检查约束来备份触发器(或过程),以保证折扣适合价格。

alter table book 
    add constraint book_discount_ck 
    check ((price > 200 and discount = 20) or discount = 0)
/

在没有存储过程或触发器的情况下应用约束需要用户了解业务规则。不幸的是,Oracle 没有提供一种机制来将特定的错误消息附加到我们的检查约束中。使用有意义的消息引发上下文特定异常的能力是存储过程的优点之一。

If you don't want to use a stored procedure then the only other option is a trigger.

create or replace trigger book_discount_rule
    before insert, update on BOOK
    for each row
begin
    if :new.price > 200 
    then
       :new.discount := 20;
    else
       :new.discount := 0;            
    end if;
end;

Personally I dislike this solution, precisely because triggers are invisible. That is, if the user runs this insert statement ...

insert into book 
     values (book_id_seq.nextval, 250, 30)
/

... they may be puzzled why the stored DISCOUNT is different from the value they submitted. I would rather use a stored procedure to enforce business rules.

Either way, in real life I would prefer to have the rules implemented through an API rather than hard-coding the values. But that is a matter of taste.


As Jeffrey points out it is a good idea to back up the trigger (or procedure) with a check constraint on the table to guarantee that the DISCOUNT is appropriate to the price.

alter table book 
    add constraint book_discount_ck 
    check ((price > 200 and discount = 20) or discount = 0)
/

Applying a constraint without either a stored procedure or o trigger requires the user to know the business rule. Unfortunately Oracle does not provide a mechanism to attach a specific error message to our check constraint. The ability to raise a context specific exception with a meaningful message is one of the advantages of stored procedures.

莫相离 2024-09-17 22:08:43

不使用任何存储过程:

ALTER TABLE "Book" ADD (
  CONSTRAINT discount_check
  CHECK (price < 200 OR discount = 0.2)
);

这样,没有人能够插入或更新一本书,除非他们插入适当的价格和折扣值。 *

*(为了万无一失,您还可以向这些列添加 NOT NULL 约束)

Without using any stored procedures:

ALTER TABLE "Book" ADD (
  CONSTRAINT discount_check
  CHECK (price < 200 OR discount = 0.2)
);

This way, no-one will be able to insert or update a Book unless they insert appropriate values for price and discount.*

*(to be bulletproof, you'd add NOT NULL constraints to these columns as well)

童话里做英雄 2024-09-17 22:08:43

如果折扣始终只是价格的函数,那么我建议将其设置为视图中的计算列。给定一个包含 idprice 列的表 Books,创建一个如下视图:

CREATE VIEW books_view AS (
  SELECT
    id,
    price,
    CASE WHEN price > 200 THEN 0.20 ELSE 0 END discount
  FROM books
  );

这样用户就无法将折扣设置为不正确的值。使用触发器解决方案,折扣可以在插入时正确设置,但随后可以通过以后的更新进行更改。

If the discount is always simply a function of the price, then I would suggest making it a calculated column in a view. Given a table Books with columns id and price, create a view like this:

CREATE VIEW books_view AS (
  SELECT
    id,
    price,
    CASE WHEN price > 200 THEN 0.20 ELSE 0 END discount
  FROM books
  );

This way a user cannot set the discount to an incorrect value. With the trigger solutions, the discount may be set correctly on insert but then could be changed by later updates.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文