【问题标题】:SQL*Plus - Spool into multiple filesSQL*Plus - 假脱机成多个文件
【发布时间】:2020-07-02 00:31:09
【问题描述】:

我有下一个将user_tables 的 DDL 存储到文件中的线轴:

set pagesize 0
set long 90000
spool C:\Users\personal\Desktop\MAIN_USR\test.txt
select DBMS_METADATA.GET_DDL('TABLE',table_name,'MAIN_USR')
FROM user_tables ut;
spool off
exit

它将所有user_tables 的 DDL 返回到一个文件中,但我需要它更加动态,并将它们返回到带有各自表的文件名的单独文件中。像这样的:

set pagesize 0
set long 90000
FOR tab_nam IN (SELECT table_name FROM user_tables) LOOP
   spool C:\Users\personal\Desktop\MAIN_USR\test.txt
      select DBMS_METADATA.GET_DDL('TABLE',table_name,'MAIN_USR')
      FROM user_tables ut;
   spool off
END LOOP;
exit

我知道上面的那个行不通,但这是我想要做什么的一种想法。

感谢任何形式的帮助

【问题讨论】:

  • 使用更好的工具,让您有更多的控制权。想到了 Python cx_Oracle。

标签: oracle for-loop plsql sqlplus spool


【解决方案1】:

使用 python 的 cx_Oracle 模块可以访问 Oracle 数据库可能是您的案例的优雅方式:

import cx_Oracle
con = cx_Oracle.connect('uname/pwd@host:port/service_name')
cur = con.cursor()

def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
    if defaultType == cx_Oracle.CLOB:
        return cursor.var(cx_Oracle.LONG_STRING, arraysize = cursor.arraysize)

cur.outputtypehandler = OutputTypeHandler

cur.execute("select table_name from user_tables order by 1")
rec = cur.fetchall()

for r in rec:
    cur.execute("select dbms_metadata.get_ddl('TABLE',:tableName) from dual",tableName=r[0])
    ddl, = cur.fetchone()

    file = r'C:\\Users\\personal\\Desktop\\MAIN_USR\\'+r[0]+'.txt' 

    with open(file,"w") as f:
            f.write(ddl)
    f.close()

其中整个schema的表名是通过第一个cur.execute确定的,第二个是创建DDL,最后一步是用各自的表名创建文件。需要考虑的重要事项与 OutputTypeHandler 的使用有关,因为无需处理源自 Dbms_Metadata.Get_Ddl 函数的 CLOB 结果。编译器不希望在创建文件期间获得 CLOB 值,否则 DDL 会太长以至于超过 4000 个字符的长度,这将阻止 to_char 转换并在不使用 OutputTypeHandler 的情况下引发错误。

【讨论】:

    【解决方案2】:

    您需要阅读 USER_TABLES 以创建对 DBMS_METADATA.GET_DDL 的 N 次调用,每个调用都有自己的假脱机文件。将所有内容假脱机到一个名为 out.sql 的文件中,并在假脱机后运行它

    set pagesize 0
    set long 90000
    
    SET TERMOUT OFF
    spool out.sql
    
    select 'spool C:\Users\personal\Desktop\MAIN_USR\'||REPLACE(table_name, '$', '_')||'.txt'||chr(13)||chr(10)||
    'SELECT DBMS_METADATA.GET_DDL(''TABLE'','''||table_name||''',''MAIN_USR'') FROM DUAL;'||chr(13)||chr(10)||
    'spool off' as cmd
    FROM user_tables ut;
    
    spool off
    
    @OUT.SQL
    
    exit
    

    【讨论】:

    • 它可以工作,但是文件中有些表没有返回它们的元数据,不幸的是大部分
    • 您能否检查在 OUT.SQl 文件中每次调用 DBMS_METADATA.GET_DDL 后“spool off”命令是否始终存在?
    • 是的。我看到问题是当 spool 为每个文件分配一个名称时,因为名称看起来不完整
    猜你喜欢
    • 2011-02-03
    • 2012-07-30
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多