【问题标题】:oracle how can i find the line number for the begin in a procedure / packageoracle我如何在过程/包中找到开始的行号
【发布时间】:2014-06-02 11:48:20
【问题描述】:

我想在每个程序、函数和打包程序的开始后添加一些代码,我有成千上万的程序、程序包等,因此手动执行此操作将花费数周的时间。

我可以搜索 all_source,但在我编写自己的代码以查找“开始”的行号之前,是否有人有任何分析代码,因为可能存在我需要忽略的子例程或匿名块

例如来自用户源

package body my_pck is
  procedure proc1 
  is
    v_var varchar2(10);
    procedure sub_proc
    is
    begin
      some code ....
    end;
  begin
< I want to insert code here>
    some code ....

    begin
      anon block ....
    end;
  end;
  procedure proc2 
  is
    v_var varchar2(10);
    procedure sub_proc_something_else
    is
    begin
      some code ....
    end;
    procedure sub_proc_another
    is
    begin
      some code ....
    end;
  begin
< I want to insert code here as well>
    some code ....
  end;
end;

所以我认为我需要一个例程来匹配开始/结束以找到添加我的代码的位置

谢谢 罗伯特

【问题讨论】:

    标签: oracle stored-procedures plsql oracle11g


    【解决方案1】:

    你肯定需要一个解析器来完成这个任务。我为Vorax 创建了一个plsql 解析器,如果你愿意,可以使用它。它不是一个成熟的解析器,但足够聪明,可以弄清楚 plsql 代码的结构。

    从 github 获取 vorax4 项目。

    cd C:\Projects
    git clone https://github.com/talek/vorax4
    gem install vorax
    

    编写一个简单的 ruby​​ 代码来处理您的场景:

    $LOAD_PATH << 'C:/Projects/vorax4/vorax/ruby/lib/'
    
    require 'vorax.rb'
    include Vorax
    
    # You need to get this from your database
    package_source =<<EOF
    
    package body my_pck is
      procedure proc1 
      is
        v_var varchar2(10);
        procedure sub_proc
        is
        begin
          some code ....
        end;
      begin
        some code ....
    
        begin
          anon block ....
        end;
      end;
      procedure proc2 
      is
        v_var varchar2(10);
        procedure sub_proc_something_else
        is
        begin
          some code ....
        end;
        procedure sub_proc_another
        is
        begin
          some code ....
        end;
      begin
        some code ....
      end;
    end;
    
    EOF
    
    structure = Parser::PlsqlStructure.new(package_source)
    
    # just print the structure of the package
    puts structure.dump
    
    # the code we want to insert
    offset = 0
    INSERT_CODE = "\n--my code\n"
    INSERT_CODE_LEN = INSERT_CODE.length
    
    # loop into the plsql structure
    structure.regions.each do |child|
    
      region = child.content
    
      # only if it's a procedure/function declared into the body of the package
      if region && child.level == 2 && region.instance_of?(Parser::SubprogRegion)
        pos_to_insert = offset + region.body_start_pos + 'begin'.length
    
        # insert the code after the BEGIN clause
        package_source.insert(pos_to_insert, INSERT_CODE)
    
        # adjust the offset
        offset += INSERT_CODE_LEN + 1
      end
    
    end
    
    # print the new version of the package
    puts package_source
    

    输出是:

    [Level: 0]
      [Level: 1] PackageBodyRegion: {:start_pos=>2, :end_pos=>467, :name=>"my_pck", :name_pos=>15, :signature_end_pos=>24, :declare_end_pos=>462}
        [Level: 2] SubprogRegion: {:start_pos=>27, :end_pos=>217, :name=>"proc1", :name_pos=>37, :body_start_pos=>145}
          [Level: 3] SubprogRegion: {:start_pos=>77, :end_pos=>141, :name=>"sub_proc", :name_pos=>87, :body_start_pos=>107}
          [Level: 3] AnonymousRegion: {:start_pos=>175, :end_pos=>210}
        [Level: 2] SubprogRegion: {:start_pos=>221, :end_pos=>462, :name=>"proc2", :name_pos=>231, :body_start_pos=>432}
          [Level: 3] SubprogRegion: {:start_pos=>271, :end_pos=>350, :name=>"sub_proc_something_else", :name_pos=>281, :body_start_pos=>316}
          [Level: 3] SubprogRegion: {:start_pos=>356, :end_pos=>428, :name=>"sub_proc_another", :name_pos=>366, :body_start_pos=>394}
    
    package body my_pck is
      procedure proc1
      is
        v_var varchar2(10);
        procedure sub_proc
        is
        begin
          some code ....
        end;
      begin
    
    --my code
        some code ....
    
        begin
          anon block ....
        end;
      end;
      procedure proc2
      is
        v_var varchar2(10);
        procedure sub_proc_something_else
        is
        begin
          some code ....
        end;
        procedure sub_proc_another
        is
        begin
          some code ....
        end;
      begin
    
    --my code
       some code ....
      end;
    end;
    

    其他解析器选项,虽然我没有使用过,但可能是:

    【讨论】:

      【解决方案2】:

      我认为这将很难(但并非不可能)做到。首先,您需要从数据库中获取包。我有一些代码可以做到这一点:

      DECLARE
        package_name user_source.name%type;
        last_package_name user_source.name%type;
        package_body CLOB;
      BEGIN
        FOR package_cur IN
        ( SELECT * FROM user_source WHERE type = 'PACKAGE BODY' ORDER BY name, line
        )
        LOOP
          package_name        := package_cur.name;
          IF last_package_name = package_name OR last_package_name IS NULL THEN
            package_body      := package_body || package_cur.text;
          ELSE
            --=======================================================
            -- whole package is now in package_body and can be altered
            --=======================================================
            insert into tmp_table values (package_body);
      
            -- move to next package
            package_body := package_cur.text;
          END IF;
          last_package_name := package_name;
        END LOOP;
        -- processing very last package
        insert into tmp_table values (package_body);
      END;
      

      下一个障碍是代码可以以多种方式进行概述,据我所知,整个包可以写在一行中。您必须找出一种或另一种方法来首先从包中提取所有过程,然后绑定适当的开始关键字。

      【讨论】:

      • 我应该什么时候投反对票?每当您遇到极其草率、不费吹灰之力的帖子或明显不正确且可能危险地不正确的答案时,请使用您的反对票。
      【解决方案3】:

      使用 $$PLSQL_LINE。另请参见 $$PLSQL_UNIT。

      BEGIN
        DBMS_OUTPUT.PUT_LINE ( $$PLSQL_UNIT || '.' || $$PLSQL_LINE || ': hello ' );
      END;
      /
      

      【讨论】:

      • 谢谢,但这取决于手动将其添加到代码中...我想自动化它...我应该添加我将提取源代码到文本文件,添加代码行然后重新编译回数据库....我现在已经编写了一个例程来做到这一点,我只是在完善具有子例程的逻辑,而不是把我的代码放在那里!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 2012-08-22
      • 2016-09-17
      • 2022-07-14
      • 1970-01-01
      相关资源
      最近更新 更多