我需要获取许多表的列填充(表中每列的计数)。我正在编写一个PLSQL脚本,该脚本将创建一个动态查询并希望打印结果。由于我的选择查询包括聚合列,我不确定如何定义 TYPE。是使用游标还是执行立即批量收集。
DECLARE
V_COLUMN_NAME ALL_TAB_COLS.COLUMN_NAME%type;
V_SELECT_POPULATION_QUERY varchar2(2000) := 'SELECT ';
V_TABLE_NAME varchar2(200) := 'EMPLOYEE'; // Will be list of tables in future
CURSOR TAB_COLS IS SELECT COLUMN_NAME FROM ALL_TAB_COLS WHERE TABLE_NAME = V_TABLE_NAME;
BEGIN
OPEN TAB_COLS;
LOOP
FETCH TAB_COLS INTO V_COLUMN_NAME;
EXIT WHEN TAB_COLS%notfound;
V_SELECT_POPULATION_QUERY := V_SELECT_POPULATION_QUERY ||'COUNT('|| V_COLUMN_NAME||'),';
END LOOP;
V_SELECT_POPULATION_QUERY:= SUBSTR(V_SELECT_POPULATION_QUERY, '0',LENGTH( V_SELECT_POPULATION_QUERY )-1);
V_SELECT_POPULATION_QUERY:= V_SELECT_POPULATION_QUERY || ' FROM '|| V_TABLE_NAME;
//NEED A WAY TO EXECUTE DYNAMIC QUERY (variable V_SELECT_POPULATION_QUERY) and print the results.
//SAMPLE DYNAMIC QUERY1 : SELECT COUNT(EMPLOYEE_ID),COUNT(NAME),COUNT(BASE_URL),COUNT(INPUT_FORM),COUNT(BASE_URL_ASUCASE),COUNT(IS_CUSTOM) FROM EMPLOYEE
//SAMPLE DYNAMIC QUERY 2: SELECT COUNT(DEPT_ID),COUNT(NAME),COUNT(BASE_URL) FROM DEPT
END;
3条答案
按热度按时间thtygnil1#
这样做的问题是每次返回的列列表都不一样,所以假设你用EXECUTE IMMEDIATE修复了代码中的直接问题:
但下一次,你需要一个不同的电话:
显然,你不能在一个循环中这样做,因为SQL语句本身是动态的,而你获取的变量不是。重用的动态SQL在所有情况下都应该返回相同的结构,但是你每次都在改变结构。
解决这个问题最直接的方法是分别查询每一列,而不是尝试一次查询表中的所有列,这样,您可以将每一列选择为一个数字变量。
但是假设这对您来说是一个性能负担,如果您真的必须在一次传递中合并所有列,那么您有两种方法。
1.确定您必须查询的最大列数(可能是数百列?)。创建一个具有该列数的记录变量。在组装COUNT(column_name)列表时,计算您追加了多少列,然后追加虚拟NULL列,无论需要多少次才能填充记录类型中的列数。
1.使用双嵌套动态SQL方法,其中包含动态SQL的整个PL/SQL块本身就是动态SQL。显然,您需要结果来执行某些操作,因此必须在该块中处理结果。假设您只需要将结果输入到表中。
在回答了您的问题之后,我想问一下您是否正确地处理了这个问题。您实际上是在计算每列的非NULL行数。如果这就是您所需要的,那么只需收集表的统计信息,您就可以在user_tab_columns(user_tables中的row_count减去user_tab_columns中的num_nulls)中得到答案。这比您自己做要容易得多。
如果你想得到 distinct 值的个数,那么你必须给你的每个COUNT()函数加上DISTINCT,但是同样,从user_tab_columns中的num_distinct得到这个信息比自己收集这个信息要容易得多。我这么多年来从来没有做过你想做的事情,所以也许这是一个你不需要真正解决的问题?
r3i60tvu2#
有一个选择。
首先创建类型:
函数接受表名作为参数;然后在循环中对该表中的每一列进行计数,将结果存储到
return
值的集合中:测试:
你说过(在你发布的代码中的注解)你将在将来使用"表列表"。函数仍然只接受一个参数,但您应该传递所需数量的表。
例如:
3pvhb19x3#
要 * 计算表中的每列 *,您不需要任何PL/SQL脚本。Oracle已经在 * 对象统计信息 * 中为您计算了该列的数量-通过抽样 * 近似 *-这对于大型表非常合适,或者通过扫描整个表来精确计算。
从技术上讲,您需要表的行计数和每列中要减去的
NULL
值的数量。小示例
收集100%百分比的统计信息(精确,无抽样)
现在使用字典视图获取表
NUM_ROWS
和列NUM_NULLS
,并将它们相减以获得结果。注意,作为一个额外的好处,你还可以得到每列的 * 不同值 * 的数量。你可以使用抽样来在更短的时间内得到估计值,或者你可以激活一个 * 并行选项 * 来收集统计信息。