为什么我在这个动态查询中需要关键字 TABLE,尽管在普通查询中不需要

Pie*_*aud 1 oracle plsql

db fiddle 现在不工作。稍后我会上传代码...

SELECT COUNT (*) FROM sys.odcivarchar2list ('2', '2');
Run Code Online (Sandbox Code Playgroud)

该查询无需使用关键字表即可工作。但在动态查询中:

DECLARE
    c             INTEGER;
    towtimestwo   SYS.odcivarchar2list := sys.odcivarchar2list ('2', '2');
BEGIN
    
     EXECUTE IMMEDIATE 'SELECT COUNT (*) FROM  :1'
        INTO c
        USING towtimestwo;
    DBMS_OUTPUT.put_line (c);

END;
Run Code Online (Sandbox Code Playgroud)

它不起作用:

无效的表名

因此我必须添加关键字。

DECLARE
    c             INTEGER;
    towtimestwo   SYS.odcivarchar2list := sys.odcivarchar2list ('2', '2');
BEGIN
    
     EXECUTE IMMEDIATE 'SELECT COUNT (*) FROM  table( :1)'
        INTO c
        USING towtimestwo;
    DBMS_OUTPUT.put_line (c);

END;
Run Code Online (Sandbox Code Playgroud)

为什么?

我正在使用 Oracle 19.0

Ale*_*ole 6

因为当动态声明

'SELECT COUNT (*) FROM  :1'
Run Code Online (Sandbox Code Playgroud)

被解析后,它会将 视为:1表名,并且您不能将绑定变量用于表名或任何其他固定部分。您只能将绑定变量用于变量,即数据。

您传递的集合是否可以被视为表格并不重要;SQL 解析器还不知道(或关心)。

对于声明:

'SELECT COUNT (*) FROM  table( :1)'
Run Code Online (Sandbox Code Playgroud)

现在它确实将 视为:1变量,因为它周围有表表达式table(),所以这是有效的。


您可以将原始静态 SQL 语句用作动态语句:

'SELECT COUNT (*) FROM sys.odcivarchar2list (''2'', ''2'')'
Run Code Online (Sandbox Code Playgroud)

或使用替代引用:

q'^SELECT COUNT (*) FROM sys.odcivarchar2list ('2', '2')^'
Run Code Online (Sandbox Code Playgroud)

因为它们也不会尝试使用绑定变量作为源表。

数据库<>小提琴