完成批量修改user_tables中的所有表的欄位名(從MS SQL導入過來,發現大小寫問題,造成很多麻煩)
存儲過程見下:
-- Created on 2012/3/14 by FREE declare -- Local variables here Cursor tbl_cur is select table_name from user_tables; --col_cur Cursor; i integer; tbl_name varchar2(50); col_name varchar2(50); begin -- Test statements here for tbl_name in tbl_cur LOOP for col_cur in (select COLUMN_NAME from all_tab_columns where table_name=tbl_name.table_name) LOOP dbms_output.put_line('alter table '||tbl_name.table_name||' rename column "'||col_cur.column_name||'" to '||col_cur.column_name); end LOOP; end LOOP; end;
(從以下轉載文章中收獲很多,謝謝作者。轉自:http://hi.baidu.com/wang90627/blog/item/394e7d019d57329ce850cd5d.html)
創建存儲過程,需要有CREATE PROCEDURE或CREATE ANY PROCEDURE的系統權限。該權限可由系統管理員授予。創建一個存儲過程的基本語句如下:
CREATE [OR REPLACE] PROCEDURE 存儲過程名 [(參數[IN|OUT|IN OUT]數據類型…)] {AS|IS} [說明部分] BEGIN 可執行部分 [EXCEPTION 錯誤處理部分] END [過程名];
其中:
可選關鍵字OR REPLACE表示如果存儲過程已經存在,則用新的存儲過程覆蓋,通常用於存儲過程的重建。
參數部分用於定義多個參數(如果沒有參數,就可以省略)。參數有三種形式:IN、OUT和IN OUT。如果沒有指明參數的形式,則默認為IN。
關鍵字AS也可以寫成IS,后跟過程的說明部分,可以在此定義過程的局部變量。
編寫存儲過程可以使用任何文本編輯器或直接在SQL *Plus環境下進行,編寫好的存儲過程必須要在SQL *Plus環境下進行編譯,生成編譯代碼,原代碼和編譯代碼在編譯過程中都會被存入數據庫。編譯成功的存儲過程就可以在Oracle環境下進行調用了。
一個存儲過程在不需要時可以刪除。刪除存儲過程的人是過程的創建者或者擁有DROP ANY PROCEDURE系統權限的人。刪除存儲過程的語法如下:
DROP PROCEDURE 存儲過程名;
如果要重新編譯一個存儲過程,則只能是過程的創建者或者擁有ALTER ANY PROCEDURE系統權限的人。語法如下:
ALTER PROCEDURE 存儲過程名 COMPILE;
執行(或調用)存儲過程的人是過程的創建者或是擁有EXECUTE ANY PROCEDURE系統權限的人或是被擁有者授予EXECUTE權限的人。執行的方法如下:
方法1:
EXECUTE 模式名.存儲過程名[(參數…)];
方法2:
BEGIN
模式名.存儲過程名 [(參數…)];
END;
傳遞的參數必須與定義的參數類型、個數和順序一致(如果參數定義了默認值,則調用時可以省略參數)。參數可以是變量、常量或表達式,用法參見下一節。
如果是調用本賬戶下的存儲過程,則模式名可以省略。要調用其他賬戶編寫的存儲過程,則模式名必須要添加。
下面是我自己的實驗:
注:游標可以“顯式”聲明,也可以“隱式”聲明。“隱式”聲明的意思是,不用聲明游標,在for循環中直接用游標的record就行。例一是內外 層循環游標都是“隱式”聲明的情況(內層循環的游標,需要用到外層循環的游標值,所以不能兩個游標都在第一個循環外聲明)。(一般:游標名是 xxx__cursor,游標中的每行記錄名是xxx_record 。並且,內層循環要用游標,內層的游標應該要用“隱式”聲明,外層游標可用可不用。)
例一:
CREATE OR REPLACE PROCEDUREmain_mx AS BEGIN FOR mainout_recordIN( SELECT /*這里的mainout_record直接是游標的每行記錄了。另外IN后面如果是select語句,就要加括號,並且select語句結束不用;結尾,IN后面如果是游標名,就不要括號*/ ID,smscontent,allcode,cjr,pretongdaoid,clientid,shr,pretime,cjsj,shstatus,shsj from t_busi_main_presend where shstatus in('1','9') and klstatus='2') LOOP /* insert into T_BUSI_PRESEND_MX*/ /* CURSOR mainmobile_cursor IS SELECT * FROM TABLE(fn_split(mainout_record.allcode,',')); */ FOR mainmobile_record IN (SELECT column_value cv FROM TABLE(fn_split(mainout_record.allcode,','))) LOOP /*SELECT column_value cv FROM TABLE(fn_split(mainout_record.allcode,','),這句話是執行fn_split這個函數,函數功能類似java中的split功能,但是oracle本身沒有這個函數,所以要自己寫,代碼是我在網上拷的,注意因為mainout_record.allcode這個記錄集就只有“一列”記錄,allcode是外層游標查出來的一個列名,所以前面是selectcolumn_value,后面打印值的時候也是寫.column_value: 功能描述:用指定分隔符切割輸入的字符串,返回一維數組,每個數組元素為一個子串。 先: CREATE OR REPLACE TYPE ty_str_split IS TABLE OF VARCHAR2 (4000); 再: CREATE OR REPLACE FUNCTION fn_split(p_str IN CLOB, p_delimiter IN VARCHAR2) RETURN ty_str_split IS j INT := 0; i INT := 1; len INT := 0; len1 INT := 0; str VARCHAR2 (4000); str_split ty_str_split := ty_str_split (); BEGIN len := LENGTH (p_str); len1 := LENGTH (p_delimiter); WHILE j < len LOOP j := INSTR (p_str, p_delimiter, i); IF j = 0 THEN j := len; str := SUBSTR (p_str, i); str_split.EXTEND; str_split (str_split.COUNT) := str; IF i >= len THEN EXIT; END IF; ELSE str := SUBSTR (p_str, i, j - i); i := j + len1; str_split.EXTEND; str_split (str_split.COUNT) := str; END IF; END LOOP; RETURN str_split; END fn_split; */ DBMS_OUTPUT.PUT_LINE(mainmobile_record.cv);/*打印結果的時候,直接反鍵存儲過程名-->測試有時是出不來結果的,這時應該"新建"-->"命令窗口"--SQL>set serveroutput on -->execute main_mx(這是存儲過程名),這樣才能打印結果 */ END LOOP; END LOOP; END;
例二(外層for循環游標是“顯式”聲明):
CREATE OR REPLACE PROCEDUREmain_mx_1 as CURSOR mainout_cursor IS SELECT ID,smscontent,allcode,cjr,pretongdaoid,clientid,shr,pretime,cjsj,shstatus,shsj from t_busi_main_presend where shstatus in('1','9') and klstatus='2'; begin FOR mainout_record IN mainout_cursor LOOP /* insert into T_BUSI_PRESEND_MX*/ /* CURSOR mainmobile_cursor IS SELECT * FROM TABLE(fn_split(mainout_record.allcode,',')); BEGIN*/ FOR mainmobile_record IN (SELECT column_value cv FROM TABLE(fn_split(mainout_record.allcode,','))) LOOP DBMS_OUTPUT.PUT_LINE(mainmobile_record.cv); END LOOP; END LOOP; END;