DBVis/PL SQL: IF EXIST - 如果可能如何正确构建
DBVis/PL SQL: IF EXIST - how to structure correctly if possible
使用 DBVis SQL 指挥官(因为我在这段代码中使用 "begin" 和 "end",我相信这段代码是以 PL SQL 方式执行的)我正在尝试执行我编写的 sql 脚本作为我的新 "cleaning trigger"
我正在尝试在此脚本中使用 IF EXISTS 语句来仅在特定列确实包含数据(已批准或拒绝)时实现清理
此脚本旨在不使用插入(到其他表)语句(如果使用它们,即使没有数据可插入,它们也会以不希望的方式在其他表上触发其他触发器)除非某列中确实有(不为空)数据:
begin
IF EXISTS (SELECT *
FROM HUB_SEGMENTS
where APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
THEN
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO
HUB_REJECTED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE
FROM
"TESTDEMO".HUB_SEGMENTS
WHERE
APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Executed');
ELSE
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Not Executed');
end;
不幸的是,我在尝试 运行 时收到以下错误消息:
[Code: 6550, SQL State: 65000] ORA-06550: line 33, column 4:PLS-00103: Encountered the symbol ";" when expecting one of the following:
if
我很确定这取决于我构建 IF EXIST
的方式
当然,可能是在我的 PL SQL 代码中,在 DBVis SQL commander 中使用 IF EXIST 是不允许的——我还没有看到很多关于这个特定语句的文档来自甲骨文。如果是这样,是否会有另一个
我可以尝试并完成我在这里尝试做的事情的方式吗?
任何指导将不胜感激
你不需要我相信的 if exists
刚转
IF EXISTS (SELECT *
FROM HUB_SEGMENTS
where APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
THEN
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
到
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS where (APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED');
这是您的代码结构:
BEGIN
IF EXISTS (SELECT... FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
THEN
INSERT INTO HUB_APPROVED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO HUB_REJECTED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
ELSE
...;
END;
您可以很容易地看到缩进在最后一个 END
之前跳过级别:您缺少一个 END IF
来关闭 IF
块。 Oracle 试图告诉您,通过给您对应于最终 end;
的行并说:Encountered the symbol ;
when expecting one of the following: if
.
BEGIN
IF EXISTS (SELECT... FROM HUB_SEGMENTS WHERE APP_OR_REJECT IN ('APPROVED', 'REJECTED');
THEN
INSERT INTO HUB_APPROVED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO HUB_REJECTED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE FROM HUB_SEGMENTS WHERE APP_OR_REJECT IN ('APPROVED', 'REJECTED');
ELSE
...;
END IF; --> here
END;
奖励:您可以使用 IN
代替这些 OR
ed 条件。
旁注:如果性能无关紧要,那么,正如@zip 所建议的那样,不要理会 IF
块。可以直接运行两个INSERT
和DELETE
语句一前一后。如果 HUB_SEGMENTS
中没有符合搜索条件的数据,则无论如何都不会插入或删除任何内容。
感谢有用的评论 - 如果我使用非 oracle SQL(可能?),这些评论会起作用。不幸的是 运行 PL/SQL DBVis 上指向 oracle 数据库的 "exists" 脚本导致错误 - Exists 在 PL/SQL 脚本中不起作用(但应该在单个 SQL 显然是陈述)。
我发现结合 IF 使用变量解决了我的问题:
Declare
v_count NUMBER;
BEGIN
select COUNT(*)
INTO v_count
FROM HUB_SEGMENTS
WHERE APP_OR_REJECT is not null; --for each row where %new.columnname is not new --=> this would be far less "expensive" sql query, need to figure out how to syntax this
IF v_count >0
THEN
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO
HUB_REJECTED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE
FROM
"TESTDEMO".HUB_SEGMENTS
WHERE
APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Executed');
ELSE
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables NOT executed');
END IF;
end;
这成功地实现了我试图实现的目标(除非特定列中确实有数据,否则不会执行 Insert/Delete 语句,以避免奇怪地意外触发其他触发器)
一位同事告诉我,按照 "for each row where %new.columnname is not new =>..." 的方式做一些事情会 cpu 密集 sql 查询少得多,但我需要弄清楚如何语法这个。现在,上面的代码在 PL/SQL 中工作,指向 DBVis 中的 oracle 数据库。
如果我找到 "for each row..." 方法,我会 post 在这里作为评论
使用 DBVis SQL 指挥官(因为我在这段代码中使用 "begin" 和 "end",我相信这段代码是以 PL SQL 方式执行的)我正在尝试执行我编写的 sql 脚本作为我的新 "cleaning trigger"
我正在尝试在此脚本中使用 IF EXISTS 语句来仅在特定列确实包含数据(已批准或拒绝)时实现清理
此脚本旨在不使用插入(到其他表)语句(如果使用它们,即使没有数据可插入,它们也会以不希望的方式在其他表上触发其他触发器)除非某列中确实有(不为空)数据:
begin
IF EXISTS (SELECT *
FROM HUB_SEGMENTS
where APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
THEN
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO
HUB_REJECTED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE
FROM
"TESTDEMO".HUB_SEGMENTS
WHERE
APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Executed');
ELSE
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Not Executed');
end;
不幸的是,我在尝试 运行 时收到以下错误消息:
[Code: 6550, SQL State: 65000] ORA-06550: line 33, column 4:PLS-00103: Encountered the symbol ";" when expecting one of the following: if
我很确定这取决于我构建 IF EXIST
的方式当然,可能是在我的 PL SQL 代码中,在 DBVis SQL commander 中使用 IF EXIST 是不允许的——我还没有看到很多关于这个特定语句的文档来自甲骨文。如果是这样,是否会有另一个 我可以尝试并完成我在这里尝试做的事情的方式吗?
任何指导将不胜感激
你不需要我相信的 if exists 刚转
IF EXISTS (SELECT *
FROM HUB_SEGMENTS
where APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
THEN
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
到
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS where (APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED');
这是您的代码结构:
BEGIN
IF EXISTS (SELECT... FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED')
THEN
INSERT INTO HUB_APPROVED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO HUB_REJECTED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
ELSE
...;
END;
您可以很容易地看到缩进在最后一个 END
之前跳过级别:您缺少一个 END IF
来关闭 IF
块。 Oracle 试图告诉您,通过给您对应于最终 end;
的行并说:Encountered the symbol ;
when expecting one of the following: if
.
BEGIN
IF EXISTS (SELECT... FROM HUB_SEGMENTS WHERE APP_OR_REJECT IN ('APPROVED', 'REJECTED');
THEN
INSERT INTO HUB_APPROVED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO HUB_REJECTED SELECT ... FROM FROM HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE FROM HUB_SEGMENTS WHERE APP_OR_REJECT IN ('APPROVED', 'REJECTED');
ELSE
...;
END IF; --> here
END;
奖励:您可以使用 IN
代替这些 OR
ed 条件。
旁注:如果性能无关紧要,那么,正如@zip 所建议的那样,不要理会 IF
块。可以直接运行两个INSERT
和DELETE
语句一前一后。如果 HUB_SEGMENTS
中没有符合搜索条件的数据,则无论如何都不会插入或删除任何内容。
感谢有用的评论 - 如果我使用非 oracle SQL(可能?),这些评论会起作用。不幸的是 运行 PL/SQL DBVis 上指向 oracle 数据库的 "exists" 脚本导致错误 - Exists 在 PL/SQL 脚本中不起作用(但应该在单个 SQL 显然是陈述)。
我发现结合 IF 使用变量解决了我的问题:
Declare
v_count NUMBER;
BEGIN
select COUNT(*)
INTO v_count
FROM HUB_SEGMENTS
WHERE APP_OR_REJECT is not null; --for each row where %new.columnname is not new --=> this would be far less "expensive" sql query, need to figure out how to syntax this
IF v_count >0
THEN
INSERT INTO
HUB_APPROVED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'APPROVED';
INSERT INTO
HUB_REJECTED (HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE)
SELECT
HUB_SEGMENTS_GUID, TID, SEGMENT, ID, ROLE, UPDATED_BY, APP_OR_REJECT, UPDATED_DATE
FROM
HUB_SEGMENTS WHERE APP_OR_REJECT = 'REJECTED';
DELETE
FROM
"TESTDEMO".HUB_SEGMENTS
WHERE
APP_OR_REJECT = 'APPROVED' or APP_OR_REJECT = 'REJECTED';
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables Executed');
ELSE
DBMS_OUTPUT.PUT_LINE('Trigger: Insert to action Tables NOT executed');
END IF;
end;
这成功地实现了我试图实现的目标(除非特定列中确实有数据,否则不会执行 Insert/Delete 语句,以避免奇怪地意外触发其他触发器)
一位同事告诉我,按照 "for each row where %new.columnname is not new =>..." 的方式做一些事情会 cpu 密集 sql 查询少得多,但我需要弄清楚如何语法这个。现在,上面的代码在 PL/SQL 中工作,指向 DBVis 中的 oracle 数据库。
如果我找到 "for each row..." 方法,我会 post 在这里作为评论