1. Cấu trúc tuần tự
Thực hiện lần lượt từng lệnh một.
dbms_output.put_line('Excellent 1');
dbms_output.put_line('Excellent 2');
2. Cấu trúc rẽ nhánh
Rẽ nhánh không đầy đủ (if)
|
IF ename = 'SCOTT' THEN
beam_me_up := 'YES';
COMMIT;
|
Rẽ nhánh đầy đủ (if…else)
|
IF sales > (quota + 200) THEN
bonus := (sales - quota)/4;
ELSE
bonus := 50;
END IF;
----
IF monthly_value <= 4000 THEN
ILevel := 'Low Income';
ELSIF monthly_value > 4000 and monthly_value <= 7000 THEN
ILevel := 'Avg Income';
ELSIF monthly_value > 7000 and monthly_value <= 15000 THEN
ILevel := 'Moderate Income';
ELSE
ILevel := 'High Income';
END IF;
|
Case
|
CASE v_grade
WHEN 'A' THEN dbms_output.put_line('Excellent'); WHEN 'B' THEN dbms_output.put_line('Very Good'); WHEN 'C' THEN dbms_output.put_line('Good'); WHEN 'D' THEN dbms_output.put_line('Fair'); WHEN 'F' THEN dbms_output.put_line('Poor'); ELSE dbms_output.put_line('Error: No such grade'); END CASE |
SELECT TRANS_DATE,CASE
WHEN
TRIM(TO_CHAR(trans_date,'DAY')) IN ('SATURDAY','SUNDAY') THEN 'weekend'
ELSE 'weekday'
END "Day Type"
FROM transactions;
|
|
3. Cấu trúc lặp
·
LOOP không định trước
x := 0;
y := 1000;
LOOP
x := x + 1;
y := y - x;
EXIT x > y;
END LOOP;
|
|
·
Fetch 1 dòng dữ liệu dau tien từ cursor: (phải mở, đóng
cursor)
·
SET SERVEROUTPUT ON
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM
employees
WHERE department_id =30;
empno employees.employee_id%TYPE;
lname employees.last_name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO empno,
lname;
DBMS_OUTPUT.PUT_LINE(empno ||'
'||lname);
CLOSE emp_cursor;
END;
/
|
Con trỏ emp_cursor trả về 6
employees có department_id=30 nhưng câu lệnh FETCH sẽ lấy về chỉ 1 row, muốn
lấy tất cả các row thì phải dùng vòng lặp (for)
|
·
Fetch lấy all row từ cursor: LOOP...FETCH (phải
mở, đóng cursor)
DECLARE
-- Khai báo cursor để
truy vấn dữ liệu
CURSOR c_Emp IS
SELECT *
FROM emp
WHERE dept_id = 10;
-- Khai báo biến
cursor tương ứng để chứa dòng dữ liệu
v_Emp c_EMP%rowtype; -- v_Emp giống như kiểu record
BEGIN
-- Mở cursor
OPEN c_Emp;
LOOP
-- Lấy dòng dữ liệu từ
cursor
FETCH c_Emp INTO
v_Emp;
-- Thoát khỏi vòng lặp
nếu đã lấy hết dữ liệu trong cursor
EXIT WHEN
c_Emp%notfound;
-- Bổ sung dữ liệu vào
Emp_ext với dữ liệu lấy được từ cursor
INSERT INTO Emp_ext
(empno, ename, job) VALUES (v_Emp.empno, v_Emp.ename, v_Emp.job);
END LOOP;
-- Đóng cursor
CLOSE c_Emp;
END;
REM ===================================c
REM Grant on commit refresh system
privilege to the owner of on
REM commit refresh materialized
view which references tables
REM outside of the owner schema
REM ===================================
declare
owner varchar(30);
cursor c_mv_owner is
select distinct u.name
from sum$ s, sumdep$ d, obj$ o1, obj$
o2, user$ u
where s.obj# = d.sumobj# and
bitand(s.mflags, 65536) != 0 and
d.p_obj# = o1.obj# and
s.obj# = o2.obj# and
o1.owner# != o2.owner# and
o2.owner# = u.user#;
begin
open c_mv_owner;
loop
fetch c_mv_owner into owner;
exit when c_mv_owner%NOTFOUND;
execute immediate 'GRANT ON
COMMIT REFRESH TO ' ||
dbms_assert.enquote_name(owner, FALSE);
end loop;
close c_mv_owner;
end;
/
|
·
FOR-LOOP: Loop đã định trước
declare
cursor c1 is select distinct
tablespace_name from
dba_data_files where tablespace_name like 'DATA200%' or
tablespace_name like 'INDX200%' order by tablespace_name;
begin
for r1 in c1 loop
dbms_output.put_line('SQL '''||'alter
tablespace ' || r1.tablespace_name || ' read only'';');
dbms_output.put_line('SQL '''||'alter
tablespace ' || r1.tablespace_name || ' offline'';');
end loop;
end;
|
--
Switch all existing users to new temp tablespace.
BEGIN FOR cur_user IN (SELECT username FROM dba_users WHERE temporary_tablespace = 'TEMP') LOOP EXECUTE IMMEDIATE 'ALTER USER ' || cur_user.username || ' TEMPORARY TABLESPACE temp2'; END LOOP; END;
-- Không sử dụng
CURSOR
BEGIN
FOR
loop_emp IN
(SELECT *
FROM
employees
WHERE
salary>15000)
LOOP
dbms_output.put_line('Number
of rows processed: '||nvl(to_char(sql%rowcount),'Null'));
END LOOP
loop_emp;
END;
for r1 in (select trunc(completion_time) completion_time,
round(sum(blocks*block_size)/1024/1024/1024,2) as archived_log_gb from
V$ARCHIVED_LOG
where
trunc(completion_time) >= trunc(sysdate-7)
--and
trunc(completion_time)>= to_date(trunc(sysdate),'dd/mm/yyyy')
and dest_id=1
group by
trunc(completion_time)
order by
trunc(completion_time) desc) loop
tAll:=tAll||'<tr>
<td>'||r1.completion_time||'</td>
<td>'||r1.archived_log_gb||'</td>
</tr>' ;
end loop;
tAll:=tAll||
|
PROCEDURE auto_drop_partition (v_date DATE)
IS
date_num1 INT := 40; -- Chi luu giu 40
ngay, PROM_CHARGE_DAILY_HIS
date_num2 INT := 70; -- Chi luu giu 40
ngay, LOG_WS_999
date_num3 INT :=
180; -- Chi luu
giu 180 ngay, reg_sms_log
--date_num4 INT :=
300; --log dau
noi, Dungnd
CURSOR c_partition
IS
SELECT table_name, partition_name
FROM user_tab_partitions
WHERE (sysdate -
to_date(SUBSTR(partition_name,length(partition_name)-7,8),'yyyy/mm/dd') >
date_num1
AND table_name IN
('PROM_CHARGE_DAILY_HIS'))
OR
(sysdate - to_date(SUBSTR(partition_name,5,6),'yyyymm')
> date_num2
AND table_name IN
('LOG_PROCESS'))
OR
(sysdate -
to_date(SUBSTR(partition_name,length(partition_name)-7,8),'yyyy/mm/dd') >
date_num3
AND table_name IN
('CP_SUM_LOG'))
OR
(sysdate -
to_date(SUBSTR(partition_name,5,6),'yyyymm') > date_num3
AND table_name IN
('REG_SMS_LOG'))
OR
(sysdate -
to_date(SUBSTR(partition_name,length(partition_name)-7,8),'yyyy/mm/dd') >
365
AND table_name IN
('LOG_WS_999'))
OR
(sysdate -
to_date(SUBSTR(partition_name,length(partition_name)-7,8),'yyyy/mm/dd') >
365
AND table_name IN
('SEND_999_LOG','SUB_TRANSACTION_LOG')) ;
v_sql_command VARCHAR2 (2400);
BEGIN
-- add partitions
FOR v_data IN c_partition
LOOP
BEGIN
EXECUTE IMMEDIATE ' Alter table '
|| v_data.table_name
|| ' drop
partition '
||
v_data.partition_name;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line
(SQLERRM);
END;
END LOOP;
END;
|
-- Chạy cả khi exception
declare
cursor c1 is
SELECT a.INST_ID,count(1)
CountSession
FROM gv$session a, gv$process b
WHERE b.ADDR = a.paddr
AND a.inst_id=b.inst_id
and a.status='INACTIVE'
and A.USERNAME in ('NEIF_OWNER')
and prev_exec_start > sysdate
- 5/24*60
and type='USER'
group by a.inst_id;
cursor c2 is
SELECT 'ALTER SYSTEM KILL SESSION
'''||a.sid||','||a.serial#||',@'||a.inst_id||''' immediate' sqltext,
a.inst_id
FROM gv$session a, gv$process b
WHERE b.ADDR = a.paddr
AND a.inst_id=b.inst_id
and a.status='INACTIVE'
and A.USERNAME in ('USER1_OWNER')
and prev_exec_start > sysdate
- 5/24*60
and type='USER' order by
a.inst_id;
vInst varchar2(20);
vSession number;
begin
for r1 in c1 loop
begin
if r1.CountSession > 100 then
vInst:=r1.inst_id;
--dbms_output.put_line(vInst);
for r2 in c2 loop
begin
if r2.inst_id=vInst
then
dbms_output.put_Line(r2.sqltext);
execute immediate
r2.sqltext;
end if;
EXCEPTION
WHEN OTHERS
THEN
dbms_output.put_Line('Error
but CONTINUE');
CONTINUE;
end;
end loop;
end if;
end;
end loop;
insert into dba_tc_logs (id, content)
values (dba_tc_seq.nextval,'Complted to Kill NEIF_OWNER INACTIVE sesssions
after 5 minutes');
commit;
end; -- Tạo dữ liệu test create table t (name1 varchar2(100), name2 varchar2(100)); alter table t rename to spct; declare t number; begin for t in 1..20000 loop insert into spct values (Null,'a'); commit; end loop; end; / |
·
WHILE-LOOP
DECLARE
countryid
locations.country_id%TYPE := 'CA';
loc_id locations.location_id%TYPE;
new_city locations.city%TYPE :=
'Montreal';
counter NUMBER := 1;
BEGIN
SELECT MAX(location_id) INTO
loc_id FROM locations
WHERE country_id = countryid;
WHILE counter <= 3 LOOP
INSERT INTO locations(location_id,
city, country_id)
VALUES((loc_id + counter),
new_city, countryid);
counter := counter + 1;
END LOOP;
END;
/
|
Notes:
·
To exit a loop use the EXIT WHEN statement;
·
To skip to the next iteration of the loop, use
the CONTINUE WHEN statement (Oracle
11g and above).
·
Ngoài ra:
·
Goto:
goto the_end;
<<the_end>>
dbms_output.put_line ('The End.'); |