【问题标题】:Oracle/PLSQL nested for loop for inserting values用于插入值的 Oracle/PLSQL 嵌套 for 循环
【发布时间】:2018-08-15 10:10:37
【问题描述】:

我得到了错误

ORA-00984:此处不允许列

当我运行这个 PLSQL 脚本时:

BEGIN
    FOR i IN (
        SELECT attribute_id
        FROM odd_attribute
    ) LOOP
        FOR j IN (
            SELECT t1.sourceattribute_id
            FROM odd_sourceattribute t1
            WHERE t1.sourcetable_id IN (
                SELECT t2.sourcetable_id
                FROM odd_sourcetable t2
                WHERE t2.sourcetable_name LIKE 'vr_db_f_%'
            )
        ) LOOP
            EXECUTE IMMEDIATE 'insert into odd_fact_attribute 
                          (attribute_id, sourceattribute_id, statusattribute_name, other_stuff_to_describe_fact) 
                          values 
                          (i.attribute_id, j.sourceattribute_id, NULL, NULL)'
            ;
        END LOOP;
    END LOOP;
END;

列名似乎是正确的,但我无法找出错误的原因。感谢所有的帮助。谢谢。

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    引发错误是因为您在 EXECUTE IMMEDIATE 的引号内引用隐式游标中的列名,这将被视为静态 sql 中的表引用。

    您可以借助占位符(以 : 开头)和 USING 语句来避免这种情况。

    EXECUTE IMMEDIATE 
    'INSERT INTO odd_fact_attribute (
            attribute_id,
            sourceattribute_id,
            statusattribute_name,
            other_stuff_to_describe_fact
        ) VALUES (
            :attribute_id,
            :sourceattribute_id,
            NULL,
            NULL
        )'
        USING i.attribute_id,j.sourceattribute_id;
    

    重要的是,不需要EXECUTE IMMEDIATE,并且带有嵌套循环的 PL/SQL 块相当于像这样的单个 INSERT 语句,这将比您的循环高效得多。

    INSERT INTO odd_fact_attribute (
        attribute_id,
        sourceattribute_id,
        statusattribute_name,
        other_stuff_to_describe_fact
    )
        SELECT o.attribute_id,
               t1.sourceattribute_id,
               NULL,
               NULL
        FROM odd_sourceattribute t1
        CROSS JOIN odd_attribute o --use appropriate join condn. if this is not the case
        WHERE t1.sourcetable_id IN (
            SELECT t2.sourcetable_id
            FROM odd_sourcetable t2
            WHERE t2.sourcetable_name LIKE 'vr_db_f_%'
        );
    

    【讨论】:

    • 第二个选项效果很好。第一个选项需要一个多小时才能执行,因为预期的输出包含大约 900,000 行。因此我只是终止了它并尝试了大约 2 秒的第二个选项。经验教训:尽可能使用查询而不是循环!非常感谢。
    猜你喜欢
    • 2021-03-02
    • 2022-08-03
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多