項目開發之存儲過程發生的那些事

前言   

       以前在項目開發過程當中,須要有一步操做就是使用存儲過程刪除一系列相關的表,再使用mybatis調用該存儲過程,輸入參數爲家人帳號,類型爲String,數據庫表結構中,該帳號字段類型爲varchar2,再實操的過程當中,沒有發生錯誤,多是輸入參數雖然傳入的是String類型,可是該帳號內容所有爲數字,由於在執行過程當中就報「ORA-01722: 無效數字」異常了。         

緣由分析

         輸入參數雖然是字符串類型,可是內容均爲數字,在執行存儲過程字符串拼接時,若是是使用「||」符號進行拼接,那麼拼接後的sql是沒有單引號的,也就是好比存儲過程當中某條語句:execu_sql := 'delete from userinfo where account = ' ||account;(execu_sql爲在存儲過程定義的變量,爲varchar(2000),":="爲賦值操做,至關於把這條sql賦值給execu_sql這個表變量進行保存),可是執行完成後,execu_sql這個變量內容爲:"delete from userinfo where account = XXXXXX",咱們知道,把這個sql運行,確定會報無效數字異常的,所以異常就是這樣出現的,由於oracle有隱式轉換機制,若是你傳入的雖然是String類型的變量,可是若是變量的內容所有都會數字,那麼oracle默認會將該String類型變量轉化爲數字,那麼運行時就會報錯了。

解決方案

        那麼咱們在實操的過程當中就要動態的拼接單引號了,可使用ASCII 編碼,單引號的ASCII 編碼我39,那麼存儲過程sql能夠這樣寫:execu_sql := 'delete from userinfo where account = '||chr(39)||account||chr(39);這樣就不會出錯了。

 

loop循環使用

       loop循環中能夠循環調用存儲過程而不會報錯,例如:

     --循環建立明日的表
     loop
   --抽取方法,檢查今天的表有無建立,若是沒有就建立
   create_gps_day_table(current_datetime);
   
   --抽取方法,檢查今天表序列是否建立,若是沒有就建立
   create_gps_day_seq(current_datetime);
   
   current_datetime := current_datetime+1;
   --當中間天數小於結束月份天數跳出循環
    exit when current_datetime>end_datetime;
    end loop; sql

    可是若是loop循環中循環執行多條sql操做,則循環會失效,例如:

     loop    
       execu_sql := 'alter table '||table_names||' add(datas clob)';
       execute immediate execu_sql;
      
       execu_sql := 'update '||table_names||' set datas = data';
       execute immediate execu_sql;
   
       execu_sql := 'alter table '||table_names||' drop column data'; 
       execute immediate execu_sql;
   
       execu_sql := 'alter table '||table_names||' rename column datas to data';
       execute immediate execu_sql;
   
       start_datetime := start_datetime+1;
   
       exit when start_datetime>current_datetime;
     end loop;  數據庫

     或者一條存儲過程當中寫多個循環,而且循環中執行一條sql操做,則第一條循環能成功,然後續循環均報:

ORA-00942:表或視圖不存在錯誤。例如:

     loop    
       table_names := 'tb_app_time_'||start_datetime;
 
       execu_sql := 'alter table '||table_names||' add(datas clob)';
       execute immediate execu_sql;
   
       start_datetime := start_datetime + 1;
   
       exit when start_datetime>end_datetime;
     end loop;  
 
      loop          
       table_names := 'tb_app_time_'||start_datetime;
   
       execu_sql := 'update '||table_names||' set datas = data';
       execute immediate execu_sql;
   
       start_datetime := start_datetime+1;
   
       exit when start_datetime>end_datetime;
     end loop; mybatis

相關文章
相關標籤/搜索