在SQL中的用户定义函数内调用函数

时间:2014-06-24 20:57:24

标签: sql oracle11g

我想在Oracle中的另一个用户定义函数中包含以下函数。

DBMS_STATS.GATHER_TABLE_STATS(SCHEMA_IN,TABLE_IN)

SCHEMA_INTABLE_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;

2 个答案:

答案 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