1. 程式人生 > >Oracle動態sql,觸發器,函式,exists

Oracle動態sql,觸發器,函式,exists

1.動態SQL

後期聯編(late binding),即SQL語句只有在執行階段才能建立,例如當查詢條件為使用者輸入時,那麼Oracle的SQL引擎就無法在編譯期對該程式語句進行確定,只能在使用者輸入一定的查詢條件後才能提交給SQL引擎進行處理。

語法:
Excute immediate 動態SQL語句 into 輸出引數列表 using 繫結引數列表 ;
create or replace procedure proc(e_id emp.eid%type)
as
e_name emp.ename%type;
begin
execute immediate 'select ename from emp where eid=:1'
into e_name using e_id; dbms_output.put_line('名字為:' ||e_name); end;

2.觸發器

觸發器的定義就是說某個條件成立的時候,觸發器裡面所定義的語句就會被自動的執行。 因此觸發器不需要人為的去呼叫,也不能呼叫。 然後,觸發器的觸發條件其實在你定義的時候就已經設定好了。

語句級觸發器:某條語句執行前或後出發
行級觸發器:表中的行資料改變時就會觸發一次

語法結構:
create [or replace] trigger triggername (觸發時間)[before/after] 
觸發事件
on 表名
[for each row]--對錶的每一行觸發器執行一次。如果沒有這一選項,則只對整個表執行一次
begin
 pl/sql語句
end

CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.]table_name | [schema.]view_name 
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
PL/SQL_BLOCK | CALL procedure_name;
create or replace trigger mytrigger
  before insert or update or delete
  on emp
begin
  if(to_char(sysdate,'DY')='星期四') then
    raise_application_error(-20001,'b不能再星期四修改emp表資料');
  end if;
end;

error_number是範圍在-20000到-20999之間的負整數, error_message是最大長度為2048位元組的字串, keep_errors是一個可選的布林值,True表示新的錯誤將被新增到已經丟擲的錯誤列表中,False表示新的錯誤將替換當前的錯誤列表,預設為False。

3.函式

create or replace function get_salsum(dept_id number,total_count out number)
return number
as
	v_sumsal number(10) := 0;
//定義遊標,進行迴圈疊加
cursor salary_cursor is select salary from employees where department_id = dept_id;
begin
	total_count := 0;

	for c in salary_cursor loop
   		v_sumsal := v_sumsal +c.salary;
  		total_count := total_count + 1;
	end loop;
	return v_sumsal;
end;

呼叫:
dbms_output.put_line(get_salsum(80,v_num));
dbms_output.put_line(v_num);

4.sql優化問題–exists

exists 存在,返回值是true not exists 不存在,返回值是false

select sysdate from dual where (select count(*) from emp where eid='1001')=1;

select sysdate from dual where not exists(select * from emp where eid='1005');
1. in()適合B表比A表資料小的情況

2. exists()適合B表比A表資料大的情況

3.當A表資料與B表資料一樣大時,in與exists效率差不多,可任選一個使用.
select * from A
where id in(select id from B)

select a.* from A a 
where exists(select 1 from B b where a.id=b.id)

minus 取得差集 intersect 取得交集 union 取得並集 union all 不過濾重複的部分