<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 11,  comments - 14,  trackbacks - 0
    關于使用PRO*C編程的一些簡單說明和例子

      PROC是ORACLE數據庫提供的編程接口之一,其應用十分的廣泛,本文通過一個具體的例子,介紹PROC編程的一些經驗及應注意的地方。
      
      例子程序:
      <code>
      #include <stdio.h>
      #include <string.h>
      #include <stdlib.h>
      #include <sqlda.h>
      #include <sqlcpr.h>
      
      EXEC SQL INCLUDE sqlca;
      /*RELEASE_CURSOR=YES 使PROC 在執行完后釋放與嵌入SQL有關資源*/
      EXEC ORACLE OPTION (RELEASE_CURSOR = YES);
      
      EXEC SQL BEGIN DECLARE SECTION;
      varchar vc_user[20];
      long al_empno=0;
      char ac_ename[11]="";
      char ac_hiredate[20]="";
      double af_sal=0;
      
      EXEC SQL VAR ac_ename IS STRING(11);
      EXEC SQL VAR ac_hiredate IS STRING(20);
      
      EXEC SQL END DECLARE SECTION;
      
      /*錯誤處理函數*/
      void sql_error(char *msg)
      {
      printf("\n%s,%ld,%s\n", msg,sqlca.sqlcode,(char *)sqlca.sqlerrm.sqlerrmc);
      EXEC SQL ROLLBACK RELEASE;
      exit(-1);
      }
      
      main()
      {
      EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE ERROR: ");
      
      /*連接數據庫*/
      strcpy(vc_user.arr,"scott/tiger@DEMO");
      vc_user.len=16;
      exec sql connect :vc_user;
      
      EXEC SQL DECLARE cur_emp CURSOR FOR
      SELECT EMPNO, ENAME,to_char(HIREDATE,'yyyy/mm/dd hh24:mi:ss'),SAL FROM EMP;
      
      EXEC SQL OPEN cur_emp;
      while(1)
      {
      al_empno=0;
      strcpy(ac_ename,"");
      strcpy(ac_hiredate,"");
      af_sal=0;
      EXEC SQL FETCH cur_emp INTO :al_empno, :ac_ename:ename_ind, :ac_hiredate:hiredate_ind, :af_sal:sal_ind;
      if( sqlca.sqlcode == 1403)
      {
      break;
      }
      printf("empno=%ld,ename=%s,hiredate=%s,sal=%lf\n",al_empno,ac_ename,ac_hiredate,af_sal);
      }
      EXEC SQL CLOSE cur_emp;
      EXEC SQL ROLLBACK WORK RELEASE;
      }
      </code>
      
      1、宿主變量的聲明
      
      在PROC中,在SQL語句中用到的變量稱為宿主變量。他們應在EXEC SQL BEGIN DECLARE SECTION;與EXEC SQL EDN DECLARE SECTION;
      
      之間聲明,如上面所示.在聲明宿主變量時應注意以下幾點:
      
      (1) 在數據庫表中定義為VARCHAR2,VARCHAR,CHAR的字段,在PROC中可聲明為CHAR,但長度應為它們在表中定義的長度加1,因為PROC中
      
      CHAR型變量用做結尾。
      
      如:ENAME在表中的定義為ename varchar2(10),在PROC中可定義為:
      EXEC SQL BEGIN DECLARE SECTION;
      char ename[11];
      EXEC SQL END DECLARE SECTION;
      
      常見錯誤說明:
      
      如果插入的字符串長度大于10,如:EXEC SQL INSERT INTO EMP(ENAME) VALUES('12345678901');會出現以下錯誤:
      error:ORA-01480: STR 賦值變量缺少空后綴。
      
      如果定義為:
      EXEC SQL BEGIN DECLARE SECTION;
      char ename[15];
      EXEC SQL END DECLARE SECTION;
      
      當插入的字符串長度大于10,小于15時,如:EXEC SQL INSERT INTO EMP(ENAME) VALUES('12345678901');會出現以下錯誤:
      error:ORA-01401: 插入的值對于列過大。
      
      當插入的字符串長度大于15,如:EXEC SQL INSERT INTO EMP(ENAME) VALUES('12345678901234');會出現以下錯誤:
      error:ORA-01401:STR 賦值變量缺少空后綴。
      
      (2) 從SQL語句中取字段的值到宿主變量中時,PROC不會自動給宿主變量去掉右空格。而是以在DECLARE SECTION 中定義的長度為準(與 表中定義的無關)不足補右空格.如果不注意這一點,在PROC中進行字符串操作時(如比較相等)會出錯。如:
      EXEC SQL BEGIN DECLARE SECTION;
      char ename[10];
      EXEC SQL END DECLARE SECTION;
      如果ENAME在表中的值為'abc',則取出的值為'abc ';
      
      可用語句EXEC SQL VAR重定義CHAR型變量。這樣宿主變量會自動去掉右空格。如下:
      EXEC SQL BEGIN DECLARE SECTION;
      char ename[11];
      EXEC SQL VAR ac_ename IS STRING(11);
      EXEC SQL END DECLARE SECTION;
      如果ENAME在表中的值為'abc',則取出的值為'abc';
      
      (3) 對浮點型的變量,為保證精度,最好是聲明成DOUBLE型的.因為DOUBLE型的精度比FLOAT型高很多.
      
      (4) 整型可聲明為LONG型(對較長的整型,而且所用的平臺支持的話,如在SUN平臺上,可聲明為LONG LONG型).
      
      (5) DATE型的處理:DATE型一般聲明為CHAR(20)。
      
      往表中插入DATE型數據時,一般用TO_DATE()函數進行類型轉換,取出值時一般用TO_CHAR()函數進行類型轉換.
      EXEC SQL select to_char(hiredate,'yyyy/mm/dd hh24:mi:ss') into :ac_hire_date from EMP where empno=1234;
      EXEC SQL insert into EMP(EMPNO,HIREDATE) values(123,to_date(:ac_hiredate,'yyyy/mm/dd hh24:mi:ss');
      
      2、宿主變量的作用范圍
      
      如果宿主變量在所有的函數之外聲明,則他們是全局變量。在使用之前要注意把變量的值初始化,宿主變量也可以在某個函數的內部定義。 這時他們是局部變量。一般都習慣把宿主變量聲明為全局變量。
      
      3、數據庫的連接與斷開
      
      數據庫的連接有以下兩種方法:
      (1)
      strcpy(vc_user.arr,"scott/tiger");
      vc_user.len=11;
      exec sql connect :vc_user;
      
      (2)
      strcpy(user,"scott");
      strcpy(pass,"tiger");
      exec sql connect :user identified by :pass;
      
      注意:在有些平臺上兩種都可以,在有些平臺上只能用第一種方法.
      
      在PROC程序中,要記住用EXEC SQL ROLLBACK WORK RELEASE;斷開與數據庫的連接,并釋放相關的數據庫資源。
      
      4、PROC中的NULL值的處理
      
      如果某一字段取出的值是NULL,會報:sqlcode=-1405, sqlerr=ORA-01405: 讀取的列值為 NULL
      
      并且相應的宿主變量的值不會被改變,為執行該SQL語句之前的值. 常用的處理NULL值的方法有:
      
      (1)采用指示器變量,此時不會有-1405錯誤,當必須是所以為NULL的字段都有相應的指示器變量,如果某一字段沒有指示器變量,但取出的值
      
      為NULL值,則仍然會有-1405錯誤.當取出的值是NULL時,相應的指示器變量變量為-1,可根據指示器變量的值做響應的處理。
      
      (2)如果字段較多,可取字段到一個結構體中及與該結構體對應的指示器結構體中.如上面的例子中可定義結構體:
      struct str_emp{
      long al_empno;
      char ac_ename;
      char ac_hiredate;
      double af_sal;
      };
      struct str_emp_ind{
      long al_empno;
      char ac_ename;
      char ac_hiredate;
      double af_sal;
      };
      
      struct str_emp str_emp;
      strcut str_emp_ind str_emp_ind;
      
      在取之前可用memset(&str_emp,0,sizeof(str_emp)).清空該結構體,這樣如果是字符型的NULL,會為"",整型的NULL會為0,
      
      浮點型的會為0.00。此時不會有-1405錯誤。
      
      (3)也可采用NVL()函數:舉例如下:
      EXEC SQL DECLARE authors CURSOR FOR
      SELECT EMPNO, NVL(ENAME,chr(0)),nvl(to_char(HIREDATE,'yyyy/mm/dd hh24:mi:ss'),chr(0)),NVL(SAL,0) FROM EMP;
      
      這樣也不會有-1405錯誤不,當取出的值是NULL時,自動用NVL()中指定的值代替.
      
      CHR(0)也可直接用''代替,如下:
      SELECT EMPNO, NVL(ENAME,''),nvl(to_char(HIREDATE,'yyyy/mm/dd hh24:mi:ss'),''),NVL(SAL,0) FROM EMP;
      
      5、PROC中的錯誤的處理
      
      所有的SQL語句都有可能出錯.所以都要加以判斷,但每個SQL語句后都加錯誤判斷,太麻煩,可用一個函數如sql_error()來進行錯誤處理,
      
      方法:
      
      (1)定義ql_error()函數。
      
      (2)在開頭加上EXEC SQL WHENEVER SQLERROR DO sql_error();這樣當發生sqlca.sqlcode <0 的錯誤時,程序自動轉到sql_error()中執行. 注意:對sqlca.sqlcode >0的錯誤如 sqlca.sqlcode =1403 是不會轉到sql_error()中執行的.
      
      另外:在UNIX下,可以用OERR 來查找錯誤的描述。如: ora ORA -1405 查找錯誤號為-1405的描述.
      
      6、PROC中調用存儲過程的方法
      
      要把存儲過程放在EXEC SQL EXECUTE 和 END-EXEC;之間,如下所示:
      
      其中:al_empno,ac_ename 為輸入參數,l_return,l_errno,c_errtext 為輸出參數。
      al_empno=8888;
      strcpy(ac_ename,"ABCD");
      EXEC SQL EXECUTE
      BEGIN
      up_db_emp(:al_empno,:ac_ename,:l_return,:l_errno,:c_errtext);
      END;
      END-EXEC;
      if (l_return != 0)
      {
      printf("調用UP_PB_EMP存儲過程出錯,errno=%ld,errtext=%s\n",l_errno,c_errtext);
      }
      
      7、PROC的命令行選項:PROC編譯器有很多的命令行選項,在命令行下直接不帶參數運行PROC,會列出所有的命令行選項來,并有說明。
      

      (1)儲存過程:編譯儲存過程是要帶上用戶名及密碼
      proc USERID=scott/tiger sqlcheck=SEMANTICS ireclen=512 iname=test.cpp
      
      (2)PARSE=NONE 對非SQL代碼不進行語法分析,默認對非SQL代碼也進行語法分析.
      
      在RED HAD6.3上的ORACLE8.1.5中用PROC時,會提示:/USR/INCLUDE/STDIO.H 及其他的.H文件中有錯. 可把PARSE=NONE加上,就好了.
      
      8、注意加上:EXEC ORACLE OPTION (RELEASE_CURSOR = YES);
      

      RELEASE_CURSOR=YES 使PROC 在執行完后釋放與嵌入SQL有關資源,保證在該PROC程序執行完后,ORACLE不會鎖住數據庫資源,如鎖表等。
      
      如果在PROC中用到ORACA,還要在程序頭加上:
      EXEC ORACLE OPTION (ORACA=YES);
      
      9、PROC中的類型轉換
      
      一、在C語言中:

      
      (1)字符型到整型可用ATOI() ATOL(),SSCANF()
      
      (2)整型,浮點型到字符型,可用SPRINTF()
      
      (3)字符型到浮點型用ATOF()不行,最好用SSCANF(),舉例如下:
      
      EXEC SQL BEGIN DECLARE SECTION;
      double d_demo;
      float f_demo;
      char ac_text[20]="222";
      EXEC SQL END DECLARE SECTION;
      
      (1)sscanf(ac_text, "%f", &d_demo);
      printf("ac_text=%s,d_demo=%f\n",ac_text,d_demo);
      
      (2)sscanf(ac_text, "%lf", &d_demo);
      printf("ac_text=%s,d_demo=%f\n",ac_text,d_demo);
      
      (3)sscanf(ac_text, "%f", &d_demo);
      printf("ac_text=%s,d_demo=%lf\n",ac_text,d_demo);
      
      (4)sscanf(ac_text, "%lf", &d_demo);
      printf("ac_text=%s,d_demo=%lf\n",ac_text,d_demo);
      
      printf("*******************\n");
      
      (5)sscanf(ac_text, "%f", &f_demo);
      printf("ac_text=%s,f_demo=%f\n",ac_text,f_demo);
      
      (6)sscanf(ac_text, "%lf", &f_demo);
      printf("ac_text=%s,f_demo=%f\n",ac_text,f_demo);
      
      (7)sscanf(ac_text, "%f", &f_demo);
      printf("ac_text=%s,f_demo=%lf\n",ac_text,f_demo);
      
      (sscanf(ac_text, "%lf", &f_demo);
      printf("ac_text=%s,f_demo=%lf\n",ac_text,f_demo);
      
      輸出的結果:
      ac_text=222.00,d_demo=0.000000
      ac_text=222.00,d_demo=222.000000
      ac_text=222.00,d_demo=222.000032
      ac_text=222.00,d_demo=222.000000
      *******************
      ac_text=222.00,f_demo=222.000000
      ac_text=222.00,f_demo=0.000000
      ac_text=222.00,f_demo=222.000000
      ac_text=222.00,f_demo=0.000000
      d_demo=atof(ac_text);
      printf("ac_text=%s,atof(ac_text)=%f\n",ac_text,d_demo);
      
      d_demo=atof(ac_text);
      printf("ac_text=%s,atof(ac_text)=%lf\n",ac_text,d_demo);
      
      f_demo=atof(ac_text);
      printf("ac_text=%s,atof(ac_text)=%f\n",ac_text,f_demo);
      
      f_demo=atof(ac_text);
      printf("ac_text=%s,atof(ac_text)=%lf\n",ac_text,f_demo);
      
      輸出的結果:
      ac_text=222.00,atof(ac_text)=1243288.000000
      ac_text=222.00,atof(ac_text)=1243288.000000
      ac_text=222.00,atof(ac_text)=1243288.000000
      ac_text=222.00,atof(ac_text)=1243288.000000
      
      從上面的結果可見:
      
      DOUBLE型應采用sscanf(ac_app_capcity, "%lf", &d_app); 打印用"%lf","%f" 都可以. (2),(4)正確
      
      FLOAT型應采用sscanf(ac_app_capcity, "%f", &d_app); 打印用"%lf","%f" 都可以. (5),(7)正確
      
      采用ATOF()轉換的結果都是錯的,所以不要用它。
      
      二、寫表或從表中取數據時:
      
      (1)字符型與整型之間可不用轉換,采用默認方式。
      
      (2)字符型與浮點型之間可不用轉換,采用默認方式。
      
      (3)日期型與字符型之間可用TO_CHAR(),TO_DATE()。
      
      10、PROC中的4種動態SQL簡介
      
      (1)動態SQL1: 不能是查詢(SELECT)語句,并且沒有宿主變量.
      
      用法:拼一串動態SQL語句,并用EXECUTE IMMEDIATE執行,如:
      EXEC SQL EXECUTE IMMEDIATE "CREATE TABLE dyn1 (col1 VARCHAR2(4))";
      
      (2)動態SQL2: 不能是查詢(SELECT)語句,并且輸入的宿主變量數目是知道的,
      
      用法:拼一串動態SQL語句,用PREPARE,EXECUTE語句執行.
      strcpy(c_sql, "DELETE FROM EMP WHERE EMPNO = ");
      EXEC SQL PREPARE sql_stmt FROM :c_sql;
      EXEC SQL EXECUTE sql_stmt USING :emp_number;
      
      (3)動態SQL3: 用于創建動態查詢, 并且要查詢的字段及輸入的宿主變量數目是知道的
      
      用法: 拼一串動態SQL語句,用PREPARE分析該語句,并要定義一個CURSOR進行取值
      
      如:如要查詢的數據按一年12月放到12張表中。表名為user_fee_1mon, user_fee_2mon,....可采用動態SQL3來進行查詢
      strcpy(c_sql,"select c_user_id,c_user_name,to_char(t_date,'yyyy/mm/dd hh:mi:ss'),n_fee\n");
      strcat(c_sql,"from USER_FEE_");
      strcat(c_sql,ac_mon);
      strcat(c_sql," \n where c_user_id = :v1");
      
      EXEC SQL PREPARE s FROM :c_sql;
      
      EXEC SQL DECLARE cur_user_fee CURSOR FOR s;
      
      EXEC SQL OPEN cur_user_fee USING :ac_user_id;
      
      while(1)
      {
      
      EXEC SQL FETCH cur_user_fee into :c_user_id,:c_user_name,:c_date,:n_fee);
      
      if (sqlca.sqlcode < 0)
      {
      /*FETCH CURSOR失敗*/
      printf("fetch cursor cur_user_fee fail,sqlcode=%ld,sqlserr=%s",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
      }
      if( sqlca.sqlcode == SQLNOTFOUND)
      {
      break;
      }
      }
      EXEC SQL CLOSE cur_user_fee;
      
      (4)動態SQL4:要處理的字段及輸入的宿主變量數目和主變量的類型事先是不知道的,如:
      INSERT INTO EMP (<unknown> VALUES (<unknown>
      
      是最復雜的動態SQL,很少用,在此不做介紹。
      
      10、SQLCA:SQL是ORACLE的一個結構體,它的域用于最近的一條SQL語句執行后的一些信息,如錯誤號,錯誤描述,警告,狀態等。常用的
      

      域介紹如下:
      SQLCA.sqlcode:錯誤號,=0正確,=1403沒取到數據
      SQLCA.sqlserrm.sqlerrmc:錯誤描述
      SQLCA.sqlerrd[3]:最近的一條SQL語句所處理的行數,如果該語句處理失敗,則它的值是不定的,如果錯誤在一個CURSOR操作中發生,則
      
      它的值指已成功處理的行數.在DELETE,UPDATE中,它不包含因外鍵約束而刪除,更新的那些行,
      DELETE FROM EMP WHERE DEPT='SALE';
      
      在表EMP中刪除20行,但如果表EMP與表ADDRESS有外鍵約束,導致表ADDRESS也被刪除20行,則SQLCA.sqlerrd[3]=20,而不是40。

    原文網址:http://oracle.chinaitlab.com/exploiture/38243.html
    posted on 2007-01-24 13:36 jinn 閱讀(475) 評論(0)  編輯  收藏 所屬分類: Oracle/pro*c

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(3)

    隨筆分類

    文章分類

    相冊

    網站鏈接

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲免费在线视频| 久久久久久久岛国免费播放| 成人免费看片又大又黄| 亚洲免费二区三区| av无码国产在线看免费网站| 亚洲一区二区三区久久| 最近免费中文字幕大全| 亚洲精品美女久久久久久久| 日韩一区二区免费视频| 国产亚洲视频在线播放大全| 亚洲午夜成人精品电影在线观看| 亚洲高清免费视频| 国产精品国产亚洲精品看不卡| 91精品国产免费久久国语蜜臀 | 在线看片免费不卡人成视频| 亚洲一区二区三区免费在线观看| 一个人免费观看视频www| 在线观看亚洲网站| 国产∨亚洲V天堂无码久久久| 最近中文字幕高清免费中文字幕mv| 亚洲精品视频免费看| 在线观看免费污视频| jizz免费一区二区三区| 亚洲AV无码一区二区乱子伦| 四虎1515hh永久久免费| 亚洲国产精品无码第一区二区三区| 亚洲 国产 图片| 5555在线播放免费播放| 亚洲av无码成人精品国产| 久久久久亚洲AV综合波多野结衣| 久9热免费精品视频在线观看| 中文字幕亚洲码在线| 亚洲精品WWW久久久久久| 99久久免费精品高清特色大片| 亚洲人成网亚洲欧洲无码| 亚洲毛片αv无线播放一区| 99久久久国产精品免费无卡顿| 美女黄频a美女大全免费皮| 亚洲av无码潮喷在线观看| 国产美女精品久久久久久久免费| 三级黄色在线免费观看|