Oracle PL/SQL:使用绑定变量进行查询

Oracle PL/SQL:使用绑定变量进行查询,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,能否请您帮助理解,是否有可能使这项工作使用绑定变量 第1步: =>例如,d_sql_查询可以类似于'CD_UNBIL.trans_dt>=TO_DATE('20200702 12:11:03','YYYYMMDD HH24:MI:SS'),或者d_sql_查询可以有更大的条件 稍后,我们将此d_sql_查询添加到更大的查询中,如下所示:- 第2步 正如您所看到的,d_sql_查询是附加的,因此整个查询如下所示 ... AND RPU_WORK.tracking_id = :tracking_id

能否请您帮助理解,是否有可能使这项工作使用绑定变量

第1步:

=>例如,d_sql_查询可以类似于'CD_UNBIL.trans_dt>=TO_DATE('20200702 12:11:03','YYYYMMDD HH24:MI:SS'),或者d_sql_查询可以有更大的条件

稍后,我们将此d_sql_查询添加到更大的查询中,如下所示:-

第2步

正如您所看到的,d_sql_查询是附加的,因此整个查询如下所示

...
AND RPU_WORK.tracking_id = :tracking_id AND RPU_WORK.tracking_id_serv = :tracking_id_serv AND '|| NVL(CD_UNBIL.trans_dt >= TO_DATE('20200702 12:11:03', 'YYYYMMDD HH24:MI:SS'), ' 1=1 ');
我希望这样做(使用下面的绑定变量)


一旦我有了上面的查询,我就可以使用“executeimmediateusing”。

您能这样构造查询的结尾吗

...
AND RPU_WORK.tracking_id = :tracking_id 
AND RPU_WORK.tracking_id_serv = :tracking_id_serv 
AND case when :b1 is not null
    then
        case when CD_UNBIL.trans_dt >= TO_DATE(:b1, 'YYYYMMDD HH24:MI:SS')
        then 1
        else 0
        end
    else 1 
    end = 1

您可以使用我的开源程序动态查找文本,并使用绑定变量替换文本

例如:

--Convert literals to bind variables.
declare
    v_sql_expression clob := q'[CD_UNBIL.trans_dt >= TO_DATE('20200702 12:11:03', 'YYYYMMDD HH24:MI:SS')]';
    v_new_sql_expression clob;
    v_tokens token_table := token_table();
    v_bind_number number := 0;
begin
    v_tokens := plsql_lexer.lex(v_sql_expression);

    for i in 1 .. v_tokens.count loop
        if v_tokens(i).type in ('text', 'numeric') then
            v_new_sql_expression := v_new_sql_expression || ':b'||v_bind_number;
            v_bind_number := v_bind_number + 1;
        else
            v_new_sql_expression := v_new_sql_expression || v_tokens(i).value;
        end if;
    end loop;

    dbms_output.put_line('New expression: '||v_new_sql_expression);
end;
/
输出:

New expression: CD_UNBIL.trans_dt >= TO_DATE(:b0, :b1)
这段代码会有一些问题,
TO_DATE
有两个变量,而不是一个,日期文本,如日期'2000-01-01'需要特殊处理,因为它实际上是三个令牌而不是一个,这不会阻止SQL注入(正如pmdba指出的),您需要调整上述代码,以便从正确的表中读取,然后存储并应用文本,等等


这可能有助于全面解释您试图解决的问题-为什么不简单地将动态表达式作为文本应用,而不是尝试使用绑定变量?

这里的问题是d_sql_查询可以具有任何运算符的任何条件,不仅仅是如上所示的日期,您将无法以这种方式完全转换为绑定变量。只要“where”子句可以包含用户输入,您就必须连接文本,并且会有潜在的SQL注入问题。我们的DBA建议使用具有不同值的绑定变量进行d_sql_查询,最终查询每次都会更改为新的sql_id,DBA无法对其进行优化。
...
AND RPU_WORK.tracking_id = :tracking_id 
AND RPU_WORK.tracking_id_serv = :tracking_id_serv 
AND case when :b1 is not null
    then
        case when CD_UNBIL.trans_dt >= TO_DATE(:b1, 'YYYYMMDD HH24:MI:SS')
        then 1
        else 0
        end
    else 1 
    end = 1
--Convert literals to bind variables.
declare
    v_sql_expression clob := q'[CD_UNBIL.trans_dt >= TO_DATE('20200702 12:11:03', 'YYYYMMDD HH24:MI:SS')]';
    v_new_sql_expression clob;
    v_tokens token_table := token_table();
    v_bind_number number := 0;
begin
    v_tokens := plsql_lexer.lex(v_sql_expression);

    for i in 1 .. v_tokens.count loop
        if v_tokens(i).type in ('text', 'numeric') then
            v_new_sql_expression := v_new_sql_expression || ':b'||v_bind_number;
            v_bind_number := v_bind_number + 1;
        else
            v_new_sql_expression := v_new_sql_expression || v_tokens(i).value;
        end if;
    end loop;

    dbms_output.put_line('New expression: '||v_new_sql_expression);
end;
/
New expression: CD_UNBIL.trans_dt >= TO_DATE(:b0, :b1)