我的 SQL 代码的正确原型是什么?

What is the right prototype for my SQL code?

我是新手 SQL,我正在尝试使用 SQLcl:

对这两个 table 应用三角函数
prodc

( PRODC_NAME, 折扣字符 (1) 默认值 'N', PK 主键 (PRODC_NAME));

peopleOrder
(  ORDERID, PRODC_NAME,
   PRIMARY KEY (ORDERID, PRODC_NAME),
   FOREIGN KEY (PRODC_NAME) REFERENCES PRODC (PRODC_NAME));

我希望我的触发器执行以下操作:

当我将行更新或插入到 peopleOrder 时,触发器应检查行的 product_name 是否在位于 [=17= 的折扣列中具有值 'N' ] table;如果它没有 'N' 值,它应该显示一条错误消息。

我尝试了很多方法和下面的触发器,但是当我插入行时,触发器似乎不起作用并且对行没有影响:

CREATE OR REPLACE TRIGGER constraint_1
After UPDATE OR INSERT on peopleOrder 
for each row
begin
    if not (:new.prodc_name in 
    (select prodc_name from prodc where discounted = 'N' )) then
     RAISE_ERROR(-30001, 'No product can be ordered 
 !');
    END IF; 
    INSERT INTO peopleOrder  VALUES (:new.ORDERID, :new.PRODC_NAME);
END; 
/

我的插入命令是:

INSERT INTO peopleOder (ORDERID, PRODC_NAME) 
VALUES (251, 'Puton'); 

和 'Puton' 在 prodc table.

的折扣列中具有值 'N'

您首先需要了解触发器是什么。它是 作为 导致其触发的语句的一部分运行的一段代码。因此,您 不能 引用 table 导致它触发。通常这是完全没有必要的。每个行触发器都可以访问 2 行:现有数据(旧)和结果数据(新)的副本。更新已填充并且 Insert/Delete 仅 new/old 适用于操作。 before 语句触发器可以修改新数据,after 触发器不能。这些行允许您在没有 DML 或 select 的情况下处理 table 中的列。 (但是你不能 'scan' table)。在任何级别,触发器都可能引发异常,从而停止整个过程和调用语句。如果未引发异常,则处理调用收益。有关更完整的描述,请参阅 PL/SQL Language Reference 或您使用的 Oracle 版本 运行。 在这种情况下,您的触发器分解为一个 if 声明。

-- Revised. Orig missed that flag comming from different table.

    create or replace trigger constraint_1
    before update or insert on peopleOrder 
    for each row
    declare 
        dis_num integer; 
    begin  
        select count(*)
          into dis_num
          from product 
         where discounted != 'N'
           and product_name = :new.product_name
           and rownum < 2; 
        if dis_num != 0 then 
           raise_application_error(-20001, 'No discounted product can be ordered!');
        end if; 
    end constraint_1;



-- Orig ==============================================
    CREATE OR REPLACE TRIGGER constraint_1
    before UPDATE OR INSERT on peopleOrder 
    for each row
    begin
        if :new.discounted = 'N' then
         RAISE_APPLICATION_ERROR(-20001, 'No discounted product can be ordered')
        end if; 
    END; 
    /