如何比较触发器中两个不同表的两个属性?

时间:2018-01-12 18:21:45

标签: database oracle oracle-sqldeveloper

所以我有两张桌子:

CREATE TABLE SALE(  
OID_PA NUMBER(*,0) PRIMARY KEY,
Amount INTEGER NOT NULL,
Delivery_DATE DATE NOT NULL,
OID_V NUMBER(*,0) NOT NULL,
CONSTRAINT "AMOUNTCHECK" CHECK(Amount >=0),
FOREIGN KEY (OID_V) REFERENCES TICKET(OID_V));

CREATE TABLE PRODUCT
(   Code NUMBER(*,0) PRIMARY KEY,
    Stock INTEGER NOT NULL,
    Price NUMBER(4,2) NOT NULL,
    Production_Cost NUMBER NOT NULL,
    Model VARCHAR2(50) NOT NULL,
    TipoMueble VARCHAR2(50) NOT NULL,
    TipoMaterial VARCHAR2(50) NOT NULL,

    OID_PA NUMBER(*,0) NOT NULL,

    CONSTRAINT "TipoMueble" CHECK(TipoMueble IN 
    ('Canteado','Complementos','Glaciar',
    'GrupoDiseño','Tiradores','Vitrinas')),
    CONSTRAINT "TipoMaterial" CHECK(TipoMaterial IN ('Aluminio','Lacados',
    'Polilaminado','Madera','Cristal','Chapa','Granito','Formica',
    'Aglomerado','Marmol','Elementos de ferreteria')),
    CONSTRAINT "StockNegativo" CHECK(Stock >=0),
    CONSTRAINT "Precio" CHECK(Price>=0),
    CONSTRAINT "CosteProduccion" CHECK (Production_cost>=0),

    FOREIGN KEY (OID_PA) REFERENCES PAQUETE(OID_PA));

现在我想创建一个触发器,我修改属性" Amount"在表格" SALE"然后它应该检查表" PRODUCT"。 如果" stock" (在PRODUCT中)小于金额(在SALE中)然后

RAISE_APPLICATION_ERROR(-20003, 'Not enough stock');

但我不知道如何在两张桌子上同时进行触发检查。 现在我的代码现在看起来很像,它也有一些我不确定如何解决的错误。

CREATE OR REPLACE TRIGGER TR_ENOUGH_STOCK
AFTER INSERT OR UPDATE OF Amount ON SALE
 BEGIN

    SELECT a.Amount, b.Stock 
    FROM ( SALE a inner join PRODUCT b on (a.Code = b.Code))

    IF b.Stock < a.Amount THEN 
        RAISE APPLICATION ERROR(-20003, 'Not enough stock');
    END IF;
END;
/

我收到以下错误:

Error(209,5): PL/SQL: SQL Statement ignored
Error(212,5): PL/SQL: ORA-00933: SQL command not properly ended
Error(214,9): PLS-00103: Encountered the symbol "IF" when expecting one of 
the following:     ; <an identifier> <a double-quoted delimited-identifier> 

1 个答案:

答案 0 :(得分:0)

这是一个如何做到这一点的例子。

创建表格&amp;触发器:

SQL> create table sale (oid_pa number, amount number);

Table created.

SQL> create table product (code number, stock number, oid_pa number);

Table created.

SQL>
SQL> create or replace trigger trg_biu_stock
  2    before insert or update
  3    on sale
  4    for each row
  5  declare
  6    l_stock product.stock%type;
  7  begin
  8    select stock into l_stock
  9      from product
 10      where oid_pa = :new.oid_pa;
 11
 12    if :new.amount > l_stock then
 13       raise_application_error(-20000, 'Not enough stock');
 14    end if;
 15  end;
 16  /

Trigger created.

SQL>

将样本记录插入PRODUCT表:

SQL> insert into product values (1, 100, 10);

1 row created.

SQL> insert into product values (2, 50, 20);

1 row created.

SQL> select * From product;

      CODE      STOCK     OID_PA
---------- ---------- ----------
         1        100         10
         2         50         20

SQL>

让我们测试一下:

SQL> -- 90 is less OID_PA = 10 stock value (which is 100)
SQL> insert into sale values (10, 90);

1 row created.

SQL> -- let's try to update it to a value larger than stock value:
SQL> update sale set amount = 200 where oid_pa = 10;
update sale set amount = 200 where oid_pa = 10
       *
ERROR at line 1:
ORA-20000: Not enough stock
ORA-06512: at "HR.TRG_BIU_STOCK", line 9
ORA-04088: error during execution of trigger 'HR.TRG_BIU_STOCK'


SQL> -- how about a value which doesn't exceed the stock value?
SQL> update sale set amount = 5 where oid_pa = 10;

1 row updated.

SQL> select * From sale;

    OID_PA     AMOUNT
---------- ----------
        10          5

SQL>

你的尝试开始:除了触发器代码语法错误之外,它无论如何都无法工作,因为你无法引用表触发器是基于因为它现在正在被更改,即它是变异。在这种情况下,Oracle会引发错误(请参阅下面的示例)。正确的方法是使用:new或:old来引用该表的列,就像我一样(参见上面的例子)。

SQL> create or replace trigger trg_biu_stock
  2    before insert or update
  3    on sale
  4    for each row
  5  declare
  6    l_stock product.stock%type;
  7  begin
  8    select p.stock into l_stock
  9      from product p
 10      join sale s
 11      on s.oid_pa = p.oid_pa
 12      where p.oid_pa = :new.oid_pa;
 13
 14    if :new.amount > l_stock then
 15       raise_application_error(-20000, 'Not enough stock');
 16    end if;
 17  end;
 18  /

Trigger created.

SQL> update sale set amount = 50 where oid_pa = 10;
update sale set amount = 50 where oid_pa = 10
       *
ERROR at line 1:
ORA-04091: table HR.SALE is mutating, trigger/function may not see it
ORA-06512: at "HR.TRG_BIU_STOCK", line 4
ORA-04088: error during execution of trigger 'HR.TRG_BIU_STOCK'


SQL>