Académique Documents
Professionnel Documents
Culture Documents
11g
Password Complexity
SYS@sw11g> @$ORACLE_HOME/RDBMS/ADMIN/utlpwdmg.sql
SCOTT@sw11g> password Changing password for SCOTT Old password: New password: Retype new password: sagesage ERROR: ORA-28003: password verification for the specified password failed ORA-20006: Password too simple
Password unchanged
Thin
Fast
SCOTT@sw11g> create table T ( id number, value number ); Table created. SCOTT@sw11g> create sequence id_seq;
Sequence created.
SCOTT@sw11g> create or replace 2 trigger populate_id 3 before insert on T 4 for each row 5 begin 6 -- dbms_db_version.ver_le_10 7 -- select id_seq.nextval into from dual; 8 9 -- dbms_db_version.ver_le_11 10 :new.id := id_seq.nextval; 11 end; 12 / Trigger created.
This feature brings improved usability for the PL/SQL programmer and improved runtime performance and scalability.
SCOTT@sw11g> declare 2 n pls_integer; 3 begin 4 for i in 1 .. 50000 loop 5 select id_seq.nextval into n from dual; 6 end loop; 7 end; 8 / PL/SQL procedure successfully completed. Elapsed: 00:00:06.18
SCOTT@sw11g> declare 2 n pls_integer; 3 begin 4 for i in 1 .. 50000 loop 5 n := id_seq.nextval; 6 end loop; 7 end; 8 / PL/SQL procedure successfully completed. Elapsed: 00:00:06.68
alter session set sql_trace=true; variable n number begin for i in 1 .. 100 loop :n := scott.id_seq.nextval; end loop; end; / alter session set sql_trace=false;
call count ------- -----Parse 1 Execute 100 Fetch 100 ------- -----total 201
cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.01 0.03 0 0 0 0.00 0.05 0 0 5 -------- ---------- ---------- ---------- ---------0.01 0.09 0 0 5
SCOTT@sw11g> insert into T test2 2 select rownum, rownum from dual connect by level < 50000;
SCOTT@sw11g> drop trigger populate_id; Trigger dropped. SCOTT@sw11g> insert into T test2 2 select id_seq.nextval, rownum from dual connect by level < 50000; 49999 rows created. Elapsed: 00:00:00.71
create or replace trigger populate_id before insert on T for each row disable begin :new.id := id_seq.nextval; end; /
Compound triggers
CREATE OR REPLACE TRIGGER compound_trigger FOR UPDATE OF salary ON employees COMPOUND TRIGGER -- Declarative part (optional) -- Variables declared here have firing-statement duration. threshold CONSTANT SIMPLE_INTEGER := 200; BEFORE STATEMENT IS BEGIN NULL; END BEFORE STATEMENT; BEFORE EACH ROW IS BEGIN NULL; END BEFORE EACH ROW; AFTER EACH ROW IS BEGIN NULL; END AFTER EACH ROW; AFTER STATEMENT IS BEGIN NULL; END AFTER STATEMENT; END compound_trigger; / Trigger created.
To avoid the mutating-table error eg: A business rule states that an employee's salary increase must not exceed 10% of the average salary for the employee's department.
To accumulate rows destined for a second table so that you can periodically bulk-insert them
create table audit_emp (employee_id number(20) ,old_salary number(10) ,new_salary number(10) ,ts timestamp);
create or replace trigger old_way after update of salary on emp_large for each row begin insert into audit_emp values (:new.employee_id ,:old.salary ,:new.salary ,systimestamp); end old_way; /
create or replace trigger new_way for update of salary on emp_large compound trigger threshhold constant
create or replace trigger new_way for update of salary on emp_large simple_integer := 100; compound trigger threshhold constant simple_integer := 100; type audit_t is table of audit_emp%rowtype index by simple_integer; t_audit audit_t; ln_index simple_integer := 0;
type audit_t is table of audit_emp%rowtype index by simple_integer; t_audit audit_t; ln_index simple_integer := 0;
procedure flush_array is n constant SIMPLE_INTEGER := t_audit.count(); begin forall j in 1..n insert into audit_emp values t_audit(j); procedure flush_array is t_audit.delete(); n constant SIMPLE_INTEGER := t_audit.count(); begin ln_index := 0; forall j in 1..n end flush_array; insert into audit_emp values t_audit(j);
t_audit.delete(); ln_index := 0; end flush_array; after each row is begin ln_index := ln_index + 1; t_audit(ln_index).employee_id := t_audit(ln_index).old_salary := t_audit(ln_index).new_salary := t_audit(ln_index).ts := if ln_index >= threshhold then flush_array(); end if; end after each row;
after each row is begin ln_index := ln_index + 1; :new.employee_id; :old.salary; t_audit(ln_index).employee_id := :new.employee_id; :new.salary; systimestamp; t_audit(ln_index).old_salary := :old.salary; t_audit(ln_index).new_salary := :new.salary; t_audit(ln_index).ts := systimestamp; if ln_index >= threshhold then -- index >= 100 flush_array; end if; end after each row;
procedure flush_array is n constant SIMPLE_INTEGER := t_audit.count(); begin procedure flush_array is forall j in 1..n n constant SIMPLE_INTEGER := t_audit.count(); begin insert into audit_emp values t_audit(j); forall j in 1..n t_audit.delete(); insert into audit_emp values t_audit(j); t_audit.delete(); ln_index := 0; ln_index := 0; end flush_array; end flush_array;
create or replace trigger package_trigger after update of salary on employees for each row begin dbms_output.put_line('package_trigger'); end old_way; /
create or replace trigger custom_stuff after update of salary on employees for each row follows package_trigger begin dbms_output.put_line('custom_stuff'); end old_way; /
package_trigger custom_stuff
1 row updated.
create or replace function f(p1 in integer ,p2 in integer := 2 ,p3 in integer := null) return number is begin return nvl(p1,0) +nvl(p2,0) +nvl(p3,0); end; /
SAGE@sw11g> select f from dual; select f from dual * ERROR at line 1: ORA-06553: PLS-306: wrong number or types of arguments in call to 'F'
CONTINUE-WHEN
declare x number := 0; begin << my_loop >> loop -- after continue statement, control resumes here dbms_output.put_line ('Inside loop: x = ' || to_char(x)); x := x + 1; continue my_loop when x < 3; dbms_output.put_line ('Inside loop, after CONTINUE: x = ' || to_char(x)); exit when x = 5; end loop my_loop; dbms_output.put_line ('After loop: x = ' || to_char(x)); end; / Inside loop: Inside loop: Inside loop: Inside loop, Inside loop: Inside loop, Inside loop: Inside loop, After loop: x = 0 x = 1 x = 2 after CONTINUE: x = 3 after CONTINUE: x = 4 after CONTINUE: x = 5
x = 3 x = 4 x = 5
create or replace function factorial_interpreted(p_n number) return number is begin if (p_n = 1) then return 1; else return factorial_interpreted(p_n-1)*p_n; end if; end; /
create or replace function factorial_native(p_n number) return number is begin if (p_n = 1) then return 1; else return factorial_native(p_n-1)*p_n; end if; end; /
declare l_n number; begin for i in 1..500000 loop l_n := factorial_interpreted(50); end loop; end; / Elapsed: 00:00:14.85
declare l_n number; begin for i in 1..500000 loop l_n := factorial_native(50); end loop; end; / Elapsed: 00:00:10.26
HR@sw11g> update logons set user_id = upper(user_id); * ERROR at line 1: ORA-12081: update operation not allowed on table "HR"."LOGONS"
conn sage/sage SAGE@sw11g> select privilege from user_tab_privs where table_name = 'LOGONS';
PRIVILEGE -------------------UPDATE
1 row selected.
SAGE@sw11g> update hr.logons set user_id = upper(user_id) * ERROR at line 1: ORA-12081: update operation not allowed on table "HR"."LOGONS"
Virtual Columns
Formula/computed columns on the database Further constraints on the database New category for partitioning on the database Creative referential integrity on the database
Without Triggers - expensive Views sometimes forgotten Re-design too much hard work!
Pivot / Unpivot
DBA Stuff