我想在Oracle中的另一个用户定义函数中包含以下函数。
DBMS_STATS.GATHER_TABLE_STATS(SCHEMA_IN,TABLE_IN)
SCHEMA_IN
和TABLE_IN
是用户定义函数的参数。但是,我收到以下错误。
ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML
我该如何解决这个问题?下面是我的SQL脚本。
CREATE OR REPLACE Function GET_COLUMNS (SCHEMA_IN IN VARCHAR2, NAME_IN IN VARCHAR2)
RETURN VARCHAR2
is
L_TEXT VARCHAR2(32767) := NULL;
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(SCHEMA_IN,NAME_IN);
FOR CUR_REC IN (SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME = name_in AND NUM_NULLS = 0) LOOP
L_TEXT := L_TEXT || ',' || CUR_REC.COLUMN_NAME;
END LOOP;
return(ltrim(l_text,','));
END;
答案 0 :(得分:1)
gather_table_stats
是一个程序,而不是一个函数。它是一个包含事务控制逻辑的程序(可能至少是一个提交)。因此,您无法在从SQL调用的函数中调用它。您可以从PL / SQL而不是SQL调用您的函数,
DECLARE
l_text varchar2(4000);
BEGIN
l_text := get_columns( <<schema>>, <<table>> );
END;
但是,对于你所采取的方法,我会非常非常怀疑。
首先,dbms_stats
收集优化程序使用的统计信息。在其他情况下使用这些统计数据通常很危险。大多数dbms_stats
调用都涉及某种程度的非决定性 - 您通常会从行样本中收集数据并进行外推。这非常适合于提供优化器信息,以便它可以大致判断表扫描将返回多少行。如果您尝试区分从不NULL
的列和非常少NULL
的列,则可能不合适。某些样本可能会获得NULL
值,其他样本可能不会。它似乎可以正常工作数月或数年,然后始终或间歇地开始失败。
其次,当您收集新的统计信息时,您可能会强制Oracle对引用该表的所有现有SQL语句进行硬分析。如果你在中午这样做,这可能是一个重大的性能打击。如果你碰巧强迫查询计划以一种糟糕的方式改变,那么你可能会让DBA感到非常悲痛。如果DBA以特定方式收集统计数据(锁定某些表的统计数据,强制其他表的直方图,强制其他人没有直方图等)来处理性能问题,那么很可能是你&#39 ;或者是为了交叉目的而工作,要么是积极地打破另一方。
第三,如果列的值永远不会有NULL
,那么它实际上应该标记为NOT NULL
。然后,您可以简单地查看数据字典,以查看哪些列可以为空,哪些列无需收集统计信息。
答案 1 :(得分:0)
您需要将您的函数设置为自治事务以执行收集表统计信息:
CREATE OR REPLACE Function GET_COLUMNS (SCHEMA_IN IN VARCHAR2, NAME_IN IN VARCHAR2)
RETURN VARCHAR2
as
pragma autonomous_transaction;
L_TEXT VARCHAR2(32767) := NULL;
BEGIN