如何在Oracle函数中创建和删除表?

时间:2015-04-21 13:20:15

标签: oracle function ddl

我有一个功能,我需要删除并创建表。在下面的示例中,我尝试创建表但它失败

CREATE OR REPLACE FUNCTION DEVTEST 
RETURN  NUMBER
IS 
    COMMAND    VARCHAR2(256);
    ID         VARCHAR2(128);
    NAME       VARCHAR2(128);
    TMP_LIST   VARCHAR2(128);
BEGIN
    ID := '12345';
    NAME := 'ABCdef';
    TMP_LIST := 'tmpTest';

    command := 'create table ' || TMP_LIST || ' ( USER_ID VARCHAR2(11), USER_NAME VARCHAR2(36))';
    DBMS_OUTPUT.PUT_LINE('command = ' || command);
    EXECUTE IMMEDIATE command;
return 0;
END;

我称之为功能:

select NSB_DEVTEST() from dual

得到错误:

ORA-14552:无法在查询或DML内执行DDL,提交或回滚ORA-06512:at" DEV1_SERVER.DEVTEST",第15行

如何更正此操作以在函数内创建/删除表?

我的服务器详细信息:

  • Oracle数据库10g企业版10.2.0.5.0版 - 64bi
  • PL / SQL版本10.2.0.5.0 - 生产
  • CORE 10.2.0.5.0生产
  • TNS for Solaris:版本10.2.0.5.0 - 生产
  • NLSRTL版本10.2.0.5.0 - 生产

3 个答案:

答案 0 :(得分:3)

问题不在于函数,而在于从SQL语句而不是从pl / sql块调用它。

SQL中的SELECT语句等同于读取一致性的READ操作。它无法对数据库进行任何更改。在" READ"之前和之后数据库应始终相同。操作完成,否则它将是一个WRITE操作,整个数据库的一致性将受到严重破坏。

此外,如错误所述,DDL操作在启动之前在后台执行COMMIT。任何读取一致操作都不应该执行任何COMMITS并在用户不知情的情况下写入数据库。

您可以改为调用pl / sql中的函数 -

DECLARE
l_result NUBMER;
BEGIN
l_result := DEVTEST;
DBMS_OUTPUT.PUT_LINE(l_number);
END;

我还是更愿意为此编写一个程序,所以其他人不会为什么不能从SQL调用它而感到困惑。我遵循的一般规则是 - 功能"得到"事情和程序"做"事物(如DML)。

答案 1 :(得分:2)

你的问题的答案是:不要。总的来说,生产代码不应该动态创建表。如果您需要一个临时保存数据的表,那么创建一次全局临时表(GTT)并让您的代码引用它。

您收到该错误的原因(除了从错误消息中不言而喻)是因为您正在SQL语句中调用该函数。你做不到;你必须直接在PL / SQL中调用它。

我很好奇为什么你认为这种方法是一种好的,可行的方法,以及你创建它后你将要做的事情。

答案 2 :(得分:1)

您的代码是完美的,代码中没有问题。问题是您尝试执行

您只能在select语句中执行纯函数,这意味着没有 ddl&dml 的函数。 (如果在函数内执行 dml 时使用 pragma automation_transaction ,则可以在选择语句中使用它)。当函数具有 DDL 命令时,您可以从不执行在select语句中执行它,但是相反,您可以在PLSQL块中执行该命令

declare 
a number;
begin
a:= devtest;
end;
/

您可以检查表格

select * from tmptest;