|
我这里今天早上的备份...
newkid
资深新手
老程序员
来自 银河系
精华贴数 15
个人空间 0
技术积分 20752 (73)
社区积分 5 (22147)
注册日期 2004-6-26
论坛徽章:66
#151
使用道具
发表于 2011-9-14 00:36
"DAU那点东西一点没省,为了帮你解析json参数,还增加了一段。"
谁说没省?你不用读模版了,不用读字典了,不用生成SQL/绑定变量了,这一大堆不是省下来的?
至于那些格式解析、打包等东西,我同意转移到外面来。
"你看我的代码:有关于裸数据的处理。我试图把存储过程改成裸数据,没整明白,改不了。"
我找来找去只在这里见到一个:
http://ellebaek.wordpress.com/20 ... g-plsql-java-and-c/
Here's the implementation of the C external procedure (refcurdesc.c):
.......
他说这个C外部过程用OCI解析REF CURSOR, 你看看是不是。
"我很奇怪,这里的人都搞些什么应用?光用存储过程就行了?"
光用存储过程的应该也不多,但是学会PLSQL肯定是有用的。
"代码不好读?脑袋里不要老想着SQL,你要读的是业务逻辑。读到调用DAO时,哦,这个DAU取得了它的数据。不要想怎么取。这样一个业务逻辑的大脉络就清晰了。"
对我来说SQL就是业务逻辑的一部分,“取得数据的方法”是重要的一环,这里没写好就会影响整个事务的性能。
就是用PLSQL写存储过程,也有人主张用你的方法,把数据存取分离出来,变成子过程,业务逻辑层不写SQL, 而是调用子过程。我也不是反对这种做法,假如分离出去的部分可以重用、可以改善可读性,也未尝不可。注意前面的两个前提。
"具体如何取得数据,单看DAO程序,你可以看到WHERE条件,这一般就够了。干嘛还非要看有哪些列呢?要看列,就看模板。这好像没什么难度。
即使你的程序罗列了列名,一般我也是不看的(好多人喜欢select *),只看WHERE。"
对我来说,取得哪些列也是重要一环。要修改表结构的时候,如果有这些静态SQL, 你可以快速知道哪些程序会受影响。
"看来大家对这个工作乐此不疲,那就不用模板也罢。"
我对PLSQL里面写SQL乐此不疲,我用静态SQL从来不需要PARSE,BIND,FETCH,CLOSE。
"我觉得有些人似乎是SQL依赖症。"
我很荣幸地对号入座。
"有说DAU程序不好懂的,看看这个,提意见。"
我还真的硬着头皮读了#150的程序。结论:不敢恭维。
insert_DAO最后一个参数stmt干什么用?看样子不像是往里传数据,因为OAD_exec没有用到它;反而出错的时候被改写(*stmt=0),但是只在update_by_PK使用,又不会返回任何数据给调用者?
(我又读了程序发现这个源头来自loadfile的参数buf,难道你是为了避免重复分配内存?那也应该有别的方法吧,何苦把程序接口弄得这么复杂?)
你既然有oad参数,数组长度应该不难得到,为什么还要设计第二个参数n?
num=_DAU.srm.tp[_DAU.srm.Aflg].offset; ------- 这个我说是天书有谁能反对?
再看你读文件的循环:
if(feof(ifd)) break;
这里不要急着出去嘛,先把“零头”处理了再退出,外面也少一段程序。
//返回后,还会有一个 ___SQL_Transaction__(SQL_Connect,TRANCOMMIT);
这个有点搞,你循环里面都提交了,为什么做完反而不提交,而要留给后面的代码?
[ 本帖最后由 newkid 于 2011-9-14 01:57 编辑 ]
__________________
世界上只有两种编程方法:Oracle的方法和错误的方法。
剑破冰山—Oracle开发艺术 即将隆重推出
http://www.china-pub.com/197199
http://www.huachu.com.cn/itbook/itbookinfo.asp?lbbh=10114321
只看该作者 引用 回复 报告 编辑
yulihua49
初级会员
精华贴数 1
个人空间 18
技术积分 1509 (1609)
社区积分 0 (1312844)
注册日期 2007-2-1
论坛徽章:3
#152
使用道具
发表于 2011-9-14 09:27
为什么服务函数可以写明全部列?
比如,有一个存根表,原先有80多列,现在有150多列。
这个表在售票、订票、退票、检票、中转、改签、取票、TVM、错票处理,电子票流程,支付,统计,审核、清算。。。。。。。都要访问,不少于几十处。
由好几个人和小组参与。所以,一个模板要生成许多语句。多数程序修改表结构时,除了更换模板,不需要修改。
下例是售票记账模块:没给表结构,影响读懂处理逻辑吗?
[Copy to clipboard] [ - ]
CODE:
/* 售票记账服务 */
int sell_app(GDA *ctx,char *data,char *msg,JSON_OBJECT errjson)
{
int ret,newvol=0;
SELL_stu sell;
SEAT_stu seat;
DEV_BILL_stu dbill;
DAU sell_DAU,seat_DAU,bill_DAU;
JSON_OBJECT json;
json=json_tokener_parse(data);
if(!json) {
sprintf(msg,"输入的数据格式错!");
json_object_array_add(errjson,jerr(100,msg));
return FORMATERR;
}
DAU_init(&sell_DAU,ctx->Connect,0,&sell,SELL_tpl);
DAU_init(&seat_DAU,ctx->Connect,0,&seat,SEAT_tpl);
data_init(&seat,SEAT_tpl);
DAU_fromJSON(&seat_DAU,json); //包括end_station
//存根的数据都是前端来的,随便多少列。那些列需要在表单上处理,或打印在票面上。或是从其他数据组合(如支付系统等)而成。与本服务器无关。
DAU_fromJSON(&sell_DAU,json);
json_object_put(json);
//检查操作权限
if(ret=checkperm(ctx,&sell,msg)) {
json_object_array_add(errjson,jerr(ret+100,msg));
DAU_free(&sell_DAU);
DAU_free(&seat_DAU);
return -1;
}
// ??? 如果是订单售票,查找订单
// 修改席位和余额库
DAU_copy(&sell_DAU,&ctx->ctx_DAU,0);
strcpy(seat.used_dev,ctx->contex.devid);
strcpy(seat.used_uid,ctx->contex.userid);
seat.used_time=ctx->contex.last_oper;
ret=sell_seat(&seat_DAU,msg,errjson);//comm_app.c,席位售出,如果需要分段在此进行
DAU_free(&seat_DAU);
if(ret) {
DAU_free(&sell_DAU);
return ret;
}
//调整票据号
DAU_init(&bill_DAU,ctx->Connect,0,&dbill,DEV_BILL_tpl);
strcpy(dbill.devid,ctx->contex.devid);
newvol=bill_add(&bill_DAU,msg,errjson); //comm_app.c,票卷号+1
if(newvol<0) {
DAU_free(&sell_DAU);
DAU_free(&bill_DAU);
return newvol;
}
//记存根,我只用这几个字段,其余80或150个与我无关吧?
sell.stat=0;
strcpy(sell.ticket_no,msg); //当前票号
sell.chksum=sell_chk_sum(&sell_DAU,msg); //comm_app.c,计算校验和
rsecstrfmt(sell.sell_time,ctx->contex.last_oper,YEAR_TO_SEC);
ret=sell_insert_dao(&sell_DAU,msg);
if(ret) {
json_object_array_add(errjson,jerr(120,msg));
DAU_free(&bill_DAU);
DAU_free(&sell_DAU);
return ret;
}
//组装返回数据
//返回下一个票号
json_object_array_add(errjson,jerr(newvol,dbill.bill_num));
json=json_object_new_object();
if(!json) {
sprintf(msg,"json MALLOC error");
ShowLog(1,"sell_app:%s",msg);
DAU_free(&bill_DAU);
DAU_free(&sell_DAU);
return MEMERR;
}
DAU_toJSON(&sell_DAU,json,0);
json_object_array_add(errjson,json);
DAU_free(&bill_DAU);
DAU_free(&sell_DAU);
return ret;
}
[ 本帖最后由 yulihua49 于 2011-9-14 10:41 编辑 ]
__________________
欢迎到我的blog:
http://blog.chinaunix.net/u3/92831/
只看该作者 引用 回复 报告 编辑
yulihua49
初级会员
精华贴数 1
个人空间 18
技术积分 1509 (1609)
社区积分 0 (1312844)
注册日期 2007-2-1
论坛徽章:3
#153
使用道具
发表于 2011-9-14 09:32
QUOTE:
--------------------------------------------------------------------------------
原帖由 newkid 于 2011-9-14 00:36 发表
num=_DAU.srm.tp[_DAU.srm.Aflg].offset; ------- 这个我说是天书有谁能反对?
--------------------------------------------------------------------------------
这个你抓得真准,不愧大侠。
要是C++,我可以来一个 recsize=table_DAU.getRecsize();
还是封得不严。写一个函数也行,不过不常用。
QUOTE:
--------------------------------------------------------------------------------
你既然有oad参数,数组长度应该不难得到,为什么还要设计第二个参数n?
--------------------------------------------------------------------------------
这个很有意思。你看那个零头,肯定n != BATCH_NUM。
这里说到DB2的批插入,它既不能定义起点,也不能定义终点,只能是数组的维,结果很难办。
正是ORACLE的优点,可以操作数组中的一部分。
QUOTE:
--------------------------------------------------------------------------------
(我又读了程序发现这个源头来自loadfile的参数buf,难道你是为了避免重复分配内存?那也应该有别的方法吧,何苦把程序接口弄得这么复杂?)
--------------------------------------------------------------------------------
前端分配了内存,在命令行可以-KkBYTEs,指定。因为不知道语句有多大。如果core dumpped,就可以再次申请大一些的。
QUOTE:
--------------------------------------------------------------------------------
这个有点搞,你循环里面都提交了,为什么做完反而不提交,而要留给后面的代码?
--------------------------------------------------------------------------------
循环里面10组(10000rows)提交一次。
begin和commit或rollback都是在svc层,另外,不够10组和零头没有commit,等出去做。
这个安排你可以看一下上边的售票记账程序,任何一步出错,都会rollback,记账失败。省得每个出错点都要rollback。C是没有try-catch的。
总之,你还是读懂了,很细。
我想稍微C了解点的,都能读个八九不离十。
QUOTE:
--------------------------------------------------------------------------------
对我来说SQL就是业务逻辑的一部分,“取得数据的方法”是重要的一环,这里没写好就会影响整个事务的性能。
就是用PLSQL写存储过程,也有人主张用你的方法,把数据存取分离出来,变成子过程,业务逻辑层不写SQL, 而是调用子过程。我也不是反对这种做法,假如分离出去的部分可以重用、可以改善可读性,也未尝不可。注意前面的两个前提。
--------------------------------------------------------------------------------
这就对了。在模块间传数据,要传结构。模板就是映射结构的,这样模块间方便些。也好读。
QUOTE:
--------------------------------------------------------------------------------
Here's the implementation of the C external procedure (refcurdesc.c):
.......
他说这个C外部过程用OCI解析REF CURSOR, 你看看是不是。
--------------------------------------------------------------------------------
是。这部分代码在ORA_Rpc()l里,也是一个包装。不然即使调用存储过程,用OCI也是很麻烦的。
|
|