PL / SQl游标的可变/文字替换?

时间:2015-12-04 09:16:11

标签: oracle plsql cursors

我经常需要在Oracle PL / SQL中调试游标。我的问题是,我最终得到了一些带有50多个变量和常量的数字游标。我正在寻找一种获取语句版本的方法,其中常量和变量用其文字替换。如果我想找出为什么光标没有显示记录/行,我应该最终替换那些变量/文字30分钟才能运行select并注释掉一些语句以找出&# 39;错了。

所以,如果我有类似

的东西
SELECT * FROM TABLE
WHERE  col1  = 123
AND    col2 != 5324
AND    col3  = 'ValueXyz';

我需要像这样的SELECT:

{{1}}

有没有办法以这种方式获取/记录SELECT所以我可以将它复制粘贴到一个新的SQL窗口中,这样我就不用花30分钟来替换那些东西了? (应该是我可以重用的东西,并没有绑定到那个特殊的游标,因为我经常在大量不同的游标上需要这些东西)。

4 个答案:

答案 0 :(得分:0)

我这样做的方法是将sql复制并粘贴到编辑器窗口中,在所有变量前加上:然后运行查询。当我使用Toad时,我得到一个窗口提示我查询中所有绑定变量的值,所以我填写它们并运行查询。保存了值,因此可以轻松地重新运行查询,或者如果需要调整值,则可以执行此操作。

e.g:

SELECT * FROM TABLE
WHERE  col1  = v1
AND    col2 != v2
AND    col3  = CONSTANT;

变为

SELECT * FROM TABLE
WHERE  col1  = :v1
AND    col2 != :v2
AND    col3  = :CONSTANT;

答案 1 :(得分:0)

可以使用GV $ SQL_BIND_CAPTURE中的数据生成游标的文字版本。根据我的经验,Oracle绑定捕获元数据并不总是可用;下面的代码适用于示例游标,但可能不够强大,无法使用所有代码。

示例架构,唯一字符串

修改源代码并为查询添加唯一标识符,以便以编程方式选择它们。使用提示,因为查询的解析版本不包含常规注释。我更改了数据类型以包含字符串和日期,以使示例更加真实。

drop table test1 purge;
create table test1(col1 number, col2 varchar2(100), col3 date);

create or replace procedure test_procedure is
    C_Constant constant date := date '2000-01-01';
    v_output1 number;
    v_output2 varchar2(100);
    v_output3 date;

    CURSOR cFunnyCursor (
      v1 NUMBER,
      v2 VARCHAR2
    ) IS
    SELECT /*+ unique_string_1 */ * FROM TEST1
    WHERE  col1  = v1
    AND    col2 != v2
    AND    col3  = C_CONSTANT;
begin
    open cFunnyCursor(3, 'asdf');
    fetch cFunnyCursor into v_output1, v_output2, v_output3;
    close cFunnyCursor;
end;
/

刷新共享池

Oracle仅捕获绑定变量的第一个实例。在运行该过程之前运行此语句以清除现有绑定数据。

alter system flush shared_pool;

运行测试程序

begin
    test_procedure;
end;
/

生成文字SQL的PL / SQL块

--Print a query with literals instead of binds.
declare
    --Change this to match the query.
    v_unique_string varchar2(100):= 'unique_string_1';

    v_sql_id varchar2(100);
    v_sql_text clob;
begin
    --Get the SQL_ID and text.
    select sql_id, sql_fulltext
    into v_sql_id, v_sql_text
    from gv$sql
    where lower(sql_text) like '%'||v_unique_string||'%'
        and sql_text not like '%quine%';

    --Loop through the binds.
    for binds in
    (
        select *
        from gv$sql_bind_capture
        where sql_id = v_sql_id
        --Match longest names first to avoid matching substrings.
        --For example, we don't want ":b1" to be matched to ":b10".
        order by length(name) desc, position
    ) loop
        --Convert the value from a string to a literal.
        if binds.datatype_string = 'NUMBER' then
            v_sql_text := replace(v_sql_text, binds.name, binds.value_string);
        elsif binds.datatype_string like 'VARCHAR2%' then
            v_sql_text := replace(v_sql_text, binds.name, ''''||binds.value_string||'''');
        --Adjust this to match your server date format. 
        elsif binds.datatype_string like 'DATE%' then
            v_sql_text := replace(v_sql_text, binds.name, 'to_date('''||binds.value_string||''', ''MM/DD/YYYY HH24:MI:SS'')');
        --TODO: Add more types here.
        end if;
    end loop;

    --Remove the unique string so it's not re-run with the literal version.
    v_sql_text := replace(v_sql_text, v_unique_string, null);

    --Print the SQL.
    dbms_output.put_line(v_sql_text);
end;
/

示例输出

SELECT /*+  */ * FROM TEST1 WHERE COL1 = 3 AND COL2 != 'asdf' AND COL3 = to_date('01/01/2000 00:00:00', 'MM/DD/YYYY HH24:MI:SS') 

不幸的是它丢失了所有格式。没有简单的方法可以解决这个问题。如果这是一笔巨大的交易,你可以使用PL / Scope来构建一些东西来代替程序中的变量,但我有一种感觉会非常复杂。希望您的IDE具有代码美化功能。

答案 2 :(得分:0)

我认为您必须使用动态SQL功能来获取这些变量值。通过使用ref cursor变量,您甚至可以看到输出 请查看以下查询。

DECLARE
vString  VARCHAR2 (32000);
vResult  sys_refcursor;
BEGIN
vString := 
     'SELECT * FROM table   
       WHERE col1 = '|| v1|| ' 
         AND col2 != '|| v2|| ' 
         AND col3 = '|| v;

OPEN vResult FOR vString;

DBMS_OUTPUT.put_line (vString);
END;

如果你有一个更大的Cursor查询,它不是一种有效的方法。因为您可能需要将整个Cursor查询替换为Dynamic SQL。

答案 3 :(得分:0)

一种可能的方法是将光标辅助到SYS_REFCURSOR变量,然后将SYS_REFCURSOR分配给绑定变量。

如果您在Toad中运行此代码段,则将要求您在弹出窗口中定义:out变量:只需选择Direction:OUT / Type:CURSOR,然后数据集将显示在“ Data Grid”中标签。

declare
  l_refcur   sys_refcursor;
  v1         varchar2(4) := 'v1'; 
  v2         varchar2(4) := 'v2'; 
  c_constant varchar2(4) := 'X';
begin
  open l_refcur for
    SELECT * FROM dual
     WHERE dummy  = c_CONSTANT;
  :out := l_refcur;
end;

其他SQL IDE也应支持此功能。