SQL: 在子类型插入之前创建触发器

SQL: Creating a trigger before subtype insert

所以我处理的情况可以描述为:
基本上,我有两种类型的汽车和超级跑车

CREATE OR REPLACE TYPE CAR_T AS OBJECT (
  id VARCHAR (10),
  fuel_type VARCHAR (10)
) NOT FINAL;

CREATE OR REPLACE TYPE SUPERCAR_T UNDER CAR_T (
  number_cylinders  number(10)
);

将超级跑车插入汽车时:

INSERT INTO CAR VALUES(SUPERCAR_T(99, 'petrol', 12));

我想在插入 CAR 之前检查气缸数是否大于 6 table WITHOUT CREATING A TABLE FOR SUPERCARS:

CREATE OR REPLACE TRIGGER INSERT_SUPERCAR
    BEFORE INSERT ON CAR
    REFERENCING NEW AS NEW
    FOR EACH ROW

    BEGIN
        IF :NEW.number_cylinders < 6 THEN
                RAISE_APPLICATION_ERROR(-20001,'Not a supercar');
    END;

我总是遇到以下错误:

bad bind variable 'NEW.number_cylinders'

看来我无法直接访问子类型的属性。我的问题是如何修复这样的错误,有没有更好的方法来使用检查约束而不为超级跑车创建新的 table?

您可以使用 :NEW.OBJECT_VALUE pseudo-column and the TREAT function 将对象转换为 SUPERCAR_T 类型,然后检查 number_cylinders 属性:

CREATE OR REPLACE TRIGGER INSERT_SUPERCAR
  BEFORE INSERT ON CAR
  REFERENCING NEW AS NEW
  FOR EACH ROW
BEGIN
  IF :NEW.OBJECT_VALUE IS OF (SUPERCAR_T)
      AND TREAT(:NEW.OBJECT_VALUE AS SUPERCAR_T).number_cylinders < 6
  THEN
    RAISE_APPLICATION_ERROR(-20001,'Not a supercar');
  END IF;
END;
/

然后:

INSERT INTO CAR VALUES(SUPERCAR_T(99, 'petrol', 12));

有效但是:

INSERT INTO CAR VALUES(SUPERCAR_T(99, 'petrol', 4));

引发异常:

ORA-20001: Not a supercar

您还可以使用 CHECK 约束:

ALTER TABLE car ADD CONSTRAINT car__supercar_cylinders__chk CHECK (
  OBJECT_VALUE IS NOT OF (SUPERCAR_T)
  OR TREAT(OBJECT_VALUE AS SUPERCAR_T).number_cylinders >= 6
);

ALTER TABLE car ADD CONSTRAINT car__supercar_cylinders2__chk CHECK (
  TREAT(OBJECT_VALUE AS SUPERCAR_T).number_cylinders IS NULL
  OR TREAT(OBJECT_VALUE AS SUPERCAR_T).number_cylinders >= 6
);

db<>fiddle here