动态选择中的标识符无效

问题描述

我有一个小程序,如果存在则应该截断分区

create or replace PROCEDURE                 drop_partition(p_table_name VARCHAR2,p_load_seq INTEGER)
AS
        l_sql_text         VARCHAR2(1000 CHAR);
        l_part_exists      NUMBER;
BEGIN
        l_sql_text:= 'SELECT count(*) FROM  user_tab_partitions where table_name=' || p_table_name ||' and high_value='||p_load_seq ;
        EXECUTE IMMEDIATE l_sql_text INTO l_part_exists;
        if (l_part_exists=1) THEN
        l_sql_text := 'ALTER TABLE ' || p_table_name || ' DROP PARTITION FOR(' || to_char(p_load_seq) || ')';
        EXECUTE IMMEDIATE l_sql_text;
        END IF;
END;

如果我尝试运行这样的程序

call drop_partition('test',1);

有错误:

ORA-00904: "TEST": invalid identifier
ORA-06512: at "DROP_PARTITION",line 8
00904. 00000 -  "%s: invalid identifier"

有什么问题,我该如何解决?

解决方法

您需要将表名括在单引号中,然后将其转义:

... where table_name=''' || p_table_name ||''' and ...

即:

l_sql_text:= 'SELECT count(*) FROM  user_tab_partitions where table_name=''' || p_table_name ||''' and high_value='||p_load_seq ;

有一个alternative quoting mechanism消除了对引号进行转义的需要,但我认为这会更加令人困惑。

使用动态SQL时,在执行之前输出生成的语句以用于调试目的会很有用:

dbms_output.put_line(l_sql_text);

并在呼叫前在客户端中启用输出。


就像贾斯汀·凯夫(Justin Cave)正确指出的那样,过程的查询部分无论如何都不需要动态。您可以使用静态SQL:

SELECT count(*)
INTO l_part_exists
FROM user_tab_partitions
where table_name = p_table_name
and high_value = p_load_seq;

默认情况下,表名称之类的标识符在数据字典中为大写,因此您可以在该语句中使用upper(p_table_name)(静态或动态);但是,如果确实有任何大小写混合的带引号的标识符,则可以改用调用方以正确的大小写传递名称:

drop_partition('TEST',1);

...假设您的test表没有带引号的标识符。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...