一、利用游標實現循環嵌套
在對oracle數據進行操作時我們會經常碰到循環甚至循環嵌套的情況。這個時候游標的作用就體現出來了。
DECLAREvId NUMBER(19);vDate DATE;--a表游標定義CURSOR a_cursor ISSELECT DISTINCT o.employeeId?FROM operations o?WHERE o.employeeId IS NULL?ORDER BY 1;--b表游標定義CURSOR b_cursor(eid number) ISSELECT DISTINCT trunc(o.startDate) startDateFROM operations o?WHERE o.employeeId = eid?AND o.employeeId IS NULLORDER BY 1;
BEGIN?FOR a_cur IN a_cursor LOOPvId := a_cur.receiverid;FOR b_cur IN b_cursor(vId) LOOPvDate := b_cur.startlifecycle;Employee_operationSettlement(vDate,vId);--做操作END LOOP;END LOOP;
END;
二、靈活使用%ROWTYPE
DECLARE ??V_employee employees%ROWTYPE?
BEGIN ??SELECT * INTO V_operationFROM employees e?WHERE e.code = '9999';--插入數據INSERT INTO employees (code,name,age)VALUES ('9998',V_operation.name,V_operation.age);--修改數據UPDATE employees tSET ROW = V_employeeWHERE e.code = '9999';
END;
三、根據主鍵表名查詢存在外鍵關聯的表名和字段名,并查詢指定主鍵值在外鍵表中關聯的數據條目
DECLAREVSql VARCHAR2(256);VCount NUMBER;CURSOR a_cursor isSELECT DISTINCT B.TABLE_NAME tableName,c.column_name columnNameFROM DBA_CONSTRAINTS A, DBA_CONSTRAINTS B, USER_CONS_COLUMNS C WHERE A.CONSTRAINT_NAME = B.R_CONSTRAINT_NAME AND B.CONSTRAINT_TYPE = 'R' AND a.TABLE_NAME = 'OPERATIONROLES'AND c.constraint_name = b.constraint_nameAND (instr(B.TABLE_NAME,'_')=0 OR instr(B.TABLE_NAME,'_CS')>0)--表名過濾條件(不包含‘_’,或包含‘_CS’)ORDER BY 1,2;
BEGIN FOR a_cur IN a_cursor LOOPVSql := 'SELECT count('||a_cur.columnName||') FROM '||a_cur.tableName||' WHERE '||a_cur.columnName||' = 40010';--指定值為(40010)EXECUTE IMMEDIATE VSql INTO VCount;IF VCount > 0 THEN --只看存在數據的條目DBMS_OUTPUT.put_line(VSql||'____'||VCount);--輸出(SQl____對應數據條數)END IF;END LOOP;
END;
四、遞歸查詢
--尋根
SELECT o.*?
FROM PartyRoleAssociations p,ORGANIZATIONUNITS o
WHERE p.partyroleid = o.id
AND LEVEL = 1 --層級
START WITH p.associationpartyroleid = '131000755'--開始子節點ID
CONNECT BY?p.associationpartyroleid = PRIOR p.partyroleid;---自頂向下
SELECT o.*?
FROM PartyRoleAssociations p,ORGANIZATIONUNITS o
WHERE p.associationpartyroleid = o.id
START WITH p.associationpartyroleid = '131000161'--父級節點ID
CONNECT BY PRIOR p.associationpartyroleid = p.partyroleid;
五、通過group by和wm_concat來快速定位數據
SELECT o.employeeId, wm_concat(o.name) --行列轉換
FROM operations o
GROUP BY o.employeeId;
六、依照模板數據快速插入數據,特別適用于表字段特別多的情況
DECLARE ??V_employee employees%ROWTYPE;CURSOR a_cursor IS SELECT * FROM employees;
BEGIN ??SELECT * INTO V_operationFROM employees e?WHERE e.code = '9999';--1INSERT INTO employees (code,name,age)VALUES ('9998',V_operation.name,V_operation.age);--2V_operation.code := '9997';V_operation.name := '張三';INSERT INTO employeesVALUES V_operation;--3FOR a_cur IN a_cursor LOOPIF a_cur.code = '9999' THENa_cur.code := '9996';a_cur.name := '李四';INSERT INTO employees?VALUES a_cur;END IF;END LOOP;--4INSERT INTO Employees(code, Name, age)SELECT '9995' code, --值,別名(可忽略)'王五' name,ageFROM Employees eWHERE e.code = '9999';
END;?
七、快速定位存儲過程
在項目開發中,經常遇到這樣的情況,現在需要改動一個表、函數或者存儲過程(簡稱為對象),但是不知道這個對象被哪些函數、定時任務或存儲過程調用,便可利用以下SQL解。
SELECT DISTINCT t.type "類型", t.name "名稱"
FROM User_Source t
WHERE t.type = 'PROCEDURE' --FUNCTION(函數),PROCEDURE(存儲過程),TRIGGER(觸發器)
AND LOWER(t.text) LIKE '%string%' --string英文小寫
UNION ALL
SELECT DISTINCT 'JOB' "類型", j.JOB_NAME "名稱" FROM user_scheduler_jobs j
WHERE LOWER(j.JOB_ACTION) LIKE '%string%';--查詢定時任務ACTION中是否包含
八、中斷ORACLE的JOB
網上查了一下,大多是通過dba_jobs_running去查SID,發現查不到,后來發現是可以通過dba_scheduler_running_jobs去查SID的
SELECT t.session_id SID FROM dba_scheduler_running_jobs t;
SELECT SID,SERIAL# FROM V$Session WHERE SID = '1018';
ALTER SYSTEM KILL SESSION '1018,127';
?