学习oci编程,从ociuldr开始
NinGoo's blog

学习oci编程,从ociuldr开始

Update:发现原来在linux上写的代码,到windows上编译会有些错误,主要是编译器对变量声明的位置容忍度不一样,已经修正了代码。另外对输出的日志做了一点增强,打印了导出的总时间,省得人工计算了。并将源代码,windows32位版本,linux32位版,及linux64版本一并打包提供下载测试。

一直想学学oci编程,无奈基础不好,几次都是看了几页文档就放下了。所以比较佩服老楼,写了很多优秀的工具,例如广泛使用的ociuldr,以及为很多人解决了难题的AUL等。最近老楼焕发第二春,对ociuldr做了大量改进,并且升级成了sqluldr2,刚刚获得的最新消息是,sqluldr2开始支持gzip压缩格式了,牛人就是牛。

上周六一大早跑到公司,处理完一点小事后,想想反正来了,就多呆会儿吧。干什么呢?溜达到老楼的blog上,看到一对sqluldr的信息,就花了一上午的时间研究了下老版的ociuldr的源代码,再参考hrb_qiuyb写的oci8版的ociuldr2,这次终于能看明白了,还是oci8的函数比较容易懂,于是就开始自己动手编译。hrb_qiuyb版的bug比较多,动不动就segment fault,想了想不如多花点时间,好好的重新改写一下,虽然老楼已经出了sqludr2,珠玉在前,不过最近流行山寨,他做企业版,我来做山寨版,哈哈。山寨版的名字,就叫tbuldr(ToolBox*UnLoader),因为是基于老楼开放出来的源代码弄的,那就继续开源吧,希望不要抢了sqluldr2的生意哈。

到今天为止,代码终于差不多稳定了,修复了几个主要的bug,同时把sqluldr2最新的一些特性也用山寨的方法实现了,可能效率不如老楼的,不过至少外观上看是差不多了,如输出到stdout新版本的sqlldr控制文件固定长度导出指定表名导出按列输出等功能一一实现了。

另外还实现了一些小的功能:

  • feedback参数,指定输出多少行以后打印一条日志,可以更好的观察进度,默认还是50w条。
  • enclose参数,为每列加入包含字符。当选择的field字符在列值中有出现的时候,enclose就有作用了。
  • fixlen参数,表示固定长度输出。而不是像sqluldr2一样当field指定为0×20(空格)的时候采用固定长度。这个主要是考虑到某些非常特殊的情况下,可能会有人希望用空格做分隔符而又不希望是固定长度的。
  • 还有个隐含的debug参数,打开后会输出一些debug信息,主要array fetch时为各列分配的内存等数据。这个主要是dw用了老楼很早以前的一个debug版本,觉得log里输出了列名还挺有用,就保留了,不过默认是不显示的,也没有写在help里,这里偷偷的透露一下了,哈哈
$tbuldr

----------------------------------------------------------------------------
- tbuldr: Release 2.21 (ociuldr)
- First issued by Lou Fangxin (@) Copyright 2004/2008, all rights reserved.
- Modified by Ning Haiyuan (http://www.NinGoo.net).
----------------------------------------------------------------------------
 Usage: TBULDR keyword=value [,keyword=value,...]
 Valid Keywords:
       user     = username/password@tnsname
       query    = select statement, can simply speicify a table name
       sql      = SQL file name
       field    = seperator string between fields
       record   = seperator string between records
       enclose  = fields enclose string
       file     = output file name, default: uldrdata.txt
       head     = print row header(Yes|No,ON|OFF,1|0)
       read     = set DB_FILE_MULTIBLOCK_READ_COUNT at session level
       sort     = set SORT_AREA_SIZE at session level (UNIT:MB)
       hash     = set HASH_AREA_SIZE at session level (UNIT:MB)
       serial   = set _serial_direct_read to TRUE if 1 at session level
       trace    = set event 10046 to given level at session level
       table    = table name in the sqlldr control file
       mode     = sqlldr option, INSERT or APPEND or REPLACE or TRUNCATE
       log      = log file name, prefix with + to append mode
       long     = maximum long field size, default 8192 max 65534
       array    = array fetch size, default 50
       buffer   = sqlldr READSIZE and BINDSIZE, default 16 (MB)
       feedback = display progress every x rows, default 500000
       form     = display rows as form (Yes|No)
       fixlen   = fix length format (Yes|No)

  for field, record and enclose, use '0x' to specify hex character code
  r=0x0d n=0x0a |=0x7c ,=0x2c t=0x09  (more: man ascii)
$tbuldr user=test/test query=t
       0 rows exported at 2009-04-16 20:43:53
    400 rows exported at 2009-04-16 20:43:54
         output file uldrdata.txt closed at 4 rows. Elapsed time: 0 min 1 sec.
         control file is t_sqlldr.ctl.

当然,山寨版就是山寨版,以下sqluldr2的新功能暂未实现:

  • parfile,这个是比较有用功能,可以防止命令行中显式输入密码导致密码泄漏等。因为涉及到文件内容解析,对我来说,难度有点高,以后再说。
  • gzip压缩,这是下午老楼刚刚加入的新特性,还有待研究。不过这是利用了zlib实现的,网上有不少现成的代码,集成进来应当是能搞定的。另外也可以输出到stdout后通过管道调用gzip实现压缩,这个已经支持了。
  • BLOB/BFILE等不提供支持,虽然BLOB可以按照LONG RAW的方式导出成16进制字符,不过不保证没问题,如果BLOB里存储的是字符应当问题不大。CLOB/LONG最大只支持到65534字节,对于大部分情况应当是足够了。

第一次用c和oci正儿八经的写东西,bug肯定一大堆。山寨有风险,慎用,如果是生产环境有需求的,建议还是找老楼的企业版,支持山寨版的同学,可以自行编译帮忙做测试,有bug和建议欢迎提交^_^

无觅相关文章插件,快速提升流量

本文网址:http://www.ningoo.net/html/2009/learn_oci_programming_from_ociuldr.html

订阅到Google | 收藏到Del.icio.us | 推荐到鲜果

上一篇: 下一篇:

本文Tags: , , , ,

17 条评论

  • At 2009.04.17 02:42, 木匠Charlie said:

    有为青年!

    • At 2009.04.17 02:44, 木匠Charlie said:

      我们下半年会用到sqluldr2, database -> search engine,到时候再给 老楼 付款.

      • At 2009.04.17 08:38, ochef said:

        牛人就是牛啊!

        • At 2009.04.17 09:00, NinGoo said:

          我们也马上要准备dump文本给搜索引擎用,所以才花了点时间来研究一下。

          • At 2009.04.17 11:01, anysql said:

            我在sqluldr2中也实现了你的全部需求.

            • At 2009.04.17 11:04, jacky said:

              牛人们就是不一样,你们做好了,我只管用就行。

              • At 2009.04.18 00:37, shengang34 said:

                宁子,加油!

                • At 2009.04.20 05:47, 圣荷 said:

                  看来的确付出挺多,相信成绩大大地!呵呵

                  • At 2009.05.05 16:09, funcc said:

                    Bug提交,我在Windows下运行,使用的query指定sql语句,报ORA-933,trace一下,后台执行的是select * from ect * from orders.
                    另外,希望这里下载的总是最新版。

                    • At 2009.05.06 09:33, NinGoo said:

                      多谢。这里是最初的版本的,新的版本后来一直在测试中,所以也就没有更新上来。新版本已经修改了很多地方,下周会重新编译打包上来。

                      • At 2009.05.07 11:09, funcc said:

                        期待新版本的发布。

                    • At 2009.05.25 16:14, l1t said:

                      语法不对?
                      /oracle>time /oracle/tbuldr.exe user=test/test query=”select * from j601″ file=’j601.csv’ head=Yes
                      Error – ORA-00933: SQL command not properly ended

                      /oracle>time /oracle/tbuldr.exe user=test/test query=j601 file=’j601.csv’ head=Yes

                      0 rows exported at 2009-05-25 16:31:48
                      Error – ORA-24374: define not done before fetch or execute and fetch

                      output file j601.csv closed at 0 rows. Elapsed time: 0 min 0 sec.
                      control file is j601_sqlldr.ctl

                      • At 2009.05.25 16:16, l1t said:

                        /oracle>gcc -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I${ORACLE_HOME}/rdbms/public -I${ORACLE_HOME}/rdbms/demo -L${ORACLE_HOME}/lib32 -lclntsh -o tbuldr.exe tbuldr.c
                        tbuldr.c:29:1: 警告:“MIN”重定义
                        在包含自 /usr/include/limits.h:411 的文件中,
                        从 /usr/local/lib/gcc/hppa2.0w-hp-hpux11.11/4.2.3/include/limits.h:122,
                        从 /usr/local/lib/gcc/hppa2.0w-hp-hpux11.11/4.2.3/include/syslimits.h:7,
                        从 /usr/local/lib/gcc/hppa2.0w-hp-hpux11.11/4.2.3/include/limits.h:11,
                        从 /oracle/product/10.2/rdbms/public/oratypes.h:17,
                        从 /oracle/product/10.2/rdbms/public/oci.h:467,
                        从 tbuldr.c:13:
                        /usr/include/sys/param.h:379:1: 警告:这是先前定义的位置

                        • At 2009.10.20 11:11, shark said:

                          你的能支持COLB字段吗? 而且生产CTL吗?

                          • At 2009.10.20 13:43, NinGoo said:

                            clob是可以的,control文件也能生成。不过这个版本还是有很多小bug的。后续因为anysql的也可以免费提供了,我就没有继续开发了。有需要可以去www.anysql.net找找

                          • At 2010.07.29 10:49, supsyg said:

                            试了一下,速度还不错,但tns连接好像还不支持:
                            ./tbuldr.exe user=test/test@lmode29 sql=t.sql field=0x7c file=test.txt
                            Error – ORA-12154: TNS:could not resolve the connect identifier specified

                            Error – ORA-24327: need explicit attach before authenticating a user
                            但如果是不加连接串,没有问题。

                            • At 2010.07.30 15:38, NinGoo said:

                              @supsyg 这个应该是tnsname本身有问题吧,用sqlplus连接正常么?

                              PS:这个是已经很久没有去更新和fix bug了。如果有这个需求,可以用anysql.net的sqluldr2。


                            (Required)
                            (Required, will not be published)