使用ant将每个存储过程复制到自己的文件中

时间:2009-10-12 20:49:01

标签: sql oracle ant procedures

我希望能够拥有一个连接到远程oracle实例的ant任务,并将每个存储过程复制到自己的文件中。我知道我可以执行一个ant sql任务

SELECT object_type, 
       object_name, 
       dbms_metadata.get_ddl(object_type, object_name) object_ddl 
FROM user_objects
WHERE OBJECT_TYPE in ('INDEX', 'TRIGGER', 'TABLE', 'VIEW', 'PACKAGE', 'FUNCTION', 'PROCEDURE', 'SYNONYM', 'TYPE')  
ORDER BY OBJECT_TYPE, OBJECT_NAME

但是这会将结果集全部放到一个文件中,而我希望每个过程都有一个文件(这是因为我打算随后将它们与SVN中的内容区分开来。)

有什么想法吗?

谢谢! 亚历

3 个答案:

答案 0 :(得分:1)

看起来你已经找到了最难的部分,如何构建SQL语句并将数据库服务器的结果传递给你的机器。

现在这样做。

  1. 构造SQL语句以获取所有内容 存储过程名称。
  2. 执行<loadfile property="procnames" file="result-of-sql-run.txt"/>
  3. 使用antcontrib for任务 迭代存储过程名称
  4. 以下是迭代的方法:

       <for list="${procnames}" delimeter="..." param="sproc-name">
          <sequential>
            <!-- Construct a new SQL statement to get specific
                 stored procedure named @{sproc-name} -->
         </sequential>
       </for>
    

    我很想知道你如何执行SQL代码并从ant连接数据库,你能发布你的解决方案吗?

答案 1 :(得分:1)

亚历山大,非常感谢你的帮助。根据您的建议,这是我使用的代码。唯一的免责声明是因为我必须使用dbms_lob.substr将clob转换为varchar2,我可以从每个过程ddl获取的最大值为4000个字符,并且它在此转换期间终止了格式化并且在一行中结束。如果您对如何纠正这两个问题有任何想法,请告诉我。

<target name="retrieve_procedures_names" depends="environment">

    <sql driver="${mp.db.driver.class}" url="${mp.db.connection.url}" userid="${mp.db.user.name}"
         password="${mp.db.password}" print="yes"
         output="${db.tmp.dir}/procedure_names.txt" onerror="stop" autocommit="true" encoding="UTF-8"
         showheaders="false" showtrailers="false">
        <classpath location="${db.driver.jar}"/>
        SELECT OBJECT_NAME FROM user_objects WHERE OBJECT_TYPE = 'PROCEDURE'
    </sql>

</target>
<target name="retrieve_procedures" depends="retrieve_procedures_names">
    <loadfile property="procnames" srcfile="${db.tmp.dir}/procedure_names.txt"/>
    <for list="${procnames}" delimiter="${line.separator}" param="sproc-name">
        <sequential>
            <sql driver="${mp.db.driver.class}" url="${mp.db.connection.url}" userid="${mp.db.user.name}"
                 password="${mp.db.password}" print="yes"
                 output="${db.tmp.dir}/@{sproc-name}.txt" onerror="stop" autocommit="true" encoding="UTF-8"
                 keepformat="true" showheaders="false" showtrailers="false">
                <classpath location="${db.driver.jar}"/>
                SELECT dbms_lob.substr(dbms_metadata.get_ddl(object_type, object_name), 4000, 1) FROM user_objects
                WHERE OBJECT_TYPE = 'PROCEDURE' and upper(object_name) = '@{sproc-name}'
            </sql>
        </sequential>
    </for>

</target>

答案 2 :(得分:0)

我做过类似的事情,我建议你用另一种语言编写DDL提取器/文件创建器(我使用Perl)并使用Ant exec 任务启动它 - 我知道这个有点不赞成,但是对另一种语言的炮轰比“SELECT DBMS_METADATA.GET_DDL ...”方法有一些优势:

(注意:您将要编写的外部程序仍然是DBMS_METADATA.GET_DDL的包装器)

  • 您可以以编程方式设置 DBMS_METADATA.SET_TRANSFORM_PARAM 选项,以提供更好的匹配 您的源控制标准。

  • 如有必要,您可以删除架构限定符。

  • 如果您的对象最初未通过Ant从源代码控制部署,您可以通过执行其他客户端程序可能引入的一些简单的空白转换来减少不匹配的噪音。

  • 如果你有这个标准,你可以更好地控制你生成的文件的扩展名(例如触发器的“.trg”)。