1

我希望能够有一个 ant 任务,它可以连接到远程 oracle 实例并将存储过程分别复制到自己的文件中。我知道我可以有一个 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 中的内容进行比较)。

有任何想法吗?

谢谢!亚历克斯

4

3 回答 3

1

看起来您已经弄清楚了如何构造 SQL 语句并将结果从数据库服务器获取到您的机器中最难的部分。

现在这样做。

  1. 构造 SQL 语句以获取所有存储过程名称。
  2. 执行<loadfile property="procnames" file="result-of-sql-run.txt"/>
  3. 使用antcontrib for task 迭代存储过程名称

以下是迭代的方法:

   <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 连接到数据库,您能发布您的解决方案吗?

于 2009-10-13T01:43:28.067 回答
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>
于 2009-10-13T18:16:52.180 回答
0

我做过类似的事情,我建议你用另一种语言(我使用 Perl)编写 DDL 提取器/文件创建器,并使用 Ant exec任务启动它 - 我知道这有点不受欢迎,但要向另一个与“SELECT DBMS_METADATA.GET_DDL...”方法相比,语言为您提供了一些优势:

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

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

  • 如有必要,您可以去掉模式限定符。

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

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

于 2009-10-13T12:32:01.713 回答