楼主: yulihua49

NEWKID:oci确实比存储过程快。

[复制链接]
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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#
发表于 2012-11-13 23:04 | 只看该作者
你又拿文件装载、卸载来说事。UTL_FILE操作文件的效率当然比不上C。PLSQL的长处是和SQL的无缝结合,它使用SQL天生比别的语言更方便,所以是最好的事务处理语言。
只要是SQL能做到的,比如卸载成DATAPUMP格式而非CSV格式,你来和PLSQL比比看?

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期: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
12#
发表于 2012-11-13 23:05 | 只看该作者
xgghxkhuang 发表于 2012-11-13 21:04
外部表可以卸载吗?

可以,目前只支持DATAPUMP格式。我曾经在ASKTOM问他为什么不支持CSV格式,TOM的回答是可以向ORACLE提出一个需求。我当时也没有METALINK账号所以不了了之。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
13#
发表于 2012-11-14 00:47 | 只看该作者
如果Oracle提供了汇编接口,没准还能更快

使用道具 举报

回复
论坛徽章:
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#
 楼主| 发表于 2012-11-14 10:52 | 只看该作者
本帖最后由 yulihua49 于 2012-11-14 10:53 编辑
sweetwow 发表于 2012-11-13 18:17
同问
为何不用sql loader


需要sqlunloder
能unloder  .csv格式吗?这个我还不知道。
另外,在loader中有时也需要特殊操作,这是就需要自己写loader了。

使用道具 举报

回复
论坛徽章:
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
15#
 楼主| 发表于 2012-11-14 10:59 | 只看该作者
本帖最后由 yulihua49 于 2012-11-14 11:05 编辑
newkid 发表于 2012-11-13 23:04
你又拿文件装载、卸载来说事。UTL_FILE操作文件的效率当然比不上C。PLSQL的长处是和SQL的无缝结合,它使用S ...


好,那我们握手言和了。
在动态解析数据时,可能其他工具开销都比较大。
oci可以高效解决数据动态解析问题,但是极其繁琐。
我这个包装器完美的解决了这个问题。

同事也做了个PRO*C的程序,比存储过程还多用了1分钟。
就是说,差别不是读写文件造成的,还是内部处理机制的差别造成的。

读写文件因为比较简单,所以常拿他做例子,做PK。
其他逻辑太复杂了,没办法玩。

使用道具 举报

回复
论坛徽章:
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#
 楼主| 发表于 2012-11-14 11:09 | 只看该作者
yulihua49 发表于 2012-11-14 10:59
好,那我们握手言和了。
在动态解析数据时,可能其他工具开销都比较大。
oci可以高效解决数据动态解析 ...

这个PRO*C,也看看吧:

复制代码
  1. //参数: 发生错误的函数名
  2. // 错误的信息
  3. //返回值:proc*c 的结果
  4. void SqlError(char* func, char* msg)
  5. {
  6. /* This function handles the SQL Errors and displays them */
  7. char err_msg[128]="";
  8. size_t buf_len=0, msg_len=0;

  9. EXEC SQL WHENEVER SQLERROR CONTINUE;

  10. LogMsg(MSG_INFO, "Error %s in %s", msg, func);
  11. buf_len = sizeof(err_msg);
  12. sqlglm(err_msg, &buf_len, &msg_len);
  13. LogMsg(MSG_INFO, "%.*s", msg_len, err_msg);
  14. OracleDisconnect();
  15. exit(EXIT_FAILURE);
  16. }



  17. //连接oracle数据库
  18. //参数: 连接的字符串,格式 user\passwd@db
  19. //返回值:proc*c 的结果
  20. int OracleConnect(const char* str)
  21. {
  22. EXEC SQL BEGIN DECLARE SECTION;
  23. /*变量声明*/
  24. char con_str[256]="";
  25. EXEC SQL END DECLARE SECTION;

  26. strcpy(con_str, str);
  27. LogMsg(MSG_INFO, "Connecting to Oracle as %s", str);

  28. /* This function connects to the Oracle Database */
  29. exec sql whenever sqlerror do SqlError("oracle_connect","connecting");
  30. exec sql connect :con_str;
  31. LogMsg(MSG_INFO, "Connected. sqlca.sqlcode=%d", sqlca.sqlcode);

  32. #ifdef DEBUG
  33. EXEC SQL ALTER SESSION SET sql_trace=true;
  34. LogMsg(MSG_INFO, "Debug: Enabled SQL Trace for this session.");
  35. #endif

  36. return (sqlca.sqlcode);
  37. }

  38. //断开oracle的连接
  39. //返回值: proc*c 的结果
  40. int OracleDisconnect()
  41. {
  42. LogMsg(MSG_INFO, "Disconnecting from Oracle");

  43. /* This function disconnects from the Oracle Database */
  44. exec sql whenever sqlerror continue;
  45. exec sql commit work release;
  46. LogMsg(MSG_INFO, "Disconnected");
  47. return (sqlca.sqlcode);
  48. }

  49. //按空格左截字符串,
  50. //参数: 要处理的字符串
  51. //返回值: 处理后的字符串
  52. char* LTrim(char* InStr,int *StrLength)
  53. {
  54. int i;
  55. for (i = 0; InStr[i] == ' '; i++);
  56. *StrLength-=i;
  57. return (InStr + i);
  58. }


  59. //按空格右截字符串,
  60. //参数: 要处理的字符串
  61. //返回值: 处理后的字符串
  62. //char* RTrim(char* InStr)
  63. //{
  64. // int i;
  65. // for (i = strlen(InStr) - 1; InStr[i] == ' ' && i >= 0; i--)
  66. // InStr[i] = '\0';
  67. // return (InStr);
  68. //}

  69. char* RTrim(char* InStr,int *StrLength)
  70. {
  71. int i;
  72. for (i =*StrLength - 1; InStr[i] == ' ' && i >= 0; i--)
  73. InStr[i] = '\0';
  74. *StrLength = i+1;
  75. return (InStr);
  76. }

  77. //把oracle的数据导出成csv
  78. //参数: sql查询
  79. // 导出csv的文件名
  80. int Sql2CSV(const char* Query,const char *Path, const char* Filename, const int BatchCount)
  81. {

  82. /* 定义宿主变量 */
  83. exec sql begin declare section;
  84. char sql_query[4000];
  85. int output_count;
  86. int output_type;
  87. int output_len;
  88. char output_buffer[4000];
  89. short output_indicator;
  90. char name[31];
  91. int occurs;
  92. exec sql end declare section;


  93. int i = 0;
  94. int j = 1;
  95. int line_pos = 0;
  96. char* p = NULL;
  97. char temp_info[64] = "";
  98. char cur_date[64]="";
  99. char* line = malloc(10 * 1024 * BatchCount);
  100. char temp_filename[256] = "";
  101. FILE* out;

  102. GetCurDate(cur_date,-SECEND_PER_DAY);
  103. sprintf(temp_filename,"%s%s_%s.tmp",Path,cur_date,Filename);

  104. if ((out = fopen(temp_filename, "w")) == NULL)
  105. {
  106. LogMsg(MSG_ERROR, "open %s file failed ", temp_filename);
  107. return -1;
  108. }

  109. memset(sql_query, 0, sizeof(sql_query));
  110. strcpy(sql_query, Query);

  111. exec sql whenever sqlerror do SqlError("sql_to_csv()","NLS_DATE_FORMAT");
  112. EXEC SQL ALTER SESSION SET NLS_DATE_FORMAT = 'YYYYMMDDHH24:MI:SS';

  113. exec sql whenever sqlerror do SqlError("sql_to_csv()","prepare s");
  114. exec sql prepare s from :sql_query; /* prepare SQL statement for execution. */
  115. /* s should not be declared as a variable */

  116. exec sql whenever sqlerror do SqlError("sql_to_csv()","declare c");
  117. exec sql declare c cursor for s; /* Declare cursor C1 for retrieving the */
  118. /* results of prepared statement s */


  119. exec sql whenever sqlerror do SqlError("sql_to_csv()","allocate descriptor");
  120. exec sql allocate descriptor 'output_descriptor' with max 256 ; /* Allocate a descriptor to identify the */
  121. /* attributes of the output generated by */
  122. /* executing the prepared statement s */


  123. /* 选择列表项->输出描述区 */
  124. exec sql whenever sqlerror do SqlError("sql_to_csv()","describe output s");
  125. exec sql describe output s using descriptor 'output_descriptor';

  126. /* 取得选择列表项个数 */
  127. exec sql whenever sqlerror do SqlError("sql_to_csv()","get descriptor count ");
  128. exec sql get descriptor 'output_descriptor' :output_count = count;

  129. LogMsg(MSG_INFO, "column count:%d", output_count);

  130. Query_Column* pColumns = (Query_Column*) malloc(sizeof(Query_Column) * output_count);
  131. if (NULL==pColumns)
  132. return -2;

  133. /* 循环处理选择列表项 */
  134. for (i = 0 ; i != output_count ; ++i)
  135. {
  136. occurs = i + 1;

  137. /* 取得选择列表项的名称并输出 */
  138. exec sql whenever sqlerror do SqlError("sql_to_csv()","get descriptor TYPE LENGTH name");
  139. exec sql get descriptor 'output_descriptor' value :occurs :output_type = TYPE, :output_len = LENGTH, :name = name;


  140. pColumns[i].type = output_type;
  141. pColumns[i].length = output_len;
  142. strcpy(pColumns[i].name, name);

  143. switch (pColumns[i].type)
  144. {
  145. case ANSI_CHARACTER_CODE:
  146. pColumns[i].length++;
  147. break;
  148. case DATE_CHARACTER_CODE:
  149. pColumns[i].length = 16;
  150. break;
  151. case NUMBER_CHARACTER_CODE:
  152. case FLOAT_CHARACTER_CODE:
  153. case VARNUM_CHARACTER_CODE:
  154. case DECIMALCHARACTER_CODE:
  155. pColumns[i].length = 0 != output_len ? output_len + 1 : DEFAULT_COL_LENGTH;
  156. break;
  157. default:
  158. pColumns[i].length = 0 != output_len ? output_len : DEFAULT_COL_LENGTH;
  159. break;
  160. }



  161. /* 设置选择列表项的类型和长度 */
  162. output_type = ANSI_CHARACTER_CODE;
  163. output_len = pColumns[i].length;
  164. exec sql whenever sqlerror do SqlError("sql_to_csv()","set descriptor TYPE LENGTH ");
  165. exec sql set descriptor 'output_descriptor' value :occurs
  166. type = :output_type , length = :output_len;

  167. }



  168. /* 循环处理选择列表项数据 */
  169. exec sql whenever sqlerror do SqlError("sql_to_csv()","open c");
  170. exec sql open c;

  171. line_pos = 0;
  172. memset(line, 0, sizeof(line));

  173. /* 提取数据完毕->退出循环 */
  174. exec sql whenever not found do break;
  175. strcpy(temp_info,"fetch c ");
  176. //exec sql whenever sqlerror do SqlError("sql_to_csv()","fetch c ");
  177. for (j = 1; ; j++)
  178. {

  179. itoa_n(j,temp_info+8);
  180. exec sql whenever sqlerror do SqlError("sql_to_csv()",temp_info);
  181. /* 行数据->输出描述区 */
  182. exec sql fetch c into descriptor 'output_descriptor';


  183. /* 循环处理每列数据 */

  184. for (i = 0 ; i < output_count ; ++i)
  185. {
  186. if (0 != i)
  187. {
  188. line[line_pos++] = ',';
  189. }

  190. occurs = i + 1;

  191. /* 取得列数据和指示变量值 */
  192. exec sql whenever sqlerror do SqlError("sql_to_csv()","get descriptor value");
  193. exec sql get descriptor 'output_descriptor'
  194. value :occurs :output_buffer = data , :output_indicator = indicator;


  195. output_buffer[pColumns[i].length ] = '\0';
  196. /* 输出列数据 */
  197. if (output_indicator != -1)
  198. {
  199. output_len = pColumns[i].length;
  200. p = LTrim(RTrim(output_buffer,&output_len),&output_len);

  201. if ((ANSI_CHARACTER_CODE == pColumns[i].type || CHAR_CHARACTER_CODE == pColumns[i].type ) && strchr(p, ',') != NULL)
  202. {
  203. line[line_pos++] = '"';

  204. strcpy(line + line_pos, p);
  205. line_pos += output_len;
  206. line[line_pos++] = '"';
  207. }
  208. else
  209. {
  210. strcpy(line + line_pos, p);
  211. line_pos += output_len;
  212. }

  213. }

  214. }
  215. line[line_pos++] = '\n';
  216. if (0 == j % BatchCount)
  217. {
  218. fwrite(line, 1, line_pos, out);
  219. fflush(out);
  220. LogMsg(MSG_INFO, "export csv count:%10d", j);
  221. memset(line, 0, sizeof(line));
  222. line_pos = 0;
  223. }

  224. }
  225. j--;
  226. if (0 != j % BatchCount)
  227. {
  228. fwrite(line, 1, line_pos, out);
  229. LogMsg(MSG_INFO, "export csv count:%10d", j);
  230. }
  231. fclose(out);
  232. free(pColumns);
  233. free(line);
  234. exec sql close c;
  235. exec sql deallocate descriptor 'output_descriptor';


  236. char new_filename[256]="";
  237. sprintf(new_filename, "%s%s_%s_%d.csv",Path,cur_date,Filename,j);

  238. if (0==j){
  239. LogMsg(MSG_INFO,"export count is 0 ,delete temp file.");
  240. unlink(temp_filename);

  241. }else{
  242. unlink(new_filename);
  243. rename(temp_filename, new_filename);
  244. }
  245. return 0;

  246. }


  247. //从ini文件中读取匹配的内容
  248. //参数: ini文件名
  249. // 匹配上的内容
  250. // 匹配关键字
  251. /*-- GetIniParm -----------------------------------------------------------------------*/
  252. void GetIniParm(const char* ini_name, char* DestStr, const char* ParName)
  253. {
  254. char buf[1024];
  255. short found = 0;

  256. #ifdef DEBUG
  257. LogMsg(MSG_INFO, "Debug: GetIniParm(%s)", ParName);
  258. #endif

  259. char file_name[256]="";
  260. ConvertAbsolutePath(ini_name,file_name);

  261. FILE* F_ini;
  262. if ((F_ini = fopen( file_name, "r")) == NULL)
  263. {
  264. LogMsg(MSG_ERROR, "Error: Unable to open ini file <%s> for reading.", file_name);
  265. }

  266. memset(buf, 0, sizeof(buf));
  267. while (fgets(buf, 1023, F_ini) != NULL)
  268. {
  269. /* Get rid of the NEWLINE char */
  270. buf[strlen(buf)-1] = '\0';
  271. if ('#' == buf[0])
  272. continue;
  273. if (strstr(buf, ParName) != NULL)
  274. {
  275. found = 1;
  276. strcpy(DestStr, buf + strlen(ParName) + 1);
  277. LogMsg(MSG_INFO, "%s=%s", ParName, DestStr);

  278. break;
  279. }
  280. }

  281. if (!found)
  282. {
  283. LogMsg(MSG_ERROR, "Error: No parameter by the name of <%s> in <%s>", ParName, ini_name);
  284. }

  285. if (F_ini)
  286. {
  287. fclose(F_ini);
  288. }
  289. }


  290. //从命令行读取参数
  291. //参数: 参数数量
  292. // 参数内容
  293. // 参数存放的变量

  294. /*-- process_parms --------------------------------------------------------------------*/
  295. void ProcessInputParms(const int argc, char* argv[], Input_Parm* parm)
  296. {
  297. int i = 0;
  298. char temp_count[32] = "";

  299. for (i = 1; i < argc; i++)
  300. {
  301. if (strncmp(argv[i], "-i", 2) == 0)
  302. {
  303. strcpy(parm->ini_name, argv[++i]);
  304. }
  305. else if (strncmp(argv[i], "-v", 2) == 0)
  306. {
  307. printf("unload - Version %s\n", VERSION);
  308. exit(0);
  309. }
  310. else if (strncmp(argv[i], "-d", 2) == 0)
  311. {
  312. memset(temp_count, 0, sizeof(temp_count));
  313. strcpy(temp_count, argv[++i]);
  314. parm->is_debug = atoi(temp_count);
  315. }
  316. else if (strncmp(argv[i], "-b", 2) == 0)
  317. {
  318. memset(temp_count, 0, sizeof(temp_count));
  319. strcpy(temp_count, argv[++i]);
  320. parm->batch_count = atoi(temp_count);
  321. }
  322. else
  323. {
  324. Usage();
  325. exit(1);
  326. }

  327. }

  328. if ((strlen(parm->ini_name) == 0))
  329. {
  330. Usage();
  331. exit(1);
  332. }
  333. }

  334. //从ini文件中读取配置参数
  335. //参数: ini文件名称
  336. // 参数存放的变量
  337. void ProcessIniParms(const char* ini, Ini_Param* parms)
  338. {
  339. char dir_name[256]="";
  340. GetIniParm(ini, parms->shell_prg, "ShellPrg");
  341. strcpy(parms->shell_prg,ConvertAbsolutePath(parms->shell_prg,dir_name));

  342. // GetIniParm(ini, parms->log_dir, "LogDir");
  343. // ExtendDir(parms->log_dir);
  344. // if (! DirectoryExists(parms->log_dir))
  345. // CreateDir(parms->log_dir);


  346. GetIniParm(ini, parms->arc_dir, "ArcDir");
  347. ExtendDir(parms->arc_dir);

  348. strcpy (parms->arc_dir, ConvertAbsolutePath(parms->arc_dir,dir_name));
  349. if (! DirectoryExists(parms->arc_dir))
  350. CreateDir(parms->arc_dir);

  351. GetIniParm(ini, parms->db_conn_str, "DBConnStr");
  352. char count[32] = "";
  353. GetIniParm(ini, count, "ArcCount");
  354. parms->arc_count = atoi(count);
  355. parms->arc_para = malloc(sizeof(ArcPara) * parms->arc_count);
  356. if (NULL == parms->arc_para)
  357. exit(-1);
  358. char parm_name[32] = "";
  359. int i = 0;
  360. for (i = 0 ; i < parms->arc_count; i++)
  361. {
  362. sprintf(parm_name, "ArcSql%d", i + 1);
  363. GetIniParm(ini, parms->arc_para[i].arc_sql, parm_name);
  364. sprintf(parm_name, "ArcFile%d", i + 1);
  365. GetIniParm(ini, parms->arc_para[i].arc_file, parm_name);
  366. }
  367. }



  368. int main(int argc, char** argv)
  369. {
  370. ExtractFilePath(argv[0],app_dir);
  371. //printf("app_dir :%s\n",app_dir);

  372. EXEC SQL WHENEVER SQLERROR DO SqlError("main()","");

  373. int i = 0;
  374. char arc_filename[256] = "";

  375. Input_Parm input_parm;
  376. Ini_Param ini_parms;

  377. memset(&input_parm, 0, sizeof(input_parm));
  378. strcpy(input_parm.ini_name, "paraconfig.ini");
  379. input_parm.is_debug = 0;
  380. input_parm.batch_count = 500;

  381. memset(&ini_parms, 0, sizeof(ini_parms));

  382. ProcessInputParms(argc, argv, &input_parm);
  383. ProcessIniParms(input_parm.ini_name, &ini_parms);


  384. OracleConnect(ini_parms.db_conn_str);
  385. for (i = 0; i < ini_parms.arc_count; i++)
  386. {


  387. LogMsg(MSG_INFO, "begin run sql2csv sql : %s ", ini_parms.arc_para[i].arc_sql);
  388. LogMsg(MSG_INFO, "end run sql2csv result: %d ",
  389. Sql2CSV(ini_parms.arc_para[i].arc_sql,ini_parms.arc_dir, ini_parms.arc_para[i].arc_file, input_parm.batch_count));

  390. }
  391. OracleDisconnect();

  392. if (FileExists(ini_parms.shell_prg))
  393. RunShell(ini_parms.shell_prg);
  394. free(ini_parms.arc_para);
  395. exit(0);
  396. }

复制代码

使用道具 举报

回复
论坛徽章:
3
ITPUB 11周年纪念徽章
日期:2012-10-09 18:09:19ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:312013年新春福章
日期:2013-02-25 14:51:24
17#
发表于 2012-11-14 11:09 | 只看该作者
20年前,很牛的同事用OCI完成foxpro 和 oracle的通讯接口,foxpro直接编程oracle....

使用道具 举报

回复
论坛徽章:
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
18#
 楼主| 发表于 2012-11-14 11:16 | 只看该作者
本帖最后由 yulihua49 于 2012-11-14 11:18 编辑
lastwinner 发表于 2012-11-14 00:47
如果Oracle提供了汇编接口,没准还能更快


实际上,oci与汇编接口没什么区别,
如果你写汇编程序,完全可以调用OCI函数进行数据库操作。
如上所说,不是什么语言的问题,而是内部处理机制的问题。

使用道具 举报

回复
论坛徽章:
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#
 楼主| 发表于 2012-11-14 11:26 | 只看该作者
babujie2001 发表于 2012-11-14 11:09
20年前,很牛的同事用OCI完成foxpro 和 oracle的通讯接口,foxpro直接编程oracle....

OCI虽然高效,但使用过于复杂。
你那位同事,自己是高手,但没有传他人。
我们现在包装了,而且开源,使用它,人人都是高手。

使用道具 举报

回复
论坛徽章:
3
ITPUB 11周年纪念徽章
日期:2012-10-09 18:09:19ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:312013年新春福章
日期:2013-02-25 14:51:24
20#
发表于 2012-11-14 11:54 | 只看该作者
yulihua49 发表于 2012-11-14 11:26
OCI虽然高效,但使用过于复杂。
你那位同事,自己是高手,但没有传他人。
我们现在包装了,而且开源,使 ...

只是感慨一下,20年。。。现在回头向你们学习来了。。。。

使用道具 举报

回复

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

本版积分规则 发表回复

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