oracle實戰第六天--pl/sql介紹和基礎


第六天

內容介紹

1.pl/sql的介紹

2.pl/sql的基礎

 

期望目標

1.理解oracle的pl/sql概念

2.掌握pl/sql編程技術(包括編寫過程、函數、觸發器…)

 

Pl/sql的介紹

Pl/sql是什么?

Pl/sql(procedural language/sql)是oracle在標准的sql語言上的擴展。Pl/sql不僅允許嵌入sql語言,還可以定義變量和常量,允許使用條件語句和循環語句,允許使用例外處理各種錯誤,這樣使得它的功能變得更加強大。

 

為什么學?

學習的必要性:

1.提高應用程序的運行性能。

2.模塊化的設計思想。

3.減少網絡傳輸量。

4.提高安全性。

 

不好的地方:

1.移植性不好。

 

用什么編寫pl/sql

Sqlplus開發工具

Sqlplus開發工具是oracle公司提供的一個工具,這個因為我們在以前介紹過的:

舉一個簡單的案例:

編寫一個存儲過程,該過程可能向某表中添加記錄

create table mytest(
       name varchar2(30),
       passwd varchar2(30)
);

--創建一個存儲過程
create or replace procedure sp_addUser
(v_name varchar2,v_passwd varchar2)
is
begin
insert into mytest values(v_name,v_passwd);
end;

--查看錯誤
show error;

--調用存儲過程的兩種方式

exec sp_addUser('zhangsan','123');

call sp_addUser('lisi','123');

 

Pl/sql developer開發工具

Pl/sql developer是用於開發pl/sql塊的集成開發環境(ide),他是一個獨立的產品,而不是oracle的一個附帶品。

舉一個例子:

編寫一個存儲過程,該過程可以刪除某表記錄。

create procedure sp_delUser
(v_name varchar2)
is
begin
delete from mytest where name = v_name;
end;

 

 

Pl/sql基礎

開發人員使用pl/sql編寫應用模塊時,不僅需要掌握sql語句的編寫方法,還要掌握pl/sql語句及語法規則。Pl/sql編程可以使用變量和邏輯控制語句,從而可以編寫非常有用的功能模塊。比如:分頁存儲過程模塊、訂單處理存儲過程模塊、轉帳存儲過程模塊..而且如果使用pl/sql編程,我們可以輕松的完成非常復雜的查詢要求。

 

簡單分類

塊(編程):存儲過程、函數、觸發器、包。

 

編寫規范

1.注釋

單選注釋 --

Select * from emp where empno=7788;--取得員工信息

多行注釋

/*……*/來划分

 

2.標識符的命名規范

1)當定義變量時,建議用v_作為前綴v_sal

2)當定義常量時,建議用c_作為前綴 c_rate

3)當定義游標時,建議用_cursor作為后綴emp_cursor;

4)當定義例外時,建議用e_作為前綴e_error;

 

Pl/sql

塊(block)是pl/sql的基本程序單元,編寫pl/sql程序實際上就是編寫pl/sql塊。要完成相對簡單的應用功能,可能只需要編寫一個pl/sql塊;但是如果想實現復雜的功能,可能需要在一個pl/sql塊中嵌套其它的pl/sql塊。

 

Pl/sql塊的結構

pl/sql由三個部分組成:定義部分、執行部分、例外處理部分。

如下所示:

Declare

/*定義部分――定義常量、變量、游標、例外、復雜數據類型*/

Begin

/*執行部分――要執行的pl/sql語句和sql語句*/

Exception

/*例外處理部分――處理運行的各種錯誤*/

end;

 

特別說明:

定義部分是從declare開始的,該部分是可選的。

執行部分是從begin開始的,該部分是必須的。

例外處理部分是從exception開始的,該部分是可選的。

 

實例1――只包括執行部分的pl/sql

set serveroutput on;--打開輸出選項

begin
     dbms_output.put_line('Hello,World');
end;

 

相關說明:

Dbms_output是oralce所提供的包(類似java的開發包),該包包含一些過程,put_line就是dbms_output包的一個過程。

 

實例2――包含定義部分和執行部分的pl/sql

declare
     v_ename varchar2(5);--定義字符串變量
begin
     select ename into v_ename from emp
     where empno = &no;
     dbms_output.put_line('雇員名:'||v_ename);
end;

多個變量的例子:

declare
     v_ename varchar2(5);
     v_sal number(7,2);
begin
     select ename,sal into v_ename,v_sal from emp
     where empno = &no;
     dbms_output.put_line('雇員名:'||v_ename||' 薪水: '||v_sal);
end;

 

相關說明:

& 表示要接收從控制台輸入的變量

 

實例3――包含定義部分、執行部分和例外處理部分

         為了避免pl/sql程序的運行錯誤,提高pl/sql的健壯性,應該對可能的錯誤進行處理,這個很有必要:

1)比如在實例中,如果輸入了不存在的雇員號,應當做例外處理。

2)有時出現異常,希望用另外的邏輯處理

declare
     v_ename varchar2(5);
     v_sal number(7,2);
begin
     select ename,sal into v_ename,v_sal from emp
     where empno = &no;
     dbms_output.put_line('雇員名:'||v_ename||' 薪水: '||v_sal);
exception
     when no_data_found
     then dbms_output.put_line('您輸入的編號有誤!');    
end;

 

相關說明:

oracle事先預定義了一些例外,no_data_found就是找不到數據的例外。

 

過程

         過程用於執行特定的操作。當建立過程時,既可以指定輸入參數(in),也可以指定輸出參數(out)。通過在過程中使用輸入參數,可以將數據傳遞到執行部分;通過使用輸出參數,可以將執行部分的數據傳遞到應用環境。在sqlplus中可以使用create procedure命令來建立過程。

實例如下:

1)寫一個過程,可以輸入雇員名,新工資,可修改雇員的工資

create procedure sp_updateUser
(spName varchar2,newSal number)
is
--定義過程要使用的變量
begin
update emp set sal = newSal where ename = spName;
end;

2)如何調用過程有兩種方法

Exec sp_update(‘scott’,1350);

Call sp_update(‘scott’,1650);

3)如何在java程序中調用一個存儲過程

package com.anllin.jdbc.oracle;

 

import java.sql.*;

 

public class NoReturnValProc

{

    public static void main(String[] args)

    {

       Connection conn = null;

       CallableStatement stmt = null;

       try

       {

           Class.forName("oracle.jdbc.driver.OracleDriver");

           conn = DriverManager

                  .getConnection("jdbc:oracle:thin:@127.0.0.1:1521:myorcl",

                         "scott", "tiger");

           stmt = conn.prepareCall("{call sp_addBooks(?,?,?)}");

           stmt.setInt(1, 1);

           stmt.setString(2, "水是最好的葯");

           stmt.setString(3, "人民出版社");

           stmt.execute();

       }

       catch (Exception e)

       {

           throw new RuntimeException(e);

       }

       finally

       {

           try

           {

              if (null != stmt)

                  stmt.close();

              if (null != conn)

                  conn.close();

           }

           catch (Exception ex)

           {

              throw new RuntimeException(ex);

           }

       }

    }

}

 

 

特別說明:

對於過程我們會在后面做更詳細的說明,這里先簡單介紹一下。

 

函數

函數用於返回特定的數據,當建立函數時,在函數頭部必須包含return子句,而在函數體內必須包含return語句返回的數據,我們可以使用create function來建立函數,實際案例:

create function annual_income(name varchar2)
return number is
annual_salary number(7,2);
begin
select sal*12+nvl(comm,0) into annual_salary
from emp
where ename = name;
return annual_salary;
end;

 

在sqlplus中調用函數

var income number
call annual_income('SCOTT') into:income;
print income;

同樣我們可以在java程序中調用該函數

select annual_income('SCOTT') from dual;

可以通過rs.getInt(1)得到返回的結果。

 

包用於在邏輯上組合過程和函數,它由包規范和包體兩部分組成。

1)我們可以使用create package命令來創建包。

實例:

create package sp_package is
       procedure update_sal(name varchar2,newsal number);
       function annual_income(name varchar2) return number;
end;

 

包的規范只包含了過程和函數的說明,但是沒有過程和函數的實現代碼。包體用於實現規范中的過程和函數

 

2)建立包體可以使用create package body命令

create package body sp_package is
--implement procedure update_sal
procedure update_sal(name varchar2,newsal number)
is
begin
     update emp
     set sal=newsal
     where ename=name;
end;
--implement function annual_income
function annual_income(name varchar2)
return number is
annual_salary number;
begin
     select sal*12+nvl(comm,0) into annual_salary
     from emp
     where ename=name;
     return annual_salary;
end;
end;

 

3)如何調用包的過程或是函數

當調用包的過程或是函數時,在過程和函數前需要帶有包名,如果要訪問其它方案的包,還需要包名前加方案名。

如:

call sp_package.update_sal('SCOTT',1500);

 

特別說明:

包是pl/sql中非常重要的部分,我們在使用過程從頁時,將會再次體驗它的威力。

 

觸發器

觸發器是指隱含的執行的存儲過程。當定義觸發器時,必須要指定觸發的事件和觸發的操作,常用 的觸發事件包括insert,update,delete語句,而觸發操作實際就是一個pl/sql塊,可以使用create trigger來建立觸發器。

 

特別說明

我們會在后面詳細為大家介紹觸發器的使用,因為觸發器是非常有用的,可維護數據庫的安全和一致性。

 

定義並使用變量

介紹:

在編寫pl/sql程序時,可以定義變量和常量;在pl/sql包括有:

1)標量類型(scalar)

2)復合類型(composite)

3)參照類型(reference)

4)lob(large object)

 

標量――常用類型

在編寫pl/sql塊時,如果要使用變量,需在定義部分定義變量。

Pl/sql中定義變量和常量的語法如下:

Indentifier [constant] datatype [not null] [:=| default expr]

Identifier:名稱

Constant:指定常量。需要指定它的初始值,且其值是不能改變的

Datatype:數據類型

Not null:指定變量值不能為null

:= 給變量或是常量指定初始值。

Default 用於指定初始值。

Expr: 指定初始值的pl/sql表達式,可是文本值,其它變量,函數等。

 

標量定義的案例:

1)定義一個變長的字符串

v_ename varchar2(10);

2)定義一個小數范圍-9999.99~9999.99

v_sal number(6,2);

3)定義一個小數並給一個初始值為5.4 。:= 是pl/sql的賦值號

v_sal2 number(6,2) := 5.4;

4)定義一個日期類型的數據。

v_hiredate date;

5)定義一個布爾變量,不能為空,初始值為false

v_valid boolean not null default false;

 

標量――使用標量

在定義好變量后,就可以使用這些變量。這里需要說明的是pl/sql塊為變量賦值不同於其它的編程語言,需要在等號前加冒號(:=)

 

下面以輸入員工號,顯示雇員姓名,工資,個人所得稅(稅率為0.03)為例。說明變量的使用,看看如何編寫。

Set serveroutput on;

declare
c_tax_rate number(3,2) := 0.03;
v_ename varchar2(5);
v_sal number(7,2);
v_tax_sal number(7,2);
begin
select ename,sal into v_ename,v_sal from emp where empno=&no;
v_tax_sal := v_sal * c_tax_rate;
dbms_output.put_line('name:'||v_ename||'sal:'||v_sal||' tax_sal:'||v_tax_sal);
end;

 

標量――使用%type類型

對於上面的 pl/sql塊有一個問題:

就是如果員工的姓名超過了5個字符的話,就會有錯誤,為為降低pl/sql程序的維護工作量,可以使用%type屬性定義變量,這樣它會按照數據庫列來確定你定義的變量的類型和長度。

標識符號 表名.列名%type

Set serveroutput on;

declare
c_tax_rate number(3,2) := 0.03;
v_ename emp.ename%type;
v_sal emp.sal%type;
v_tax_sal number(7,2);
begin
select ename,sal into v_ename,v_sal from emp where empno=&no;
v_tax_sal := v_sal * c_tax_rate;
dbms_output.put_line('name:'||v_ename||'sal:'||v_sal||' tax_sal:'||v_tax_sal);

end;

 

復合變量(composite)--介紹

用於存放多個值的變量。主要包括這幾種:

1)pl/sql記錄

2)pl/sql表

3)嵌套表

4)varray

 

復合類型—pl/sql記錄

類似與高級語言中的結構體,需要注意的是,當引用pl/sql記錄成員時,必須加記錄變量作為前綴(記錄變量.記錄成員)如下:

declare
--declare record type
type emp_record_type is record(
     name emp.ename%type,
     salary emp.sal%type,
     title emp.job%type
);
--reference record type
sp_record emp_record_type;
begin
select ename,sal,job into sp_record
from emp
where empno=7788;
dbms_output.put_line('name: '||sp_record.name);
end;

 

復合類型—pl/sql

相當於高級語言中的數組,但是需要注意的是在高級語言中數組的下標不能為負數,而pl/sql是可以為負數的,並且表元素的下標沒有限制。實例如下:

declare
type sp_table_type is table of emp.ename%type
index by binary_integer;
sp_table sp_table_type;
begin
     select ename into sp_table(0)
     from emp
     where empno=7788;
     dbms_output.put_line('name : ' || sp_table(0));
end;

 

說明:

Sp_table_type 是pl/sql表類型

emp.ename%type 指定了表元素的類型和長度

sp_table 為pl/sql表變量

sp_table(0) 則表示下標為0的元素。

 

復合變量――嵌套表

 

復合變量――變長數組

 

參照變量

介紹

參照變量是指用於存放數值指針的變量。通過使用參照變量,可以使得應用程序共享相同對象,從而降低占用的空間。在編寫pl/sql程序時,可以使用游標變量(ref cursor)和對象類型變量(ref obj_type)兩種參照變量類型。

 

游標變量(ref cursor

使用游標時,當定義游標時不需要指定相應的select語句,但是當使用游標時(open時)需要指定select 語句,這樣一個游標就與一個select語句結合了。實例如下:

1)請使用pl/sql編寫一個塊,可以輸入部門號,並顯示該部門所有員工姓名和他的工資。

declare
type sp_emp_cursor is ref cursor;
sp_cursor sp_emp_cursor;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
  open sp_cursor
  for
  select ename,sal
  from emp
  where deptno=&no;
loop
  fetch sp_cursor into v_ename,v_sal;
  exit when sp_cursor%notfound;
  dbms_output.put_line('name: ' || v_ename || ' sal: ' || v_sal);
end loop;
end;

 

2)在1)的基礎上,如果某個員工的工資低於200元,就增加100元。

declare
type sp_emp_cursor is ref cursor;
sp_cursor sp_emp_cursor;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
  open sp_cursor
  for
  select ename,sal
  from emp
  where deptno=&no;
loop
  fetch sp_cursor into v_ename,v_sal;
  if
       v_sal<200
  then
       update emp set sal=sal+100
       where ename = v_ename;
  end if;
  exit
       when sp_cursor%notfound;
  dbms_output.put_line('name: ' || v_ename || ' sal: ' || v_sal);
end loop;
end;

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM