oracle存儲過程-cursor遊標基礎

Cursor的應用場景:sql

查詢結果集list ,使用cursor 的狀況,確定會有下邊這兩種狀況,纔可能使用到cursor :數組

  1. 須要依據查詢到的結果集,做爲條件,進行下一步的查詢。
  2. 須要在結果集某個位置上,知足某種條件時,對數據進行不一樣的修改。

上邊的兩種狀況,都會涉及到遍歷數據,因此遊標的使用也須要注意:oop

好比,你的查詢結果集很大,首先佔了不少的內存,其次,遍歷這麼龐大的結果集,效率也確定高不了。
另外,若是還有其餘方式解決問題的話,那就不要選擇使用遊標,可是遊標在使用中,的確有,定義遊標、打開遊標、關閉遊標,這些操做,這樣也確定快不了多少。code

 

Cursor的類別:orm

1.隱式遊標。server

    DML操做和單行SELECT語句會使用隱式遊標,如:INSERST,UPDATE,DELETE , SELECT ... INTO ..內存

    另外一種方式 :資源

create or replace procedure test_class_procedure
as
begin
for class_dec in (
  select * from t_class
)
loop
dbms_output.put_line('姓名:'||class_dec.name||' 年齡:'||class_dec.age);
end loop;
end;

 執行:input

set serveroutput on;
begin
 test_class_procedure;
end;

    隱式遊標其實默認已經打開遊標,並在執行完成後關閉遊標釋放資源。it

2.顯示遊標。

   顯示遊標分爲靜態遊標與動態遊標,顯示遊標的寫法會在存儲過程當中定義Cursor ,而且通常都有固定的四個步驟:聲明遊標 、打開遊標 、提取數據 、關閉遊標 。顯式遊標打開後,必須顯式地關閉。遊標一旦關閉,遊標佔用的資源就被釋放,遊標變成無效,必須從新打開才能使用。

示例:

CREATE OR REPLACE NONEDITIONABLE PROCEDURE PRC_MDS1_TO_MDS2 (parameter IN VARCHAR2, exitcode OUT INT)
AS
	-- 定義一個變量用來保存此存儲過程的名字
	v_logic_proc_name VARCHAR2(30) := 'PRC_MDS1_TO_MDS2';
	
	-- 聲明顯式遊標, 查詢udt_mds1_input中item不爲null的數據
  	CURSOR c_udt_mds1_input_item_notnull IS SELECT * FROM scpomgr.udt_mds1_input WHERE item IS NOT NULL AND TRIM(item) IS NOT NULL;
  	-- 定義遊標變量,該變量的類型爲基於遊標c_udt_mds1_input_item_notnull的記錄 
  	c_mds1_item_notnull_row c_udt_mds1_input_item_notnull%ROWTYPE;  
  	
  	-- 聲明一個遊標,查詢udt_mds1_input中item爲null的數據 -- MARKET、itemgroup、package、config不爲NULL
  	CURSOR c_udt_mds1_input_item_null IS 
  			SELECT * 
  			FROM scpomgr.udt_mds1_input 
  			WHERE (item IS NULL OR TRIM(item) IS NULL)
  			AND market IS NOT NULL AND TRIM(market) IS NOT NULL
  			AND itemgroup IS NOT NULL AND TRIM(itemgroup) IS NOT NULL 
  			AND package IS NOT NULL AND TRIM(package) IS NOT NULL
  			AND config IS NOT NULL AND TRIM(config) IS NOT NULL;
  	-- 定義遊標變量
  	c_mds1_item_null_row c_udt_mds1_input_item_null%ROWTYPE;
  	
  	-- 再聲明一個遊標,查詢udt_mds1_input中item爲null -- MARKET、ITEMGROUP、PACKAGE、CONFIG有爲NULL的
  	CURSOR c_udt_mds1_item_null_other IS 
  			SELECT * 
  			FROM scpomgr.udt_mds1_input 
  			WHERE (item IS NULL OR TRIM(item) IS NULL)
  			AND (market IS NULL OR TRIM(market) IS NULL
  				OR itemgroup IS NULL OR TRIM(itemgroup) IS NULL
  				OR package IS NULL OR TRIM(package) IS NULL
  				OR config IS NULL OR TRIM(config) IS NULL); 
  	-- 定義遊標變量
  	c_mds1_item_null_other_row c_udt_mds1_item_null_other%ROWTYPE;

BEGIN
  
	-- 設置要返回的變量值
	exitcode := -20999;

	-- 若是傳入的參數是BYPASS, 則表示不運行
	IF parameter = 'BYPASS' THEN
		exitcode := 0;	-- 返回0表示執行成功
      	RETURN;
   	END IF;

   	-- 記錄具體邏輯開始執行
	logger.info (v_logic_proc_name || ':' || parameter || ' ,Start');
   
	------------------- 具體的業務邏輯  -------------------
	
	-- 1. 將UDT_MDS1_INPUT全部字段輸入到MDS1_BCKUP對應同名字段中
	pkg_log.info(v_logic_proc_name || ':' || '步驟1,將UDT_MDS1_INPUT的數據備份到MDS1_BCKUP表中');
	INSERT INTO scpomgr.MDS1_BCKUP SELECT * FROM scpomgr.UDT_MDS1_INPUT;
	
	-- 2. 是否要先清空中間表和UDT_MDS2_REVIEW表中的數據
	pkg_log.info(v_logic_proc_name || ':' || '步驟2,刪除mid_mds1_mds2和udt_mds2_review表中的數據');
  	DELETE FROM scpomgr.mid_mds1_mds2;  	-- 刪除中間表數據
  	DELETE FROM scpomgr.udt_mds2_review;   	-- 刪除UDT_MDS2_REVIEW表數據
  	
  	-- 3. 循環處理ITEM不爲NULL的數據 
  	pkg_log.info(v_logic_proc_name || ':' || '步驟3,循環處理udt_mds1_input中item不爲null的數據');
  	FOR c_mds1_item_notnull_row IN c_udt_mds1_input_item_notnull LOOP
  		-- 使用嵌套內部塊
  		declare
	    	-- 定義變量
  			v_country scpomgr.udt_country_ratio.country%TYPE; 	-- 定義一個國家變量
  			v_color scpomgr.udt_basic_info.color%TYPE;       	-- 定義一個顏色變量
	    begin
	      	-- 3.1 查詢udt_country_ratio.country信息,並賦值給v_country
	    	BEGIN
	    	SELECT country INTO v_country  
	    	FROM (
	         		SELECT ucr.country
	         		FROM scpomgr.udt_country_ratio ucr
	         		WHERE ucr.market=c_mds1_item_notnull_row.market 
	         		AND ucr.itemgroup=c_mds1_item_notnull_row.itemgroup
	         	) 
	    	WHERE ROWNUM=1;
	    	EXCEPTION 
	          	WHEN no_data_found THEN
	          	pkg_log.error(v_logic_proc_name || ':' || '根據' || c_mds1_item_notnull_row.market || '和' || c_mds1_item_notnull_row.itemgroup || 
	          				'沒有在scpomgr.udt_country_ratio查詢到對應的國家信息');
	          	prc_udt_error_log(c_mds1_item_notnull_row.itemgroup, c_mds1_item_notnull_row.market, '', 
	          			'沒有在scpomgr.udt_country_ratio查詢到對應的國家信息', 1, 'PRC_MDS1_TO_MDS2');
	    	END;
       
	    	-- 3.2 查詢udt_basic_info.color信息,並賦值給v_color
	    	BEGIN 
	    	SELECT color INTO v_color  
	    	FROM (
	         		SELECT ubi.color
	         		FROM scpomgr.udt_basic_info ubi
	         		WHERE ubi.item = c_mds1_item_notnull_row.item
	         	) 
	    	WHERE ROWNUM=1;
	    	EXCEPTION 
	          	WHEN no_data_found THEN
	          	pkg_log.error(v_logic_proc_name || ':' || '根據' || c_mds1_item_notnull_row.item || '沒有在scpomgr.udt_basic_info查詢到對應的顏色信息');
	          	prc_udt_error_log(c_mds1_item_notnull_row.item, '', '', '沒有在scpomgr.udt_basic_info查詢到對應的顏色信息', 1, 'PRC_MDS1_TO_MDS2');
	    	END;     
    
	    	-- 3.3 將數據保存到中間表中
	    	INSERT INTO scpomgr.mid_mds1_mds2(market,brand,itemgroup,item,descr,status,loc,package,config,dmdtype,version_no,country,color,
	                w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24,w25,w26,w27)   
	    	VALUES (c_mds1_item_notnull_row.market, c_mds1_item_notnull_row.brand, c_mds1_item_notnull_row.itemgroup, c_mds1_item_notnull_row.item, c_mds1_item_notnull_row.descr,
	             c_mds1_item_notnull_row.status, c_mds1_item_notnull_row.loc, c_mds1_item_notnull_row.package, c_mds1_item_notnull_row.config, c_mds1_item_notnull_row.dmdtype,
	             c_mds1_item_notnull_row.version_no, v_country, v_color, c_mds1_item_notnull_row.w0, c_mds1_item_notnull_row.w1, c_mds1_item_notnull_row.w2,
	             c_mds1_item_notnull_row.w3, c_mds1_item_notnull_row.w4, c_mds1_item_notnull_row.w5, c_mds1_item_notnull_row.w6, c_mds1_item_notnull_row.w7,
	             c_mds1_item_notnull_row.w8, c_mds1_item_notnull_row.w9, c_mds1_item_notnull_row.w10, c_mds1_item_notnull_row.w11, c_mds1_item_notnull_row.w12,
	             c_mds1_item_notnull_row.w13, c_mds1_item_notnull_row.w14, c_mds1_item_notnull_row.w15, c_mds1_item_notnull_row.w16, c_mds1_item_notnull_row.w17,
	             c_mds1_item_notnull_row.w18, c_mds1_item_notnull_row.w19, c_mds1_item_notnull_row.w20, c_mds1_item_notnull_row.w21, c_mds1_item_notnull_row.w22,
	             c_mds1_item_notnull_row.w23, c_mds1_item_notnull_row.w24, c_mds1_item_notnull_row.w25, c_mds1_item_notnull_row.w26, c_mds1_item_notnull_row.w27);
	    end;
  	END LOOP;
  	
  	-- 4. 循環處理ITEM爲NULL的數據 
  	pkg_log.info(v_logic_proc_name || ':' || '步驟4,循環處理udt_mds1_input中item爲null,但MARKET/itemgroup/package/config不爲NULL的數據');
  	FOR c_mds1_item_null_row IN c_udt_mds1_input_item_null LOOP
  		-- 使用嵌套內部塊
  		declare
	    	-- 定義變量
	    	v_item scpomgr.udt_basic_info.item%TYPE;   		-- 定義item
  			v_descr scpomgr.udt_basic_info.descr%TYPE;   	-- 定義descr
			-- 定義國家和國家佔比  			
  			v_country scpomgr.udt_country_ratio.country%TYPE; 				-- 國家
  			v_country_ratio scpomgr.udt_country_ratio.country_ratio%TYPE;   -- 國家佔比
		  	
  			-- 使用數組定義15種顏色及佔比
  			type v_color_varray is varray(15) of scpomgr.udt_country_ratio.color1%TYPE;		-- 顏色
  			v_color v_color_varray := v_color_varray('', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  			type v_color_ratio_varray is varray(15) of scpomgr.udt_country_ratio.color1_ratio%TYPE;		-- 顏色佔比
  			v_color_ratio v_color_ratio_varray := v_color_ratio_varray(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
		  	
		  	-- 使用數組定義28周的數據量變量
		  	type v_w_varray is varray(28) of scpomgr.udt_mds1_input.w0%TYPE;
		  	v_w v_w_varray := v_w_varray(c_mds1_item_null_row.w0,c_mds1_item_null_row.w1,c_mds1_item_null_row.w2,c_mds1_item_null_row.w3,c_mds1_item_null_row.w4,c_mds1_item_null_row.w5,
		  						c_mds1_item_null_row.w6,c_mds1_item_null_row.w7,c_mds1_item_null_row.w8,c_mds1_item_null_row.w9,c_mds1_item_null_row.w10,c_mds1_item_null_row.w11,
							  	c_mds1_item_null_row.w12,c_mds1_item_null_row.w13,c_mds1_item_null_row.w14,c_mds1_item_null_row.w15,c_mds1_item_null_row.w16,c_mds1_item_null_row.w17,
							  	c_mds1_item_null_row.w18,c_mds1_item_null_row.w19,c_mds1_item_null_row.w20,c_mds1_item_null_row.w21,c_mds1_item_null_row.w22,c_mds1_item_null_row.w23,
							  	c_mds1_item_null_row.w24,c_mds1_item_null_row.w25,c_mds1_item_null_row.w26,c_mds1_item_null_row.w27);
		  	
	    begin
		    -- 4.1 查詢udt_country_ratio中抓取對應的country、 country_ratio、color1..1五、color1..15_ratio,並賦值給相應的變量
	    	BEGIN
	    	SELECT country,country_ratio,color1,color1_ratio,color2,color2_ratio,color3,color3_ratio,color4,color4_ratio,color5,color5_ratio,color6,color6_ratio,
	    			color7,color7_ratio,color8,color8_ratio,color9,color9_ratio,color10,color10_ratio,color11,color11_ratio,color12,color12_ratio,color13,color13_ratio,
	    			color14,color14_ratio,color15,color15_ratio
	    	INTO v_country,v_country_ratio,v_color(1),v_color_ratio(1),v_color(2),v_color_ratio(2),v_color(3),v_color_ratio(3),v_color(4),v_color_ratio(4),
	    			v_color(5),v_color_ratio(5),v_color(6),v_color_ratio(6),v_color(7),v_color_ratio(7),v_color(8),v_color_ratio(8),v_color(9),v_color_ratio(9), 
	    			v_color(10),v_color_ratio(10),v_color(11),v_color_ratio(11),v_color(12),v_color_ratio(12),v_color(13),v_color_ratio(13),v_color(14),v_color_ratio(14),
	    			v_color(15),v_color_ratio(15)
	    	FROM (
	         		SELECT ucr.country,ucr.country_ratio,ucr.color1,ucr.color1_ratio,ucr.color2,ucr.color2_ratio,ucr.color3,ucr.color3_ratio,ucr.color4,ucr.color4_ratio,
	         			ucr.color5,ucr.color5_ratio,ucr.color6,ucr.color6_ratio,ucr.color7,ucr.color7_ratio,ucr.color8,ucr.color8_ratio,ucr.color9,ucr.color9_ratio,
	         			ucr.color10,ucr.color10_ratio,ucr.color11,ucr.color11_ratio,ucr.color12,ucr.color12_ratio,ucr.color13,ucr.color13_ratio,ucr.color14,ucr.color14_ratio,
	         			ucr.color15,ucr.color15_ratio
	         		FROM scpomgr.udt_country_ratio ucr
	         		WHERE ucr.market = c_mds1_item_null_row.market
	         		AND ucr.itemgroup = c_mds1_item_null_row.itemgroup
	         	) 
	    	WHERE ROWNUM=1;
	    	EXCEPTION 
	          	WHEN no_data_found THEN
	          	pkg_log.error(v_logic_proc_name || ':' || '根據' || c_mds1_item_null_row.market || '和' || c_mds1_item_null_row.itemgroup || 
	          			'沒有在scpomgr.udt_country_ratio查詢到對應國家和顏色及佔比信息');
	          	prc_udt_error_log(c_mds1_item_null_row.itemgroup, c_mds1_item_null_row.market, '', 
	          			'沒有在scpomgr.udt_country_ratio查詢到對應國家和顏色及佔比信息', 1, 'PRC_MDS1_TO_MDS2');
	    	END;
	    	
	    	-- 4.2對於country_ratio、color_ratio不爲NULL的記錄 更新W0-W27的數據
	    	FOR i in 1 .. 15 LOOP
	    		-- 先判斷有沒有顏色,若是沒有則不處理
	    		IF(v_color(i) IS NOT NULL AND TRIM(v_color(i)) IS NOT NULL) THEN
	    			-- 4.2.1 獲取item,descr
	    			v_item := '';
	    			v_descr := '';	-- 先設置爲默認值
			    	BEGIN 
			    	SELECT item,descr INTO v_item,v_descr  
			    	FROM (
			         		SELECT ubi.item,ubi.descr
			         		FROM scpomgr.udt_basic_info ubi
			         		WHERE ubi.country = v_country
			         		AND ubi.itemgroup = c_mds1_item_null_row.itemgroup
				         	AND ubi.package = c_mds1_item_null_row.package
				         	AND ubi.color = v_color(i)
				         	AND ubi.config = c_mds1_item_null_row.config
			         	) 
			    	WHERE ROWNUM=1;
			    	EXCEPTION 
			          	WHEN no_data_found THEN
			          	pkg_log.error(v_logic_proc_name || ':' || '根據' || c_mds1_item_null_row.itemgroup || ',' || c_mds1_item_null_row.package || ',' ||
								v_color(i) || ',' || c_mds1_item_null_row.config || '沒有在scpomgr.udt_basic_info查詢到對應的item和descr信息');
			          	prc_udt_error_log(c_mds1_item_null_row.itemgroup, c_mds1_item_null_row.package|| '+' || c_mds1_item_null_row.config, '', 
	          					'沒有在scpomgr.udt_basic_info查詢到對應的item和descr信息', 1, 'PRC_MDS1_TO_MDS2');
			    	END;
	    		
		    		-- 4.2.2 若是不爲空,則要計算v_w的數據
					IF(v_country_ratio IS NOT NULL AND v_color_ratio(i) IS NOT NULL) THEN
						--循環處理v_w0...v_w27的數據
				    	FOR j in 1 .. 28 LOOP
				    		v_w(j) := v_w(j) * v_country_ratio * v_color_ratio(i);
				    	END LOOP;
				    	-- 將處理完的數據插入到中間表中
				    	INSERT INTO scpomgr.mid_mds1_mds2(market,itemgroup,package,config,country,country_ratio,color,color_ratio,item, descr,
	                		w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24,w25,w26,w27)   
	    				VALUES (c_mds1_item_null_row.market, c_mds1_item_null_row.itemgroup, c_mds1_item_null_row.package, c_mds1_item_null_row.config, v_country, v_country_ratio, 
	    					v_color(i),v_color_ratio(i), v_item, v_descr, 
	    					v_w(1), v_w(2), v_w(3), v_w(4), v_w(5), v_w(6), v_w(7), v_w(8), v_w(9), v_w(10), v_w(11), v_w(12), v_w(13), v_w(14), v_w(15), v_w(16),v_w(17), 
	    					v_w(18), v_w(19), v_w(20), v_w(21), v_w(22), v_w(23), v_w(24), v_w(25), v_w(26), v_w(27), v_w(28));
				    END IF;
	    		END IF;
			END LOOP;
  		end;
    END LOOP;
    
    -- 5. 對於若UDT_MDS1_INPUT.ITEM爲NULL,MARKET、ITEMGROUP、PACKAGE、CONFIG有爲NULL的
    pkg_log.info(v_logic_proc_name || ':' || '步驟5,循環處理udt_mds1_input中item爲null,而且MARKET/itemgroup/package/config有爲NULL字段的數據');
  	FOR c_mds1_item_null_other_row IN c_udt_mds1_item_null_other LOOP
  		-- 使用嵌套內部塊
  		declare
  			-- 定義一個變量保存數據
  			v_null_filed varchar2(500);
  		begin
  			if(c_mds1_item_null_other_row.market is null or trim(c_mds1_item_null_other_row.market) is null) then
				v_null_filed := v_null_filed || 'market,';
			elsif(c_mds1_item_null_other_row.itemgroup is null or trim(c_mds1_item_null_other_row.itemgroup) is null) then
				v_null_filed := v_null_filed || 'itemgroup,';
			elsif(c_mds1_item_null_other_row.package is null or trim(c_mds1_item_null_other_row.package) is null) then
				v_null_filed := v_null_filed || 'package,';
			elsif(c_mds1_item_null_other_row.config is null or trim(c_mds1_item_null_other_row.config) is null) then
				v_null_filed := v_null_filed || 'config';
			end if;
	  		-- 找出哪一個字段爲空,並記錄下來
	  		pkg_log.error(v_logic_proc_name || ':' || 'scpomgr.UDT_MDS1_INPUT表中下面字段爲空: ' || v_null_filed);
    		prc_udt_error_log('', '', '', 'scpomgr.UDT_MDS1_INPUT表中下面字段爲空: ' || v_null_filed, 1, 'PRC_MDS1_TO_MDS2');
	  	END;
  	END LOOP;
  	
  	-- 6. 將中間表的數據保存到UDT_MDS2_REVIEW表中
  	pkg_log.info(v_logic_proc_name || ':' || '步驟6,將中間表mid_mds1_mds2的數據保存到udt_mds2_review表中');
  	INSERT INTO scpomgr.udt_mds2_review(market,brand,itemgroup,item,descr,status,loc,package,color,config,dmdtype,version_no,
              w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24,w25,w26,w27)
  	SELECT market,brand,itemgroup,item,descr,status,loc,package,color,config,dmdtype,version_no,
         	w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24,w25,w26,w27 
  	FROM scpomgr.mid_mds1_mds2;
	
	-- 說明沒有錯誤, 執行成功
	exitcode := 0;
   	-- 記錄完成
	logger.info (v_logic_proc_name || ':' || parameter || ' ,Success');
   	-- 成功的話, 提交
	COMMIT;

EXCEPTION
	WHEN OTHERS THEN
		exitcode := SQLCODE;	-- 返回錯誤代碼
      	pkg_log.error('Failure:' || v_logic_proc_name || ':' || SQLCODE || ':' || SQLERRM || ':' || substr(dbms_utility.format_error_backtrace, 1, 1024));
      	COMMIT;
END PRC_MDS1_TO_MDS2;
相關文章
相關標籤/搜索