微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在postgresql中实现“type is <typeName> table of rowid index by”的概念来比较表数据和新插入的数据

如何解决如何在postgresql中实现“type is <typeName> table of rowid index by”的概念来比较表数据和新插入的数据

我正在尝试将下面的代码从 oracle 转换为 postgres(基本上目标是根据某个日期在表中插入一些记录而不重叠,如果日期范围重叠,它应该引发触发器。)但是经过很多努力不知道怎么做?

DECLARE
    V_check PLS_INTEGER;
BEGIN
    SELECT COUNT(*) INTO V_check
    FROM   user_objects
    WHERE  object_name = 'STORE_ROWID'
    AND    object_type = 'PACKAGE';
    IF V_check=0 THEN
        EXECUTE IMMEDIATE 'CREATE PACKAGE store_rowid AS'
        ||CHR(10)||'  TYPE T_rowid IS TABLE OF ROWID INDEX BY BINARY_INTEGER;'
        ||CHR(10)||'  T_newones    T_rowid;'
        ||CHR(10)||'  T_empty      T_rowid;'
        ||CHR(10)||'END store_rowid;';
    END IF;
END;

CREATE OR REPLACE TRIGGER biu_base_host
    BEFORE INSERT OR UPDATE ON BASE_HOST
    BEGIN
        STORE_ROWID.T_newones := STORE_ROWID.T_empty;
END biu_base_host;

CREATE OR REPLACE TRIGGER aiufr_base_host
    AFTER INSERT OR UPDATE ON BASE_HOST
    FOR EACH ROW
    BEGIN
        STORE_ROWID.T_newones(STORE_ROWID.T_newones.COUNT+1) := :NEW.ROWID;
END aiufr_base_host;

CREATE OR REPLACE TRIGGER aiu_base_host
    AFTER INSERT OR UPDATE ON BASE_HOST
    DECLARE
        r           BASE_HOST%rOWTYPE;
        V_count     INTEGER;
        V_status    PLS_INTEGER;
        C_lockid    CONSTANT PLS_INTEGER := 1001;

    BEGIN
    V_status := DBMS_LOCK.request(C_lockid,DBMS_LOCK.x_mode,release_on_commit=>TRUE);
    IF V_status NOT IN (0,4)
    THEN
        RAISE_APPLICATION_ERROR(-20102,'DBMS_LOCK.request ERROR,rc='||V_status);
    END IF;

    FOR i IN 1..STORE_ROWID.T_newones.COUNT
    LOOP
        SELECT  * INTO r
        FROM    BASE_HOST
        WHERE   ROWID = STORE_ROWID.T_newones(i);

        SELECT  COUNT(*) INTO V_count
        FROM    BASE_HOST
        WHERE   ROWID <> STORE_ROWID.T_newones(i)
        AND     ZONE_ID = r.ZONE_ID
        AND     SITE_ID = r.SITE_ID
        AND     ORG_ID = r.ORG_ID
        AND     (start_date BETWEEN r.start_date AND r.end_date
                OR end_date BETWEEN r.start_date AND r.end_date
                OR (start_date < r.start_date AND end_date > r.end_date));

        IF V_count <> 0 THEN
            RAISE_APPLICATION_ERROR(-20001,'Range from '||
                TO_CHAR(r.start_date,'YYYYMMDD-HH24MISS') ||
                ' to '||
                TO_CHAR(r.end_date,'YYYYMMDD-HH24MISS')||
                ' overlaps existing records');
        END IF;
    END LOOP;
END aiu_base_host;

解决方法

我认为排除约束是实现这一目标的完美方式,我编写了以下代码来实现相同的功能:

创建扩展 btree_gist; 创建表 base_host( zone_id numeric(3),site_id numeric(3),org_id VARCHAR(16),start_date date,end_date date,reserved_capacity numeric(5,2),last_update date,user_id VARCHAR(32),EXCLUDE USING GIST (zone_id WITH =,site_id WITH =,org_id WITH =,daterange("start_date","end_date") WITH &&));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。