首页 > 解决方案 > DBMS_METADATA.GET_DDL 在 PROCEDURE 中不起作用

问题描述

我创建了一个脚本来从 DEVBASE 用户复制一个表:

DECLARE
  YTABLE_NAME   CONSTANT VARCHAR2 (50) := 'TABLE_NAME';
  YRECREATE     CONSTANT BOOLEAN       := FALSE;
--
  XCOMMAND               CLOB;

  FUNCTION TABLE_EXISTS (ZTABLE_NAME IN VARCHAR2)
    RETURN BOOLEAN IS
    XCOUNT   NUMBER;
  BEGIN
    SELECT COUNT (*)
      INTO XCOUNT
      FROM USER_TABLES A
     WHERE A.TABLE_NAME = ZTABLE_NAME;

    RETURN XCOUNT > 0;
  END;
BEGIN
  IF TABLE_EXISTS (YTABLE_NAME) THEN
    IF YRECREATE THEN
      EXECUTE IMMEDIATE 'DROP TABLE ' || YTABLE_NAME || ' CASCADE CONSTRAINTS';
    ELSE
      RAISE_APPLICATION_ERROR (-20000, 'TABLE ' || YTABLE_NAME || ' ALREADY EXISTS');
    END IF;
  END IF;

  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'PRETTY', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'EMIT_SCHEMA', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_CREATION', FALSE);
  DBMS_METADATA.SET_TRANSFORM_PARAM (DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS_AS_ALTER', FALSE);
  XCOMMAND := DBMS_METADATA.GET_DDL ('TABLE', YTABLE_NAME, 'DEVUSER');

  EXECUTE IMMEDIATE XCOMMAND;
END;

它可以工作,但是如果我使用此代码创建一个过程,我会收到错误“ORA-31603:在模式 DEVUSER 中找不到 TABLE 类型的对象 {表名}”。

CREATE OR REPLACE PROCEDURE COPY_TABLE (YTABLE_NAME IN VARCHAR2, YRECREATE IN BOOLEAN) IS
BEGIN
  -- exact same code
END;

为什么会这样?

标签: oracleplsql

解决方案


Oracle文档指出:

在存储过程、函数和定义者权限包中,角色被禁用。因此,这样的 PL/SQL 程序只能在自己的模式中获取对象的元数据。如果你想编写一个 PL/SQL 程序来获取不同模式中对象的元数据,你必须使程序调用者权限。

为此,您必须添加authid到您的过程中。


推荐阅读