------------DB2版本------------
CREATE OR REPLACE PROCEDURE procedure_name(IN | OUT | INOUT parameter_name data-type,...) )--存儲過程可以設定輸入參數和輸出參數
LANGUAGE SQL--DB2可以用多種語言編寫存儲過程,這里用的是純SQL BEGIN--開始DECLARE vID smallint;--定義變量,和Oracle一樣 DECLARE變量名 變量的數據類型;
FOR V AS SELECT BRND_CD FROM TMP_BRND_CD--for循環 tmp_brnd_cd預先創建好
DO--循環體開始
SET vID=BRND_CD;--對vID賦值,db2可以用set賦值,也可以用values賦值,這里可以寫成values(BRND_CD) into vID
INSERT INTO WWM_FORINSERT_TEST VALUES(vID);--往wwm_forinsert_test 插入數據
END FOR;--循環體結束
END @--存儲過程結束
--循環
•LOOP 循環,簡單的循環
CREATE PROCEDURE LEAVE_LOOP (DEPTIN char(3), OUT p_counter INTEGER)
Ll: BEGIN
DECLARE v_at_end , v_counter INTEGER DEFAULT 0;
DECLARE v_lastname VARCHAR(15);
DECLARE v_birthd, v_hired DATE;
DECLARE c1 CURSOR
FOR SELECT lastname, hiredate, birthdate FROM employee--定義游標:
WHERE WORKDEPT = deptin;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_at_end = 1;
OPEN c1;--打開游標
FETCH_LOOP: LOOP
FETCH c1 INTO v_lastname, v_hired, v_birthd;
IF v_at_end <> 0 THEN -- loop until last row of the cursor
LEAVE FETCH_LOOP; --跳出loop循環??
END IF;
SET v_counter = v_counter + 1;
INSERT INTO REPORT_INFO_DEPT
values(v_lastname, v_hired, v_birthd);
END LOOP FETCH_LOOP;
SET p_counter = v_counter;
END Ll
•WHILE 循環,進去循環前檢查條件是否滿足
CREATE PROCEDURE DEPT_REPT (DEPTIN char(3), OUT p_counter INTEGER)
P1: BEGIN
DECLARE v_at_end , v_counter INTEGER DEFAULT 0;
DECLARE v_lastname VARCHAR(15);
DECLARE v_birthd, v_hired DATE;
DECLARE c1 CURSOR
FOR SELECT lastname, hiredate, birthdate FROM employee
WHERE WORKDEPT = deptin;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_at_end = 1;
OPEN c1;
FETCH c1 INTO v_lastname, v_hired, v_birthd;
WHILE (v_at_end = 0)
DO
INSERT INTO REPORT_INFO_DEPT
values(v_lastname, v_hired, v_birthd);
SET v_counter = v_counter + 1;
FETCH c1 INTO v_lastname, v_hired, v_birthd; --??
END WHILE;
SET p_counter = v_counter;
END P1
•REPEAT 循環,退出前檢查條件
•FOR 循環
CREATE PROCEDURE DEPT_REPT1 (DEPTIN char(3), OUT p_counter INT)
P1:BEGIN
DECLARE v_counter INT DEFAULT 0;
FOR dept_loop AS --此處給 FOR 起了名字
SELECT lastname, hiredate, birthdate FROM employee
WHERE WORKDEPT = deptin
DO
INSERT INTO REPORT_INFO_DEPT values
(dept_loop.lastname,dept_loop.hiredate,dept_loop.birthdate);
SET v_counter = v_counter + 1;
END FOR;
SET p_counter = v_counter;
END P1
--條件判斷:if語句
CREATE PROCEDURE UPDATE_SAL (IN empNum CHAR(6),INOUT rating SMALLINT)
LANGUAGE SQL
BEGIN
IF rating = 1 THEN
UPDATE employee SET salary = salary * 1.10, bonus = 1000 WHERE empno = empNum;
ELSIF rating = 2 THEN
UPDATE employee SET salary = salary * 1.05, bonus = 500 WHERE empno = empNum;
ELSE
UPDATE employee SET salary = salary * 1.03, bonus = 0 WHERE empno = empNum;
END IF;
END
•CASE 語句:支持兩種類型的 CASE 語句,以根據一個條件的狀態實現邏輯的分支
◦simple CASE 語句用於根據一個字面值進入某個邏輯
◦searched CASE 語句用於根據一個表達式的值進入某個邏輯
--使用 searched CASE 語句的存儲過程
CREATE PROCEDURE sal_increase_lim1 (empid CHAR(6))
BEGIN
DECLARE years_of_serv INT DEFAULT 0;
DECLARE v_incr_rate DEC(9,2) DEFAULT 0.0;
SELECT YEAR(CURRENT DATE) - YEAR(hiredate)
INTO years_of_serv
FROM empl1
WHERE empno = empid;
CASE
WHEN years_of_serv > 30 THEN
SET v_incr_rate = 0.08;
WHEN years_of_serv > 20 THEN
SET v_incr_rate = 0.07;
WHEN years_of_serv > 10 THEN
SET v_incr_rate = 0.05;
ELSE
SET v_incr_rate = 0.04;
END CASE;
UPDATE empl1
SET salary = salary+salary*v_incr_rate
WHERE empno = empid;
END
-----------游標
--•定義游標:DECLARE 游標名 CURSOR FOR SELECT 語句
在 SQL 過程中,游標除了迭代結果集中的行,還可以將結果集返回給調用程序或其他過程
•WITHOUT RETURN/WITH return:選項指定游標的結果表是否用於作為從一個過程中返回的結果集。
•WITH RETURN TO CALLER:選項指定將來自游標的結果集返回給調用者,后者可以是另一個過程或一個客戶機應用程序。這是默認選項。
•WITH RETURN TO CLIENT:選項指定將來自游標的結果集返回給客戶機應用程序,繞過任何中間的嵌套過程。
--下面是游標聲明的幾個例子:
1.DECLARE c1 CURSOR FOR select * from staff; --(DECLARE關鍵字,cl游標名稱,CURSOR是必須有的,指通過c1的游標來操作staff里所有的數據)最常用的最普通的。
2.DECLARE c1 CURSOR WITH HOLD FOR select * form staff; --如果不加with hold則此游標遇到commit或者rollback語句會自動關閉。加上了with hold 則必須用close關閉。
3.DECLARE c1 CURSOR WITH RETURN TO CALLER FOR select * form staff;
4.DECLARE c1 CURSOR WITH RETURN TO CLIENT FOR select * form staff;
若要從一個過程中返回結果集,需要:
•創建一個過程,創建時指定 DYNAMIC RESULT SETS 子句中聲明存儲過程將要返回結果集的數量。
•聲明游標,聲明時指定 WITH RETURN 子句。
•打開該游標,並使之保持 open 狀態,如果關閉該游標,則結果集將不能返回給調用者應用程序。
--返回一個結果集的游標的聲明
CREATE PROCEDURE emp_from_dept() DYNAMIC RESULT SETS 1 --返回的結果集超出定義的數量會返回一個警告
P1: BEGIN
DECLARE c_emp_dept CURSOR WITH RETURN
FOR SELECT empno, lastname, job, salary, comm. FROM employee WHERE workdept = ‘E21’;
OPEN c_emp_dept;
END P1
----------臨時表空間
•要使用臨時表,數據庫中必須存在一個用戶臨時表空間(默認情況下沒有),創建表空間:
create user temporary tablespace usertemp1
managed by system using ('usertemp1')
•可使用 DECLARE GLOBAL TEMPORARY TABLE 語句來定義臨時表。DB2的臨時表是基於會話的,且在會話之間是隔離的。
當會話結束時,臨時表的數據被刪除,臨時表被隱式卸下。對臨時表的定義不會在 SYSCAT.TABLES 中出現。
--NOT LOGGED:不記錄事務日志
動態表復制(CREATE TABLE AS&CREATE TABLE LIKE)
--CREATE TABLE AS:所有約束、注釋和序列都沒有被拷貝,但數據成功拷貝了
--CREATE TABLE LIKE:拷貝了所有NOT-NULL約束,並且沒有拷貝表數據
DECLARE GLOBAL TEMPORARY TABLE gbl_temp
LIKE empltabl --沒有拷貝數據
ON COMMIT DELETE ROWS
NOT LOGGED IN usr_tbsp
--------定義臨時表
/*
方法1:
ON COMMIT DELETE ROWS:在提交的時候清空數據,默認屬性
*/
DECLARE GLOBAL TEMPORARY TABLE 表名
( --參數列表
NAME VARCHAR(10),---姓名
DEPT SMALLINT,---部門
SALARY DEC(7,2)---工資
)
ON COMMIT DELETE ROWS;
/*
方法2:
1. ON COMMIT PRESERVE ROWS:在執行commit操作時,保留表中的所有行,一直到會話結束
2. LIKE 引用表名 INCLUDING COLUMN DEFAULTS WITH REPLACE:字段和類型引用其他表
*/
DECLARE GLOBAL TEMPORARY TABLE 表名
LIKE 引用表名 INCLUDING COLUMN DEFAULTS
WITH REPLACE
ON COMMIT PRESERVE ROWS;
/*
方法3:
DEFINITION ONLY WITH REPLACE:程序結束后自動刪除該臨時表
*/
DECLARE GLOBAL TEMPORARY TABLE 表名 AS
(
SELECT * FROM staff WHERE <condition>
)
DEFINITION ONLY WITH REPLACE;
-----------異常處理
begin(程序開始)前聲明異常 DECLARE handler-type HANDLER FOR SQLEXCEPTION\SQLWARNING\NOT FOUND ,
SQLEXCEPTION\SQLWARNING\NOT FOUND 為異常類型,
handler-type處理類型有以下幾種:
•UNDO 在處理器操作執行之前,DB2會回滾存儲過程中執行的SQL操作。在處理器操作完成之后,存儲過程會終止,並將控制返回給調用者
•EXIT 在處理器操作完成之后,存儲過程會終止,並將控制返回給調用者
•CONTINUE 在處理器操作完成之后,會繼續執行產生這個異常語句之后的下一條語句,
•需要注意的問題:
◦DB2存儲過程會在SQL執行完成后,將返回信息賦值給SQLCODE和SQLSTATE。這兩個DB2內置變量在使用前需要定義。
◦定義UNDO類型的異常處理,在定義后面可以跟上操作語句。
◦UNDO類型的異常處理,必須是處理原子操作的SQL塊,DB2默認不是原子操作的。在BEGIN跟上ATOMIC即可。
CREATE OR REPLACE PROCEDURE TEST (
IN num INTEGER,
OUT P_ERRORCODE VARCHAR(256), --SQL返回碼
OUT P_ERRORDESC VARCHAR(1024)) -- SQL返回信息
BEGIN ATOMIC
DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
-- 定義一個UNDO類型的異常處理
DECLARE UNDO HANDLER FOR SQLEXCEPTION set P_ERRORCODE = to_char(sqlcode), P_ERRORDESC = '處理失敗';
update userinfo t set t.usercode = '000000000003' where t.usercode='000000000002';
update userinfo t set t.usercode = '00000000000100' where t.usercode='000000000001'; --這里會因usercode字段超長出現異常
set P_ERRORCODE = to_char(abs(SQLCODE));
set P_ERRORDESC = '處理成功';
END;
SELECT
RTRIM( csz ) INTO v_sys_status--sd:復制表:要求目標表不存在,因為在插入時會自動創建。
FROM pas.xtb_xtcs
WHERE UPPER( csmc )= 'SYS_STATUS';
FETCH cur_jkwj INTO v_tablename,--sd:把數據放到變量里
v_filename,
v_extname;
--------------導入數據
load from 'd:\CSB_KM.del' of del replace into CSB_KM;
load from 'v_fileallname' of del insert into v_tablename nonrecoverable;
DEL:/*裝載數據文件的類型,大家用到比較多的應該是DEL,一般有4種,IXF,DEL,ASC,CURSOR
ASC 表示不分界的 ASCII 數據,數據的划分由位置決定。DEL 表示分界的 ASCII 數據,每行的數據長度可變。
分界的數據可以使用多種修飾符,主要的兩種是 COLDEL 和 CHARDEL;
COLDEL 決定列和列之間如何分界,CHARDEL 決定字符串數據如何分界*/
insert:/*DB2共有4個選項,其中INSERT為插入模式,相當於append(追加模式);
而REPLACE 為替換模式,可以理解為clear table then insert;
TERMINATE/RESTART,指定當 DB2 LOAD 由於任何原因未完成時,是停掉,還是重新load。*/
NONRECOVERABLE / COPY YES --以nonrecoverable模式還是以copy yes模式來load數據,一般來講用NONRECOVERABLE(也可以不寫)
runstats on table pas.jxdx_ckzh and index all;--sd:優化器:創建index后以及表有很大的變化后,最好執行該語句
---當文件名以.ixf結束時,使用import,其他的用load。。
import from 'd:\CSB_KM.ixf' of ixf modified by compound=100 commitcount 10000 insert into ,,;
SELECT * FROM SYSCAT.COLUMNS WHERE COLNAME='HYDH';--可以查看哪些表中用到了‘HYDH’字段
--DB2多行轉一行【XML方式】
--分組然后合並,然后去除XML標簽
SELECT replace(replace(replace(xml2clob(xmlagg(xmlelement(name A, 【字段】))),'</A><A>', '【分隔符】'),'</A>',''),'<A>','')
from 【表】
group by 【分組字段】
文件備份:
1.表結構備份
db2look -d 數據庫名 -i 用戶名 -w 密碼 -e -c -o f:/bjg/ycpas_tjrq.sql
2.單表備份
db2 "export to f:khdx_hy_tjrq.dat of del select * from khdx_hy"
3.全庫備份
db2 force application all--殺死進程(應該多執行幾次)
db2 backup db %DATA_BASE_NAME% to %BAKUP_TMP% PARALLELISM 2 COMPRESS
--%DATA_BASE_NAME%:數據庫名 %BAKUP_TMP%:保存的地址
