2014-04-13sql
1.pl/sql分匿名塊和命名塊數據庫
匿名塊語法:oracle
DECLAREide
declaration statements函數
BEGINoop
executable statments指針
EXCEPTIONserver
exception-handing statments ---異常處理內存
END;ci
命名塊:存儲過程,函數,觸發器,包等。
2.pl/sql語句塊分三部分:
1)聲明部分:
2)可執行部分:
3)異常處理部分:
其中可執行部分是語句塊中惟一要求必須存在的部分,聲明部分和異常處理部分是可選的。
3.聲明變量
1)語法:
identifier [CONSTANT] datatype [NOT NULL] [:=value |DEFAULT expr];
2)示例一
declare
v_first_name varchar2(50);
c_count constant number :=0; ----常量
v_hiredate date;
v_vaild BOLLEAN NOT NULL DEFAULT TRUE;
//顯示僱員的姓名,工資,我的所得稅
set serveroutput on;
declare
v_ename varchar2(20);
v_sal number(6,2);
v_tax_rate constant number(3,2) :=0.06; ---稅率
v_tax_sal number(6,2);
begin
select ename,sal into v_ename,v_sal from emp where empno = &no;
v_tax_sal := v_sal * v_tax_rate; ---賦值
dbms_output.put_line('v_ename: ' || v_ename);
dbms_output.put_line('v_sal: ' || v_sal);
dbms_output.put_line('v_tax_sal: ' || v_tax_sal);
end;
3)示例二(和一聲明變量方法不同)
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
v_tax_rate constant number(3,2) :=0.06; ---稅率
v_tax_sal number(6,2);
begin
select ename,sal into v_ename,v_sal from emp where empno = &no;
v_tax_sal := v_sal * v_tax_rate; ---賦值
dbms_output.put_line('v_ename: ' || v_ename);
dbms_output.put_line('v_sal: ' || v_sal);
dbms_output.put_line('v_tax_sal: ' || v_tax_sal);
end;
4.標識符的命名規則
1)定義變量,建議用v_,如v_ename
2)定義常量,建議用c_,如c_tax_rate
3)定義遊標,建議使用_cursor做爲後綴,如emp_cursor
4)定義表類型,建議使用_table_type做爲後綴,如sal_table_type
5)定義表變量,建議使用_table做爲後綴,如sal_table
5.PL/SQL編譯過程步驟
編譯過程包括語法檢查,綁定以及僞代碼生成。語法檢查涉及檢查PL/SQL代碼中的編譯錯誤。在糾正語法錯誤以後,會給每一個變量分配內存地址,以保存ORACLE數據,這個過程稱爲綁定。接下來,會產生PL/SQL語句塊的僞代碼,僞代碼是PL/SQL引擎的指令列表,對於命名語句塊,僞代碼會存儲在數據庫中,並在程序下一次執行時使用。
6.替代變量
在匿名PL/SQL塊中接受輸入參數使用&或者&&做爲替代變量
7.初始化變量用select into 語法
//求emp表中的平均工資
set serveroutput on;
declare
v_sal number(6,2);
begin
select avg(sal) into v_sal from emp;
dbms_output.put_line('v_sal: ' || v_sal);
end;
##在sqlplus中執行最後要加/。
8.if 語句
1)if 語法:
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;
]
END IF;
2)示例:
//若是工資小於2000,把僱員的薪水加50
set serveroutput on;
DECLARE
v_sal emp.sal%TYPE;
BEGIN
SELECT sal into v_sal FROM emp where lower(ename)=lower('&name');
if v_sal<2000 then
update emp set sal=sal+50 where lower(ename)=lower('&name');
end if;
dbms_output.put_line('v_sal: ' || v_sal);
END;
##驗證
SELECT * from emp where sal<2000;
//若是job=PRESIDENT,sal=sal+200;job=MANAGER ,sal=sal+1000;other ,sal=sal+100
&empno
set serveroutput on;
DECLARE
v_sal EMP.SAL%type;
v_job EMP.JOB%type;
v_empno EMP.EMPNO%TYPE;
BEGIN
SELECT job,sal,empno into v_job,v_sal,v_empno FROM emp where empno=&no;
if v_job='PRESIDENT' then
update emp set sal=sal+200 where empno=v_empno;
elsif v_job='MANAGER' then
update emp set sal=sal+1000 where empno=v_empno;
else
update emp set sal=sal+100 where empno=v_empno;
end if;
DBMS_OUTPUT.PUT_LINE('v_job: '|| v_job);
DBMS_OUTPUT.PUT_LINE('v_sal:' || v_sal);
COMMIT;
END;
ROLLBACK; --回滾
##驗證
SELECT * from emp where empno=7566;
9.循環語句
1)loop循環
loop
statements;
exit [when condition];
end loop;
//示例
create table tmp01 (id int);
declare i int :=1;
begin
loop
insert into tmp01 values(i);
commit;
exit when i>100;
i :=i+1;
end loop;
end;
select * from tmp01;
2)while 循環
while condition loop
statement1;
statement2;
..........
end loop;
//示例
create table tmp01 (id int);
declare i int :=1;
begin
while i<=100 loop
insert into tmp01 values(i);
i :=i+1;
end loop;
commit; ----批量提交
end;
select * from tmp01;
3)for 循環
for counter in [reverse] lower_bound .. upper_bound loop
statement1;
statement2;
........
end loop;
##counter變量不須要定義
//示例
drop table tmp01 purge;
create table tmp01 (id int);
begin
for i in 1..100 loop
insert into tmp01 values(i);
end loop;
commit;
end;
select * from tmp01;
4)case
//用替代變量輸入部門號,使用case語句判斷條件更新僱員工資
部門號爲10,僱員加薪10%
部門號爲20,僱員加薪8%
部門號爲30,僱員加薪15%
若是輸入其餘數字,則顯示「該部門不存在」
set serveroutput on;
DECLARE
v_deptno emp.deptno%type;
begin
v_deptno :=&deptno;
case
when v_deptno=10 then
update emp set sal=sal*1.1 where deptno=v_deptno;
when v_deptno=20 then
update emp set sal=sal*1.08 where deptno=v_deptno;
when v_deptno=30 then
update emp set sal=sal*1.15 where deptno=v_deptno;
else
dbms_output.put_line('no such department');
end case;
end;
10.SQL遊標
當執行select,insert,update,delete 時oracle會爲SQL語句分配相應的上下文區(context area).oracle使用上下區解析並執行相應的SQL語句,而遊標就是指向上下文區的指針。
遊標包括隱式遊標和顯示遊標。其中隱式遊標也稱爲SQL遊標,專門用於處理select into,insert,update,delete語句。顯示遊標用於處理多行select語句。
SQL遊標屬性:sql%found,sql%notfound,sql%rowcount,sql%isopen等
1)sql%isopen:用於肯定SQL遊標是否打開。
2)sql%found/sql%notfound:用於肯定SQL語句是否執行成功。
set serveroutput on;
declare
v_deptno emp.deptno%type := &no;
begin
update emp set sal = sal*1.05 where deptno=v_deptno;
if sql%notfound then
dbms_output.put_line('deptno is not exist.');
else
dbms_output.put_line('sql execute successful.');
end if;
end;
3)sql%rowcount:用於返回sql語句所做用的總計行數。
set serveroutput on;
declare
v_deptno emp.deptno%type := &no;
begin
update emp set sal = nvl(sal,0)*1.05 where deptno=v_deptno;
dbms_output.put_line('have '|| sql%rowcount || ' row changed.');
if sql%notfound then
dbms_output.put_line('deptno is not exist.');
else
dbms_output.put_line('sql execute successful.');
end if;
end;
4)案例
用替代變量輸入客戶名(不區分大小寫)和所在城市,並修改客戶所在城市,若是客戶不在,則顯示「該客戶不在」
##建立表
create table customer(customer_id number not null,customer_name varchar2(50),
city_name varchar2(50),constraint pk_customer primary key(customer_id));
##插入數據
insert into customer values(1,'yangry','henan');
insert into customer values(2,'lisn','shangqiu');
insert into customer values(3,'lij','nanyang');
insert into customer values(4,'guoyf','luoyang');
set serveroutput on;
declare
v_uname CUSTOMER.CUSTOMER_NAME%TYPE;
v_cname CUSTOMER.CITY_NAME%TYPE;
begin
v_uname :='&uname';
v_cname :='&cname';
update customer set city_name=v_cname where upper(customer_name)=upper(v_uname);
if sql%notfound then
dbms_output.put_line('the customer is not exist');
end if;
commit;
end;
//另外一種聲明變量的方法
v_uname CUSTOMER.CUSTOMER_NAME%TYPE :='&uname';
v_cname CUSTOMER.CITY_NAME%TYPE :='&cname';
//begin後也可修改成:
select customer_name into v_uname from customer where upper(customer_name) = '&uname';
v_cname :='&cname';--此句不能用select的緣由跟下面的set語句有關。