PL-SQL:在过程内部执行触发器

时间:2019-06-17 08:01:30

标签: oracle plsql triggers

我想在过程内执行触发器。有什么方法可以在过程中执行PL / SQL(带有顶点)?我尝试使用此代码接收以下错误。

 LINE/COL ERROR
 -------- -----------------------------------------------------------------
 6/22     PLS-00103: Encountered the symbol "
          CREATE OR REPLACE TRIGGER managed_service_start
          AFTER STARTUP ON DATABASE
          DECLARE
          pdb_role VARCHAR2(64);
          pdb_name " when expecting one of the following:
          ( - + case mod new not null <an identifier>
          <a double-quoted delimited-identifier> <a bind variable>
          continue avg count current exists max min prior sql stddev
          sum variance execute forall merge time timestamp interval
          date <a string literal with character set specification>

 LINE/COL ERROR
 -------- -----------------------------------------------------------------
          <a number> <a s

我该怎么办?我的目标是只运行一次此过程,并避免在每个pdb中执行触发器。

CREATE OR REPLACE PROCEDURE start_services AS
BEGIN
    FOR i IN (SELECT name FROM v$pdbs p WHERE p.name <> 'PDB$SEED')
    LOOP
        EXECUTE IMMEDIATE 'ALTER SESSION SET CONTAINER= ' || i.name;
        EXECUTE IMMEDIATE  '
        CREATE OR REPLACE TRIGGER managed_service_start
            AFTER STARTUP ON DATABASE
        DECLARE
            pdb_role VARCHAR2(64);
            pdb_name VARCHAR2(64);
            host VARCHAR2(64);
        BEGIN
            SELECT database_role INTO pdb_role FROM v$database;
            SELECT Upper(sys_context ("userenv", "con_name")) INTO pdb_name FROM dual;
            SELECT host_name INTO host FROM v$instance;

            IF pdb_role = "PRIMARY" THEN
                DBMS_SERVICE.START_SERVICE(pdb_name || "_RW");
            ELSE
                -- IF host IN ("host_name1","host_name2") THEN
                IF host LIKE "%de%" THEN 
                    DBMS_SERVICE.START_SERVICE(pdb_name || "_RO");
                END IF;
            END IF;
        END;
        /
        ';
    END LOOP;
END;
/

2 个答案:

答案 0 :(得分:1)

在您的文本中,好像您在所有文字上都加上了双引号。它们必须是单引号。

由于这些单引号位于文字字符串内,因此您需要在行中放置两个单引号。

begin
execute immediate '
CREATE OR REPLACE TRIGGER managed_service_start
AFTER STARTUP ON DATABASE
DECLARE
  pdb_role VARCHAR2(64);
  pdb_name VARCHAR2(64);
  host VARCHAR2(64);
BEGIN
  SELECT database_role INTO pdb_role FROM v$database;
  SELECT Upper(sys_context (''userenv'', ''con_name'')) INTO pdb_name FROM dual;
  SELECT host_name INTO host FROM v$instance;

  IF pdb_role = ''PRIMARY'' THEN
    DBMS_SERVICE.START_SERVICE(pdb_name || ''_RW'');
  ELSE
    -- IF host IN (''host_name1'',''host_name2'') THEN
    IF host LIKE ''%de%'' THEN 
      DBMS_SERVICE.START_SERVICE(pdb_name || ''_RO'');
    END IF;
  END IF;
END;
/';
end;
/

最好的问候, 炖阿什顿

答案 1 :(得分:0)

简单地,将所有双引号替换为单引号,并用引号引起来的字符串(q'<delimeter><Your code><delimeter>')包裹触发器的DDL,如下所示:

CREATE OR REPLACE PROCEDURE start_services AS
BEGIN
    FOR i IN (SELECT name FROM v$pdbs p WHERE p.name <> 'PDB$SEED')
    LOOP
        EXECUTE IMMEDIATE 'ALTER SESSION SET CONTAINER= ' || i.name;
        EXECUTE IMMEDIATE  q'#
        CREATE OR REPLACE TRIGGER managed_service_start
            AFTER STARTUP ON DATABASE
        DECLARE
            pdb_role VARCHAR2(64);
            pdb_name VARCHAR2(64);
            host VARCHAR2(64);
        BEGIN
            SELECT database_role INTO pdb_role FROM v$database;
            SELECT Upper(sys_context ('userenv', 'con_name')) INTO pdb_name FROM dual;
            SELECT host_name INTO host FROM v$instance;

            IF pdb_role = 'PRIMARY' THEN
                DBMS_SERVICE.START_SERVICE(pdb_name || '_RW');
            ELSE
                -- IF host IN ('host_name1','host_name2') THEN
                IF host LIKE '%de%' THEN 
                    DBMS_SERVICE.START_SERVICE(pdb_name || '_RO');
                END IF;
            END IF;
        END;
        #';
    END LOOP;
END;
/

干杯!