【发布时间】:2021-06-01 01:34:19
【问题描述】:
我正在尝试将下面的代码从 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;
【问题讨论】:
-
Postgres 9.2 是 no longer supported 如果您今天迁移现有项目,请不要从完全过时的 Postgres 版本开始。你应该直接使用 Postgres 13
-
在 Postgres 中,您可以定义 exclusion constraint 以防止范围重叠。无需触发器或 PL/pgSQL
-
看看Migrate your mindset。虽然它使用 SQL Server 到 Postgres,但它同样适用于从 Oracle 转换。您需要在转换之前确定代码/用户类型的用途。此外,这要么是非常古老的 Oracle,要么只是糟糕的 Oracle,单个复合触发器也会做同样的事情。但是忘记直接翻译。 Postgres 没有包,没有集合,也没有 rowid。我重复@a_horse_with_no_name 的建议,定义一个排除约束,然后去掉所有代码。并升级。
-
谢谢,我认为排除约束是实现这一目标的完美方法,我编写了以下代码来实现相同的功能:CREATE EXTENSION 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 &&));
-
您应该要求@a_horse_with_no_name 重新发布他们的帖子作为答案然后接受它,或者发布您的解决方案作为答案然后接受它。已回答的问题可以帮助后来的提问者解决同样的问题。请不要将已回答的问题留在未回答的状态。
标签: postgresql oracle plsql triggers postgresql-9.2