【问题标题】:Looping through tables with Oracle Subqueries使用 Oracle 子查询循环遍历表
【发布时间】:2011-06-22 17:26:59
【问题描述】:

我想针对数据库中具有合适列的每个表运行 Oracle 验证函数。 验证可以简单地针对一个表运行:

SELECT
count (*)
FROM
Table_name t
Where
SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(t.Column_name, 0.005) <> 'TRUE';

这适用于单个表,但由于有超过 100 个要测试,我想使用子查询将它与 Oracle 元数据表合并,从而使整个事情自动化。我想出了两个变体,但都不起作用,我猜是因为它无法从子查询内部传递变量。 我的两个尝试是:

SELECT TABLE_NAME tab, COLUMN_NAME col, (select count(*) from tab where sdo_geom.validate_geometry(tab.col, 0.005) <> 'TRUE')
From
All_Tab_Columns
where 
owner = 'WCCDATA' and DATA_TYPE = 'SDO_GEOMETRY'

返回:

SQL 错误:ORA-00904:“TAB”。“COL”:标识符无效 00904. 00000 - "%s: 无效标识符"

SELECT count(*)
From 
(SELECT
TABLE_NAME, COLUMN_NAME as col
FROM
All_Tab_Columns
where 
owner = 'WCCDATA' and DATA_TYPE = 'SDO_GEOMETRY') subquery
WHERE sdo_geom.validate_geometry(subquery.col, 0.005) <> 'TRUE';

返回:

ORA-06512:在“MDSYS.SDO_GEOM”,第 2204 行 00942. 00000 - “表或视图不存在”

有人有什么想法吗?谢谢。

【问题讨论】:

    标签: oracle


    【解决方案1】:

    您永远不能将列值引用为标识符(表、列等)。为此,您需要编写一些 PL/SQL 来动态创建和执行 SQL,可能像这样:

    DECLARE
       CURSOR cur_tables IS
          SELECT   table_name,
                      'SELECT count(*) From '
                   || table_name
                   || ' WHERE sdo_geom.validate_geometry('
                   || column_name
                   || ', 0.005) <> ''TRUE'''
                      AS dsql
            FROM   all_tab_columns
           WHERE   owner = 'WCCDATA' AND data_type = 'SDO_GEOMETRY';
       v_count   NUMBER;
    BEGIN
       FOR r_tables IN cur_tables LOOP
          EXECUTE IMMEDIATE r_tables.dsql INTO   v_count;
    
          DBMS_OUTPUT.put_line(r_tables.table_name || ': ' || v_count);
       END LOOP;
    END;
    

    【讨论】:

    • 感谢 Allan,我以前从未接触过 PL/SQL,所以这对我来说是全新的。当我尝试在 Oracle SQL Developer 中运行它但它不起作用并且我收到错误消息:codeORA-00933:SQL 命令未正确结束 ORA-06512:在第 15 行 00933.00000 -“SQL 命令不正确结束了"code有什么想法吗?
    • @Jonathan:PL/SQL 块对我来说很好,所以我认为它必须是在查询中构造的 SQL(这是有道理的,因为第 15 行是 EXECUTE IMMEDIATE 命令)。尝试单独运行查询并运行它产生的一两个 SQL 语句。另一种可能性是空行正在抛弃 SQL Developer(我对它不够熟悉,不知道这是否可能)。
    • 对不起,但不高兴。根据您的建议,我在DECLARE 中运行了Select,它本身就很好,它创建的selects 也是如此。我不知道如何只运行 PL/SQL,但我确实设法(最终)弄清楚如何使用 SQLPlus(从单独的机器)运行它,但这给出了与 SQL Developer 完全相同的错误(00933和第 15 行的 06512)。也尝试删除空行,但没有效果。我们的 Oracle 是 10.2.0.4,如果这有所作为的话。
    • 尝试运行带有输出的 PL/SQL 块(set serveroutput on; 在上面的代码之前)。如果您得到一些结果,这可能表明某些 SQL 有效,但并非全部有效。这绝对不是 SQL Developer(我也检查过这种可能性),它不应该是版本问题。
    • 这让我想通了。它选择了所有表名,包括各种应用程序创建的“垃圾”表(即 BIN$pb1YwZ6b21DgQEwKIHAqJQ==$0MDRT_169B0$ )。我已经通过在您的 WHERE owner = 'WCCDATA' AND data_type = 'SDO_GEOMETRY'; 中添加更多子句来解决此问题 - 该行的结果然后变为 Where Owner = 'WCCDATA' And Data_Type = 'SDO_GEOMETRY' And Table_Name Not Like 'BIN$%' And Table_Name Not Like 'MDRT_%' And Not Regexp_Like(Table_Name, 'N_[0-9]+_.*') And Not Regexp_Like(Table_Name, '[A-Z][0-9]'); - 现在可以使用。谢谢!
    猜你喜欢
    • 2020-04-13
    • 2018-12-06
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 1970-01-01
    相关资源
    最近更新 更多