我有一个功能,我需要删除并创建表。在下面的示例中,我尝试创建表但它失败
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行
如何更正此操作以在函数内创建/删除表?
我的服务器详细信息:
答案 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;