首页 > 解决方案 > 过程、游标和触发器可以在对象关系数据库的用户定义类型中使用吗?

问题描述

我是对象关系数据库的新手,目前正在通过教科书自学。

在 Oracle 中使用 UDT 对象表创建用户定义类型时,是否可以使用过程、游标、触发器等,或者这些功能仅可用于关系数据库?

我自己花时间在网上搜索以找到这个答案,但我已经阅读了很多关于这个主题的内容,这让我感到困惑,所以我认为可以在这里简单地回答(希望如此)。

标签: oraclestored-proceduresplsqluser-defined-typesobject-relational-model

解决方案


在 Oracle 中使用 UDT 对象表创建用户定义类型时,是否可以使用过程、游标、触发器等。

是的。

还是这些功能仅适用于关系数据库?

不。


CREATE TYPE person IS OBJECT(
  id NUMBER,
  first_name VARCHAR2(50),
  last_name VARCHAR2(50),
  mother REF PERSON,
  MEMBER FUNCTION full_name( self IN PERSON )
    RETURN VARCHAR2,
  MEMBER FUNCTION children (self IN PERSON )
    RETURN SYS_REFCURSOR
);

CREATE TABLE people OF person (
  ID PRIMARY KEY
);

CREATE TYPE BODY person IS
  MEMBER FUNCTION full_name( self IN PERSON )
    RETURN VARCHAR2
  IS
  BEGIN
    RETURN self.first_name || ' ' || self.last_name;
  END;

  MEMBER FUNCTION children( self IN PERSON )
    RETURN SYS_REFCURSOR
  IS
    p_cursor SYS_REFCURSOR;
  BEGIN
    OPEN p_cursor FOR
    SELECT VALUE(p) AS child
    FROM   people p
    WHERE  p.mother.id = self.id;

    RETURN p_cursor;
  END;
END;
/

CREATE SEQUENCE people__id__seq;

CREATE TRIGGER people__new__trg
BEFORE INSERT ON people
FOR EACH ROW
  WHEN (new.ID IS NULL)
BEGIN
  :new.ID := PEOPLE__ID__SEQ.NEXTVAL;
END;
/

INSERT INTO people ( first_name, last_name )
SELECT 'Alice', 'Abbot' FROM DUAL UNION ALL
SELECT 'Belle', 'Burns' FROM DUAL UNION ALL
SELECT 'Carol', 'Charles' FROM DUAL;

UPDATE people
SET mother = ( SELECT REF(p) FROM people p WHERE id=2 )
WHERE id = 3;

然后:

SELECT id,
       first_name,
       last_name, 
       p.mother.id
FROM   people p;

输出:

身份证 | FIRST_NAME | LAST_NAME | 母亲身份证
-: | :--------- | :-------- | --------:
 1 | 爱丽丝 | 方丈 |      
 2 | 美女 | 烧伤 |      无效的
 3 | 卡罗尔 | 查尔斯 | 2

显示触发器已工作,ID为行生成值。

DECLARE
  p_person PERSON;
  p_child  PERSON;
  p_cursor SYS_REFCURSOR;
BEGIN
  SELECT VALUE( p )
  INTO   p_person
  FROM   people p
  WHERE  id = 2;

  p_cursor := p_person.children();
  DBMS_OUTPUT.PUT_LINE( 'Children of ' || p_person.full_name );

  LOOP
    FETCH p_cursor INTO p_child;
    EXIT WHEN p_cursor%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE( p_child.full_name );
  END LOOP;

  CLOSE p_cursor;
END;
/

输出:

贝尔伯恩斯的孩子们
卡罗尔·查尔斯

显示函数中的光标示例。程序也是可能的,并作为 OP 的示例。

db<>在这里摆弄


推荐阅读