楼主: yulihua49

[PRO*C] 看我做的数据库包装器

[复制链接]
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
11#
发表于 2008-11-20 10:01 | 只看该作者
我说没用绑定变量是指这几个地方:
       p+=sprintf(p,"where start_date=to_date('%s','YYYY-MM-DD') ",
                rjultostrfmt(buf,today,"YYYY-MM-DD")); //日期转字符串

                p+=sprintf(p,"and train_no='%s' ",Train_no);

                p+=sprintf(p,"and carno='%s' ",carno);

"现在,我的C程序员可以只写应用逻辑啦,不必关心SQL,只要知道这20来个函数就行了。"
我想像不出,拿掉了SQL, 还剩下什么应用逻辑?不关心SQL的程序员能写出高质量的事务处理模块?除非你说的是UI(用户交互,输入输出格式化)?
你这种方法其实是把SQL肢解得支离破碎,给调试、调优制造了障碍。

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
12#
 楼主| 发表于 2008-11-20 17:09 | 只看该作者
原帖由 newkid 于 2008-11-20 10:01 发表
我说没用绑定变量是指这几个地方:
       p+=sprintf(p,"where start_date=to_date('%s','YYYY-MM-DD') ",
                rjultostrfmt(buf,today,"YYYY-MM-DD")); //日期转字符串

                p+=sprintf(p,"and train_no='%s' ",Train_no);

                p+=sprintf(p,"and carno='%s' ",carno);

"现在,我的C程序员可以只写应用逻辑啦,不必关心SQL,只要知道这20来个函数就行了。"
我想像不出,拿掉了SQL, 还剩下什么应用逻辑?不关心SQL的程序员能写出高质量的事务处理模块?除非你说的是UI(用户交互,输入输出格式化)?
你这种方法其实是把SQL肢解得支离破碎,给调试、调优制造了障碍。

你知道JAVA的Hibernate(ORM,Object Relational Map)吗?也叫JAVA bean,就是业务逻辑与访问逻辑分离的思想,我们老板很欣赏。就是:业务逻辑只面向对象(在C,就是struct),根本不必关心数据库的存在,或者是哪种数据库。
因此,逼得我只好写了一个DTO,负责把数据库的东西传到struct,才写完,所以拿出来给大家看看。不过,干完这事,的确觉得这个思想真不错。应用程序只写业务逻辑啦,想要数据就跟DTO要一个,想修改,就:
     //准备好where子句,然后:
     ret=DTO_update(&_DTO,where);// 就行了,修改的条数在ret里。
想插入新纪录就:
     //在struct里准备好数据,然后:
      ret=DTO_insert(&_DTO,msg);    //就行了,如果出错,msg里有信息。
你看省事不省事?
用PROC*C,insert和update是多么痛苦啊!

现在,我们这的孩子们根本就不用学习SQL啦,只用DTO。
另外,where不需要绑定变量的,只用C变量就可以了。
调试非常简单啊,把语句打在日志里,粘到SQLplus里就可以执行了。见1楼注释里的语句,就是从日志里粘出来的。
这个系统可以进行多表联合查询,看3楼的.h,DTO_getm()和DTO_nextm()就是做多表的。

这个系统就是为了开发高性能TUXEDO应用服务器的,已经测试过,性能非常高,在IA64服务器,SUSE系统,ORA10G数据库,
每秒能够;
Fetch 6万条记录,插入900条。

我反而认为,复杂怪异的SQL语句效率未必高。简单语句 + C程序的处理逻辑才是真正高效,十多年的经验。

[ 本帖最后由 yulihua49 于 2008-11-20 17:33 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
13#
 楼主| 发表于 2008-11-20 17:47 | 只看该作者
原帖由 zhangfengh 于 2008-11-20 09:15 发表
唉,为什么这么多人都把sql当做洪水猛兽呢

应用程序不允许出现SQL语句有什么好处?


我们的应用非常复杂,用户需求永远搞不清,业务逻辑时时修改,数据结构经常变化。如果我们用PROC*C,
大量的SQL语句,每一个SQL语句都牵涉到大量的列名,一旦数据结构变化,我改不起啊!
现在,有了DTO,进一步,把那个仅存的where,放到DAO(Data Access Object)里,业务程序中完全消灭了SQL。
现在,某表增加了一个列,只需修改模板(自动模板器连这个也省略)。原来的业务程序,只要没有涉及新加的列,都无需修改。
你看1楼的例子,如果SEAT表结构改变,我的程序没有任何变化的。当然这只是个DEMO,没有业务逻辑的,只是把读到的各行以JSON格式打印而已。

[ 本帖最后由 yulihua49 于 2008-11-20 17:50 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
14#
 楼主| 发表于 2008-11-20 18:02 | 只看该作者
我想像不出,拿掉了SQL, 还剩下什么应用逻辑?

没有了SQL,就剩下业务逻辑了,就是面向业务规则的那些东西:
看看这一段程序:
DTO_init(&seat_DTO,ctx->SQL_Connect,"SEAT",&seat,seat_type);
//getSeat_for_sell(), 这是个DAO,有人写这个DAO,你不需要关心。你只要知道它为售票而取席位就行了。
//它的条件是:始发日期、车次、上车站、下车站、席别、用途、数量。
        if(0!=getSeat_for_sell(&seat_DTO,app.start_date,app.Train_no,app.beg_station,app.arrive,
                app.xb,app.purpose,app.quantity,msg)) {
                DTO_free(&seat_DTO);
                return -1;
        }
        p=0;
        for(i=0;i<app.quantity;i++) { //每张票
        JSON_OBJECT *json;
                if(ret=DTO_next(&seat_DTO)) { //取一个数据
                        if(ctx->SQL_Connect->Errno==LOCKED) {
                                ShowLog(4,"getxw LOCKED continue next");
                                i--;
                                continue;
                        }
                        break;
                }
//把取到的席占用
                seat.flag=1;
                seat.used_time=now;
                strcpy(seat.used_uid,userid);
                strcpy(seat.used_dev,devid);

                ret=updateSeat_by_ROWID(&seat_DTO,seat.ROWID,msg);//这也是个DAO
                if(ret != 1) {
                        ShowLog(1,"占用席位失败,stmt=%s,ROWID=%s", msg,seat.ROWID);
                        i--;
                        continue;
                }
            

你要是特别关心DAO是什么样子,在seat_DAO.c里:
//where已经比较充分体现了业务逻辑与访问逻辑的关联,至于数据内容,不必关心了吧?
int getSeat_for_sell(DTO *DP,char *strdate,char *Train_no,char *beg_station,int arrive,int xb,int purpose,int quantity,char *stmt)
{
int ret;

        if((xb%10)==0) { //软卧 硬卧的查询
            sprintf(stmt,"WHERE START_DATE=to_date('%s','%s') AND "
                        "BEG_STATION = '%s' AND "
                        "TRAIN_NO = '%s' AND "
                        "SEAT_TYPE > %d  AND SEAT_TYPE <= %d AND "
                        "END_STATION >= %d AND PURPOSE=%d AND FLAG=0 AND ROWNUM<%d "
                        "ORDER BY END_STATION,CARNO,SEAT_NO,SEAT_TYPe ",
                strdate,YEAR_TO_DAY,
                beg_station,Train_no,
                xb,xb+9, arrive,purpose, quantity+2 );
                if(xb==0) strcat(stmt,"desc ");
                strcat(stmt,"for update WAIT 10 SKIP LOCKED");
        } else {
                sprintf(stmt,"WHERE START_DATE=to_date('%s','%s') AND "
                    "BEG_STATION = '%s' AND TRAIN_NO = '%s' AND "
                    "seat_type = %d and end_station >= %d AND PURPOSE = %d AND "
                    "FLAG=0 AND ROWNUM<%d ORDER BY END_STATION,CARNO,SEAT_NO "
                    "FOR UPDATE WAIT 10 SKIP LOCKED",
                        strdate,YEAR_TO_DAY,
                        beg_station, Train_no,
                        xb, arrive, purpose,
                        quantity+2 );
        }
         DP->srm.selectExtra="/* +role */";
              ret=DTO_prepare(DP,stmt);
              ShowLog(5,"seat_DAO:%s,ret=%d",stmt,ret);//stmt里已经是完整的语句啦。
              return ret;
     }

      
        int updateSeat_by_ROWID(DTO *DP,char *ROWID,char *stmt)
{
        sprintf(stmt,"WHERE ROWID='%s'", ROWID);
        return DTO_update(DP,stmt);
}

[ 本帖最后由 yulihua49 于 2008-11-20 18:18 编辑 ]

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
15#
发表于 2008-11-21 00:21 | 只看该作者
"你知道JAVA的Hibernate(ORM,Object Relational Map)吗?也叫JAVA bean,就是业务逻辑与访问逻辑分离的思想,我们老板很欣赏。就是:业务逻辑只面向对象(在C,就是struct),根本不必关心数据库的存在,或者是哪种数据库。"
建议你或者你们老板去看看TOM KYTE的书, 这一节详细论述了为什么“数据库无关”是不可取的:
http://book.csdn.net/bookfiles/82/100822248.shtml
每种数据库实现原理不一样(比如说,锁的机制),数据库提供了一些特有的(不通用的)功能(比如说,ORACLE的分析函数,CONNECT BY等),试图使用通用的SQL就牺牲了高效率方案。

"     //准备好where子句,然后:
     ret=DTO_update(&_DTO,where);// 就行了,修改的条数在ret里。
想插入新纪录就:
     //在struct里准备好数据,然后:
      ret=DTO_insert(&_DTO,msg);    //就行了,如果出错,msg里有信息。
你看省事不省事?
用PROC*C,insert和update是多么痛苦啊!"

恰恰相反,在存储过程里写一个INSERT或UPDATE的代码十分清爽且赏心悦目。要我把WHERE剥离出来交给另外一个程序,这才痛苦呢,程序都没法看了。


"现在,我们这的孩子们根本就不用学习SQL啦,只用DTO。"
不管用不用存储过程,要和关系数据库打交道就得掌握SQL技巧,要不然这些孩子长大后迟早会付出代价。


"另外,where不需要绑定变量的,只用C变量就可以了。"
这是你的误区,你的WHERE中充满了常量,你的共享池将会塞满大同小异的SQL,你的数据库将会耗费大量CPU在不必要的硬解析,而且这个问题不是靠升级硬件能够解决的。

"调试非常简单啊,把语句打在日志里,粘到SQLplus里就可以执行了。见1楼注释里的语句,就是从日志里粘出来的。"
如果出了性能问题,怎么才能找到产生SQL的代码?你怎么知道要打印哪个语句?


"这个系统可以进行多表联合查询,看3楼的.h,DTO_getm()和DTO_nextm()就是做多表的。"
谁来写连接条件?多级子查询写在哪?不懂SQL的孩子们能搞定?


"这个系统就是为了开发高性能TUXEDO应用服务器的,已经测试过,性能非常高,……"
本来可以更高的。你最大的问题在于绑定变量。


"我反而认为,复杂怪异的SQL语句效率未必高。简单语句 + C程序的处理逻辑才是真正高效,十多年的经验。"
高效的SQL+PL/SQL处理逻辑才是王道,二十年的经验。
我不是倚老卖老,这是很多业内人士的共识(尤其在这里,一个数据库论坛)


"我们的应用非常复杂,用户需求永远搞不清,业务逻辑时时修改,数据结构经常变化。如果我们用PROC*C,
大量的SQL语句,每一个SQL语句都牵涉到大量的列名,一旦数据结构变化,我改不起啊!"
"现在,某表增加了一个列,只需修改模板(自动模板器连这个也省略)。原来的业务程序,只要没有涉及新加的列,都无需修改。"

需求变更从来都不是增加一个、几个列名那么简单。有时候需要增加新表,有时候要修改关系;修改肯定是有代价的,不管你修改的是C程序,还是存储过程。模块化作得好的话,这种代价就可降到最低。

"你看1楼的例子,如果SEAT表结构改变,我的程序没有任何变化的。当然这只是个DEMO,没有业务逻辑的,只是把读到的各行以JSON格式打印而已。"
如果改变的结构用于业务逻辑,则无论你用什么方法实现(C程序,存储过程),都不可避免要修改。你这个通用输出程序本来就是客户端的东西,和存储过程无关。

"没有了SQL,就剩下业务逻辑了,就是面向业务规则的那些东西:
看看这一段程序:"
这段程序无非就是取一个空位打上占用标记,用PL/SQL来写的话程序更简洁。
我很想知道你是怎么处理并发的,ctx->SQL_Connect->Errno==LOCKED具体在数据库端是怎么实现的?用SELECT FOR UPDATE NOWAIT?
你这段程序很可能两个SESSION 取到同一行,并且都认为它是空的。

"你要是特别关心DAO是什么样子,在seat_DAO.c里:"
再次提醒:你的WHERE没有用绑定变量!好好去想办法解决,即使你不使用存储过程!

[ 本帖最后由 newkid 于 2008-11-21 04:37 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
16#
 楼主| 发表于 2008-11-21 09:14 | 只看该作者
原帖由 newkid 于 2008-11-21 00:21 发表


看看这一段程序:"
这段程序无非就是取一个空位打上占用标记,用PL/SQL来写的话程序更简洁。
我很想知道你是怎么处理并发的,ctx->SQL_Connect->Errno==LOCKED具体在数据库端是怎么实现的?用SELECT FOR UPDATE NOWAIT?
你这段程序很可能两个SESSION 取到同一行,并且都认为它是空的。


看样子,我们老板与你在技术路线上是完全两股道上跑的车( 老板禁止使用存储过程),我现在只能听老板的。
我这个正是铁路客票处理,很怕重码的,小心你哪天的票与别人重了!笑话,看seat_DAO,
那不是有 for update WAIT 10 SKIP LOCKED吗?,而且使用了DTO_prepare,以后的DTO_next会自动进行Fetch,DTO_free会自动进行close cursor。事务在这个程序之外,这个程序(还有一堆其他程序)成功,commit,否则rollback。结果将被送到客户端,制票将有客户端处理。这是TUXEDO服务器,三层模型。
我们不仅使用了加锁,而且跳锁,即,你占用了1、2、3号,同时别人可以抢4、5、6号。一个资源可以成百上千的终端进行争夺。
ctx->SQL_Connect->Errno==LOCKED具体在数据库端是怎么实现的:
SQL_Connect是一个数据库句柄,里边有登录信息、错误信息,OCI句柄等等。有时用SYBASE,就放入CT_LIB的环境,不过这对用户透明。在对数据库操作时,取OCI的信息和状态码,放在SQL_Connect里,应用程序就得到啦!
LOCKED、SQLNOTFOUND、DUPKEY是宏定义,在ORACLE、SYBASE、INFORMIX里不同。

[ 本帖最后由 yulihua49 于 2008-11-21 10:22 编辑 ]

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
17#
发表于 2008-11-21 10:53 | 只看该作者
呵呵,我没打算说服你们改变技术路线,只是想传播革命火种。
那个关于WHERE绑定变量的建议是货真价实的,听不听就由你了。
至于那个并发处理,等我明天有空了仔细看看。

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
7
BLOG每日发帖之星
日期:2008-11-24 01:01:03BLOG每日发帖之星
日期:2009-01-20 01:01:05BLOG每日发帖之星
日期:2009-02-02 01:01:04BLOG每日发帖之星
日期:2009-03-27 01:01:10BLOG每日发帖之星
日期:2009-06-15 01:01:022010新春纪念徽章
日期:2010-03-01 11:08:29ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28
18#
发表于 2008-11-21 11:28 | 只看该作者
楼主和newkid的看法其实是现在两种经常争论的观点,
前者试图写一个非常强大的中间层,所有业务和数据逻辑都放在中间层上,
这样换一种数据库,譬如Oracle、sqlserver、mysql、access都可以运用,
缺点是通用性的sql往往无法达到很高的效率,你想你又要兼容oracle,
又要兼容access,从某种角度上等于oracle在你这里很多优化都使用不了,
只能发挥等同access的性能,当并发数多,数据量大的时候,性能问题尤其明显。

后者则把业务和数据逻辑,尽量使用数据库内置的function来处理,
这样的好处是能最大化发挥数据库的强项和新特性,楼主你总不能
自信到认为自己写的中间层,比Oracle和微软写得性能一样快吧??
缺点是如果换数据库,不同数据库内置的function不同,需要改
相当多的程序。

我觉得问题还是出于利益分配吧,中间层厂商当然希望逻辑都放中间层,
这样产品才能卖得多,卖得贵,Oracle当然希望逻辑都放数据库端,
更多地利用数据库提供的功能,这样才能鼓励用户升级数据库版本,
而且习惯oracle,不会因为觉得贵,
而试图用更便宜的sqlserver或是mysql。

[ 本帖最后由 asword 于 2008-11-21 11:40 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
19#
 楼主| 发表于 2008-11-21 16:30 | 只看该作者
原帖由 newkid 于 2008-11-21 10:53 发表
呵呵,我没打算说服你们改变技术路线,只是想传播革命火种。
那个关于WHERE绑定变量的建议是货真价实的,听不听就由你了。
至于那个并发处理,等我明天有空了仔细看看。

不同的技术观点,争论一下没有害处,大家都可以思考一下对方的道理。
我们这里是这样的,少数懂SQL的写DAO,这样的人很贵的,公司不想养太多,这就是老板的思想。
大批的程序员只要大概知道SQL是怎么回事就行了,专心研究业务。

另外,你看那个seat_DAO,如果更换数据库,或调优(这些都属于修改访问逻辑,而非业务逻辑),只要改写这一段就行了,使用这个DAO的程序会有很多,就不用一一修改了。访问逻辑属于DAO,业务逻辑属于应用,分的很清楚。

我这个中间层,可以处理复杂SQL的。
比方下边的SQL,是自动生成模板用的,从数据库中读表结构:
SELECT  c.table_name,c.column_name,decode(data_type, 'CHAR',1, 'VARCHAR',1, 'VARCHAR2',1, 'DATE',129,'FLOAT',8, 'LONG',126, 'NUMBER',decode(nvl(DATA_SCALE,0),0, decode(nvl(data_precision,0), 0,257, 1,2, 2,2, 3,3, 4,4, 5,4, 6,4, 7,4, 8,4,9,4, 10,6, 11,6, 12,6, 13,6, 14,6, 15,6, 16,6, 17,6, 18,6, 257),8),257) Fld_Column_Type,decode(data_type, 'CHAR',data_length+1, 'VARCHAR',data_length+1,'VARCHAR2',data_length+1, 'DATE',20,'FLOAT',8,'LONG',-1, 'NUMBER', decode(nvl(DATA_SCALE,0),0,decode(nvl(data_precision,0), 0,35, 1,1, 2,1, 3,2, 4,4, 5,4, 6,4, 7,4, 8,4, 9,4, 10,8, 11,8, 12,8, 13,8, 14,8, 15,8, 16,8, 17,8, 18,8, 257),8),35) Fld_Column_Len,decode(data_type, 'CHAR',null, 'VARCHAR',null, 'VARCHAR2',null, 'DATE','YYYY-MM-DD HH24:MI:SS','FLOAT','%%lg','LONG',null, 'NUMBER',decode(nvl(DATA_SCALE,0),0,null,'%%'||to_char(data_precision+2)||'.'||to_char(DATA_SCALE)||'lf'),null) Fld_Format,k.position

FROM all_tab_columns c, (select table_name,column_name,position from all_cons_columns where owner='TICKET' and table_name='SEAT' and position is not null) k

where c.table_name = k.table_name(+) and c.column_name = k.column_name(+) and c.owner = 'TICKET' and c.table_name='SEAT' order by c.table_name, c.column_id

估计没几个人能马上看明白。

接下贴

[ 本帖最后由 yulihua49 于 2008-11-21 16:41 编辑 ]

使用道具 举报

回复
论坛徽章:
14
2009新春纪念徽章
日期:2009-01-04 14:52:28沸羊羊
日期:2015-03-04 14:51:52优秀写手
日期:2014-03-14 06:00:13马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:022013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15蜘蛛蛋
日期:2012-06-27 21:08:142012新春纪念徽章
日期:2012-01-04 11:53:29ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
20#
 楼主| 发表于 2008-11-21 16:43 | 只看该作者
//这个结构并不对应具体的表,所以模板必须手工写
// 你可以看到,这个select 6个字段,分别进行代码变换。
static T_PkgType PARTTERN_type[]={
        {CH_CHAR,49,"c.table_name",0,-1},
        {CH_CHAR,49,"c.column_name"},
        {CH_SHORT,sizeof(short),
                "decode(data_type, 'CHAR',1, 'VARCHAR',1, 'VARCHAR2',1, 'DATE',129,'FLOAT',8, "
                "'LONG',126, 'NUMBER',decode(nvl(DATA_SCALE,0),0, "
                "decode(nvl(data_precision,0), 0,257, 1,2, 2,2, 3,3, 4,4, 5,4, 6,4, 7,4, 8,4,"
                "9,4, 10,6, 11,6, 12,6, 13,6, 14,6, 15,6, 16,6, 17,6, 18,6, 257),8),257) "
                "Fld_Column_Type"},
        {CH_SHORT,sizeof(short),"decode(data_type, 'CHAR',data_length+1, 'VARCHAR',data_length+1,"
                "'VARCHAR2',data_length+1, 'DATE',20,'FLOAT',8,'LONG',-1, 'NUMBER', "
                "decode(nvl(DATA_SCALE,0),0,decode(nvl(data_precision,0), 0,35, 1,1, 2,1, 3,2, "
                "4,4, 5,4, 6,4, 7,4, 8,4, 9,4, 10,8, 11,8, 12,8, 13,8, 14,8, 15,8, 16,8, 17,8, "
                "18,8, 257),8),35) "
                "Fld_Column_Len"},
        {CH_CHAR,30,"decode(data_type, 'CHAR',null, 'VARCHAR',null, 'VARCHAR2',null, "
                "'DATE','YYYY-MM-DD HH24:MI:SS','FLOAT','%%lg','LONG',null, "
                "'NUMBER',decode(nvl(DATA_SCALE,0),0,null,"
                "'%%'||to_char(data_precision+2)||'.'||to_char(DATA_SCALE)||'lf'),null) "
                "Fld_Format"},
        {CH_SHORT,sizeof(short),"k.position"},
        {-1,0,0,0}
};

还需要公告一个数据结构:
typedef struct  {
        char Fld_Tlb_Name[49];
        char Fld_Column_Name[49];
        short Fld_Column_Type;
        short Fld_Column_Len;
        char Fld_Format[30];
        short Fld_PK;
} PARTTERN_s;

二者是完全对应的。

[ 本帖最后由 yulihua49 于 2008-11-21 16:57 编辑 ]

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表