PL/SQL編程java
pl/sql(procedural language/sql)是Oracle在標準的sql語言上的擴展。pl/sql不只容許嵌入式sql語言,還能夠定義變量和常量,容許使用條件語句和循環語句,容許使用例外處理各類錯誤。這樣使得他的功能變的更強大。缺點是移植性很差。sql
編寫一個存儲過程,向表中添加數據。數據庫
begin編程
insert into mytest values ('小紅','m123');c#
end;數組
① exec xxc_pro1; 或者是安全
② call xxc_pro1;oracle
pl/sql能夠作什麼?ide
塊:包括過程、函數、觸發器、包。函數
編寫規範:
eg:select * from emp where empno=7788;--取得員工信息
/*……*/多行註釋
① 當定義變量時,建議用v_做爲前綴:v_ename
② 當定義常量時,建議用c_做爲前綴:c_rate
③ 當定義遊標時,建議用_cursor做爲後綴:emp_cursor
④ 當定義例外時,建議用e_做爲前綴:e_error
塊(block)是pl/sql的今本程序單元,編寫pl/sql程序實際上就是在編寫pl/sql塊;pl/sql塊由三部分組成:定義部分,執行部分,例外處理部分。
declare --可選部分
/*定義部分:定義常量,變量,遊標,例外,複雜數據類型*/
begin --必選部分
/*執行部分:要執行的pl/sql語句和sql語句*/
exception --可選部分
/*例外處理部分:處理運行的各類錯誤*/
實例1:只包含執行部分的pl/sql塊
SQL> set serveroutput on --打開輸出
SQL> begin
2 dbms_output.put_line('hello');
3 end;
4 /
說明:dbms_output是oracle提供的包,該包包含一些過程,put_line就是其中之一。
實例2:包含定義部分和執行部分
SQL> declare
2 v_ename varchar2(5);
3 begin
4 select ename into v_ename from emp where empno = &no;
5 dbms_output.put_line('僱員名'||v_ename);
6 end;
7 /
說明:&:從控制檯輸入變量,會彈出一個對話框。
實例3.同時輸出僱員名和工資
SQL> declare
2 v_ename varchar2(20);
3 v_sal number(10,2);
4 begin
5 select ename,sal into v_ename,v_sal from emp where empno=&no;
6 dbms_output.put_line('僱員名:'||v_ename||' 工資:'||v_sal);
7 end;
8 /
包含定義,執行,和例外處理的pl/sql塊。
實例4.當輸入的員工號不存在時
SQL> declare
2 v_ename varchar2(20);
3 v_sal number(10,2);
4 begin
5 select ename,sal into v_ename,v_sal from emp where empno =&no;
6 dbms_output.put_line('僱員名:'||v_ename||' 工資:'||v_sal);
7 exception --異常處理部分
8 when no_data_found then
9 dbms_output.put_line('請輸入正確的員工號!');
10 end;
11 /
以上爲塊的基礎,下面來介紹塊的各個組成:過程,函數,觸發器,包。
過程
過程用於執行特定的操做,當執行過程的時候,能夠指定輸入參數(in),也能夠指定輸出參數(out)。經過在過程當中使用輸入參數,能夠講數據輸入到執行部分,經過使用輸出參數,能夠將執行部分的數據輸出到應用環境,在pl/sql中可使用create procedure命令來建立過程。
編寫一個存儲過程,能夠輸入僱員名和新工資來改變員工工資。
--案例
create or replace procedure xxc_pro3(newname in varchar2,newsal in number) is
begin
update emp set sal=newsal where ename=newname;
end;
調用 exec xxc_pro3(‘SCOTT’,2900);[A1]
--in表示是輸入參數,能夠不寫,默認是in,但out必須寫。
在java程序中調用存儲過程來修改工資;
//演示java程序調用oracle中的存儲過程
package TestOraPro;//根據不一樣的包,包名不一樣
import java.sql.*;
public class TestOraPro {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
//加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲得鏈接 1521爲端口號
Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");
//建立callablestatement
CallableStatement cs=ct.prepareCall("{call xxc_pro3(?,?)}");
//給?賦值
cs.setString(1, "SMITH");
cs.setInt(2,2600);
//執行
cs.execute();
}catch(Exception e){
e.printStackTrace();
} finally{
//關閉資源
cs.close();
ct.close();
}
}
}
以上爲過程基礎,後會詳細講。
函數
函數用於返回特定的數據,當創建函數時,在函數頭部必須包含return子句,而在函數體內必須包含return語句來返回數據,可使用create function來創建函數。
案例1.返回工人年工資。
--函數案例
create or replace function xxc_fun1(newname varchar2)
return number is yearSal number(10,2);
begin
select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=newname;
return yearSal;
end;
在sqlplus中調用函數
sql>var income number;
sql>call xxc_fun1(‘SCOTT’) into: income;
sql>print income;
在java中調用函數
select xxc_fun1(‘SCOTT’) from dual;
這樣能夠經過rs.setInt(1)獲得返回結果。
包
包用於在邏輯上組合過程和函數,它由包規範和包體兩部分組成。
1.咱們能夠用create(or replace) package命令來建包;
實例:create package xxc_package is
Procedure update_sal (name varchar2,newsal number);
Function annual_sal(name varchar2) return number;
End;
包規只包含過程和函數的說明,可是沒有函數和過程的實現代碼。[A2]
包體用於實現包規範中的過程和函數。
2.創建包體能夠用create package body命令。
create package body xxc_package is
Procedure update_sal(name varchar2,newsal number) is
begin
update emp set sal=newsal where ename=name;
end;
function annual_sal(name varchar2) return number is
annual_salary number;
begin
select sal*12+nvl(comm,0)*12 into annual_salary from emp where ename=name;
return;
end;
end;
[A3] 3.如何調用包中的過程和函數。
在過程和函數前加上包名。
exec xxc_package.update_sal(‘SCOTT’,120);
觸發器
觸發器是指隱含的存儲過程,當定義觸發器是,必須指定觸發事件和觸發的操做,經常使用的觸發操做有insert、update和delete。觸發器操做其實是一個pl/sql塊,可使用create trigger命令來建立觸發器。由於觸發器內容不少,會在後面詳細介紹,觸發器是很是有用的,能夠用來維護數據庫的安全和一致性。
在編寫pl/sql塊時能夠定義的變量和常量;
標量類型(scalar)—經常使用類型
語法格式(即前邊最多見的格式)
變量名 [constant] datatype [not null] [:=/default expr]
expr:指定初始值的pl/sql表達式,能夠是文本,其餘變量,函數等。
定義標量案例
① 定義一個變長字符串
V_ename varchar2(10);
② 定義一個小數,範圍在-9999.99~9999.99
v_sal number(6,2);
③ 定義一個小數並賦初值 :=是pl/sql的賦值符號;
v_sal number(6,2):=12.3;
④ 定義一個日期類型數
v_birthday date;
⑤ 定義一個布爾類型變量,不能爲空,默認是false;
v_valid boolen not null default false;
[A4] 下面以輸入員工號,顯示員工姓名,工資,我的所得稅(稅率爲0.03)爲例,說明變量的使用。
declare
c_tax_rate number(3,2):=0.03;
v_ename varchar2(5);
v_sal number(10,2);
v_tax_sal number(10,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(‘員工名:’||v_ename||’工資:’||v_sal||’繳稅:’||v_tax_sal);
end;
對於上邊的pl/sql塊,有一個問題。
若是員工的名字長於5個字符,就會出現錯誤,爲了下降pl/sql的維護工做量,可使用%type屬性來定義變量,這樣它會按照數據庫列來肯定你定義的變量的類型和長度。
變量名 表名.列名%type
對於上例的改動
v_ename emp.ename%type;
v_sal emp.sal%type;
複合類型(composite)-介紹
用於存放多個值的變量,主要包括這幾種:
① pl/sql記錄;
② pl/sql表;
③ 嵌套表;
④ varray;
其中① ② 用的多,③ ④ 用的少。
1.pl/sql的記錄。
相似於高級語言的結構體,當引用pl/sql記錄成員的時候,必需要加記錄變量做爲前綴(記錄變量.記錄成員)。
如:declare
type emp_record_type is record(name emp.ename%type, salary emp.sal%type,title emp.job%type);[A5]
xxc_record emp_record_type;
begin
select ename,sal,job into xxc_record from emp where empno=&no;
dbms_output.put_line(‘員工名:’||xxc_record.name||’工資:’||xxc_record.salary);
end;
2.pl/sql表
至關於高級語言中的數組,須要注意的是高級語言中的數組的下標不能爲負,但表的下標沒有限制,能夠爲負。[A6]
例如:declare -- binary_integer表示下標是整數
type xxc_table_type is table of emp.ename%type index by binary_integer;
xxc_table xxc_table_type;
begin --下標0能夠是任何整數,-1,-2,23均可以,但輸出的時候也要是同一個數,否則會出錯。
select ename into xxc_table(0) from emp where empno=7788;
dbms_output.put_line(‘員工名:’||xxc_table(0));
end;
在這個實例中,若是把where子句去掉,就會出錯,由於你只請求了一個數據,而返回了多行數據。解決辦法是使用參照變量。
參照變量
參照變量是指用於存放數據指針的變量,經過使用參照變量可使得應用程序共享相同的對象,從而下降佔用的空間。在編寫pl/sql程序時,可使用遊標變量(ref cursor)和對象類型變量(ref obj_type)這兩種參照變量,用得多的是遊標變量。
遊標變量
定義遊標是,不須要指定select語句,但當使用遊標(open)時,須要指定select語句,這樣一個遊標就與一個遊標就與一個select語句結合了。
實例:① 編寫一個pl/sql塊,輸入部門號,顯示全部員工名和工資。
declare
type xxc_emp_cursor is ref cursor;
test_cursor xxc_emp_cursor;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open test_cursor for select ename,sal from emp where deptno=&no;
loop
fetch test_cursor into v_ename,v_sal;
exit when test_cursor%notfound;
dbms_output.put_line(‘名字:’||v_ename||’工資:’||v_sal);
end loop;
close test_cursor;
[A7] end;
② 在① 的基礎上,若是員工的工資低於2000,加100
declare
type xxc_emp_cursor is ref cursor;
test_cursor xxc_emp_cursor;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open test_cursor for select ename,sal from emp where deptno=&no;
loop
fetch test_cursor into v_ename,v_sal;
exit when test_cursor%notfound;
if v_sal<2000 then
update emp set sal=sal+100 where ename=v_ename;
v_sal=v_sal+100;
end if;
dbms_output.put_line(‘名字:’||v_ename||’工資:’||v_sal);
end loop;
close test_cursor;
end;
[A8] Pl/sql分支控制語句
1.條件分支語句
if…then if…then…else if…then…eslif…then…else…
當if語句結束時要有end if。
不等於號是<>,不是!=,
if job=’MANAGER’,是單引號,不是雙引號。
2.循環語句
--loop是pl/sql中最簡單的循環語句,這種循環以loop開始,以end loop結束,此循環至少會被執行一次。
例:編寫一個循環過程,可輸入用戶名,並循環添加10個用戶到user表中,用戶編號從1開始。
Sql>create table user(userid number(10),username varchar2(20));
Sql>create procedure xxc_insert_user1(name varchar2) is
declare
v_Num number:=1; --不用指定大小嗎?
begin
loop
insert into user values(v_num,name);
exit when v_num=10;[A9]
v_num:=v_num+1; --Oracle中沒有++符號
end loop;
end;
--while循環
當while條件爲真時,執行循環體。
以while…loop開頭,以end loop結尾。
例:上題,用戶號從11開始,添加10名用戶。
create procedure xxc_insert_user2(name varchar2) is
declare
v_Num number:=11; --不用指定大小嗎?
begin
while v_num<=20 loop
insert into user values(v_num,name);
v_num:=v_num+1;
end loop;
end;
--for循環
循環基本結構以下:
begin
for i in reverse 1..10 loop
insert into users(I,’小紅’);
end loop;
end;
順序控制語句 --goto,null
Goto語句會增長程序的複雜性,下降可讀性,通常不使用,但有時會很方便。
基本語法 goto lable ,lable是定義好了的標籤。
例:declare
i int:=1;
begin
loop
dbms_output.put_line(‘i=’||i);
if i=10 then
goto end_loop;
end if;
end loop;
<<end_loop>> --此爲標籤,注意格式
dbms_output.put_line(‘循環結束’);
end;
null語句不執行任何操做,好處是能夠提升程序的可讀性。
例:if sal<2000 then
update emp set sal=sal+100 where ename=name;
else
null;
編寫分頁過程
從易到難,先寫簡單的過程。
寫無返回值的過程,並被Java程序調用,前邊已寫過,再也不重寫。如今寫一個有返回值的過程,並用Java程序調用。
例:輸入員工號,輸出員工姓名。
Create procedure xxc_pro4 (empid in number,empname out varchar2) is
Begin
Select ename into empname from emp where empno = empid;
End;
Java程序調用。
import java.sql.*;
public class TestOraPro1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
//加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲得鏈接 1521爲端口號
Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");
//建立callablestatement
CallableStatement cs=ct.prepareCall("{call xxc_pro4(?,?)}");
//給第一個?賦值
cs.setInt(1,7788);
//給第二個?賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);
//執行
cs.execute();
//取出返回值,要注意?的順序,第幾個?是返回值就寫幾。
String name = cs.getString(2);
System.out.println(「7788的名字是」+name);
}catch(Exception e){
e.printStackTrace();
}finally{
//關閉資源
cs.close();
ct.close();
}
}
}
案例擴展:輸入一個員工號,輸出該員工的名字,工資和崗位。
create procedure xxc_pro5(empid in number,empname out varchar2,empsal out number,empjob out varchar2) is
begin
select ename,sal,job into empname,empsal,empjob from emp where empno=empid;
end;
Java調用
import java.sql.*;
public class TestOraPro1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
//加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲得鏈接 1521爲端口號
Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");
//建立callablestatement
CallableStatement cs=ct.prepareCall("{call xxc_pro4(?,?,?,?)}");
//給第一個?賦值
cs.setInt(1,7788);
//給後3個?賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);
cs.registerOutParameter(3,oracle.jdbc.OracleTypes.DOUBLE);
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);
//執行
cs.execute();
//取出返回值,要注意?的順序,第幾個?是返回值就寫幾。
String name = cs.getString(2);
String job = cs.getString(4);
System.out.println(「7788的名字是」+name+」 工做是」+job);
}catch(Exception e){
e.printStackTrace();
}finally{
//關閉資源
cs.close();
ct.close();
}
}
}
帶有返回值的存儲過程(結果集是個列表)。
案例:編寫個存儲過程,輸入部門號,輸出該部門的全部員工的信息。
分析以下:
因爲Oracle的存儲過程沒有返回值,它的全部返回值都是經過out參數來替代的,列表一樣也不例外,但因爲是個集合,因此不能用通常參數,必需要用package。因此分爲兩部分。
① 建立一個包,在包中定義一個test_package,是個遊標;
create package test_package as type test_cursor is ref cursor;
End test_package;
② 建立存儲過程
create procedure xxc_pro6(xxcno in number,xxc_cursor out test_package.test_cursor) is
begin
open xxc_cursor for select * from emp where deptno=xxcno;
end;
在Java中調用此存儲過程
import java.sql.*;
public class TestOraPro1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
//加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲得鏈接 1521爲oracle端口號
Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");
//建立callablestatement
CallableStatement cs=ct.prepareCall("{call xxc_pro6(?,?)}");
//給第一個?賦值
cs.setInt(1,10);
//給第二個?賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);
//執行
cs.execute();
//獲得結果集
ResultSet rs = (ResustSet)cs.getObject(2);
While(rs.next()){
System.out.println(rs.getInt(1)+」 」+rs.getString(2)+」 」+rs.getString(3));
}
}catch(Exception e){
e.printStackTrace();
}finally{
//關閉資源
cs.close();
ct.close();
}
}
}
開始編寫分頁過程。
例:請編寫一個存儲過程,要求能夠輸入表名、每頁顯示記錄數、當前頁,返回總記錄數、總頁數和返回的結果集。
如今先回顧一下分頁的語句,這是個模板。
select * from (select t1.*,rownum rn from (select * from emp) t1 where rownum<=10) where rn>=6;
① 建立一個包,在包中定義一個test_package2,是個遊標;
create package test_package2 as type test_cursor2 is ref cursor;
End test_package2;
② 建立存儲過程;
create procedure fenye is
(tablename in varchar2, --表名
rowsize in number, --每頁記錄數
pagenow in number, --當前頁
recordnum out number, --總記錄數
pagenum out number, --總頁數
set_cursor out test_package2.test_cursor2 --結果集的遊標
) is
v_sql varchar2(1000);
v_begin nuber:=(pagenow-1)*rowsize+1;
v_end nuber:=pagenow*rowsize;
begin
--v_sql是鏈接字符串,有點繞,看仔細
v_sql := 'SELECT * FROM (SELECT T.*,ROWNUM rn FROM (SELECT * FROM ' ||
TABLENAME || ' ) T WHERE ROWNUM <= ' || V_END ||
' ) WHERE rn >= ' || V_BEGIN;
--打開遊標,把遊標和sql語句結合起來
open set_cursor for v_sql;
--計算recordnum和pagenum
v_sql:= 'SELECT COUNT(*) FROM ' || TABLENAME;
execute immediate v_sql into recordnum;
if mod(recordnum,rowsize)=0 then
pagenum:=recordnum/rowsize;
else
pagenum:=recordnum/rowsize+1;
end if;
close set_cursor;
end;
用Java程序調用:
import java.sql.*;
public class TestOraPro1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
//加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//獲得鏈接 1521爲端口號
Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");
//建立callablestatement
CallableStatement cs=ct.prepareCall("{call fenye(?,?,?,?,?,?)}");
//給?賦值
cs.setString(1,」emp」);
cs.setInt(2,5);
cs.setInt(3,1);
//註冊總記錄數
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);
//註冊總頁數
cs.registerOutParameter(5,oracle.jdbc.OracleTypes.INTEGER);
//註冊結果集
cs.registerOutParameter(6,oracle.jdbc.OracleTypes.CURSOR);
//執行
cs.execute();
//取出返回值,要注意?的順序,第幾個?是返回值就寫幾。
int rnum=cs.getInt(4);
int pnum=cs.getInt(5);
ResultSet rs=(ResultSet)cs.getObject(6);
System.out.println(」記錄數是:」+rnum+」 總頁數是:」+pnum);
while(rs.next()){
System.out.println(」編號:」+rs.getInt(1)+」姓名:」+rs.getString(2));
}
}catch(Exception e){
e.printStackTrace();
}finally{
//關閉資源
cs.close();
ct.close();
}
}
}
例外處理
例外處理分爲預約義例外,其餘預約義例外和自定義例外。
案例:當輸入的僱員編號不存在時
declare
v_ename emp.ename%type;
begin
select ename into v_name from emp where empno=&no;
dbms_output.putline(’名字是:’||v_name);
exception
when no_data_found then
dbms_output.putline(’編號不存在!’);
end;
no_data_found就是一個預約義例外,在執行select語句時會出異常,但在執行update等語句時不會觸發該例外。
預約義例外是由pl/sql所提供的系統例外。當pl/sql違反Oracle的規定時就會隱含觸發一個內部例外。
經常使用的例外:
例:create or replace procedure xxc_pro7(no number) is
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno=no;
case
when v_sal<1000 then
update emp set sal=sal+200 where empno=no;
when 1000<=v_sal<2000 then
update emp set sal=sal+300 where empno=no;
end case;
exception
when case_no_found then
dbms_output.putline(’case中沒有和’||v_sal||’相匹配的條件’);
end;
declare
cursor emp_cursor is select ename,sal from emp;
begin
open emp_cursor;
for emp_record1 in emp_cursor loop
dbms_output.putline(emp_cursor.ename);
end loop;
exception
when cursor_already_open then
dbms_output.putline(’遊標已打開!’);
end;
3.dup_val_on_index例外
在惟一索引所對應的列上插入重複的值時,會隱含的觸發此例外。
begin
insert into dept values(10,’公關部’,’北京’);
exception
when dup_val_on_index then
dbms_output.putline(’在deptno列上不能有重複值!’);
end;
4.invaild_cursor
當試圖在不合法的遊標上執行操做時,就會觸發該例外。例如當試圖從沒有打開的遊標提取數據或是關閉沒有打開的遊標時,就會觸發。
declare
cursor emp_cursor is select ename,sal from emp;
emp_record emp_cursor%rowtype;
begin
--open emp_cursor; --打開遊標(但被註釋掉了)
fetch emp_cursor into emp_record;
dbms_output.putline(emp_cursor.ename);
close emp_cursor;
exception
when invalid_cursor then
dbms_output.putline(’請檢查遊標是否打開’);
end;
5.invalid_number例外
當輸入的數據有誤時,會觸發該例外。好比把100寫成1oo就會觸發。
begin
update emp set sal=sal+’1oo’;
exception
when invalid_number then
dbms_output.putline(’輸入的數字不正確!’);
end;
6.too_many_rows例外
當執行select into語句時,若是返回超過了一行,則會觸發該例外。
declare
v_ename emp.ename%type;
begin
select ename into v_ename from emp;
exception
when too_many_rows then
dbms_output.putline(’返回了多行!’);
end;
7.zero_divide例外 當2/0,即0作分母的時候觸發。
8.value_error例外
當在執行賦值操做時,若是變量的長度不足以容納實際數據,就會觸發該例外。
declare
v_ename varchar2(5);
begin
select ename into v_ename from emp where empno=&no;
dbms_output.putline(’名字是:’||v_ename);
exception
when value_error then
dbms_output.putline(’數據超出變量長度!’);
end;
其餘預約義例外。
自定義例外
預約義例外是和oracle的錯誤相關的,而自定義例外於oracle錯誤沒有任何關係,它是由開發人員爲特定的狀況所定義的例外。
例:編寫一個pl/sql塊,接收一個僱員號,並給該僱員的工資增長1000元,若是該僱員不存在,請提示。
create or replace procedure test_ex(no number) is
declare
myex exception; --定義一個例外
begin
update emp set sal=sal+1000 where empno=no;
if sql%notfound then -- sql%notfound表示沒有更新數據
raise myex; --觸發myex
end if;
exception
when myex then
dbms_output.putline(’未更新成功!’);
end;
視圖
視圖與表的區別
建立視圖
create view 視圖名 as select語句 [with read only];
例:建立視圖,把emp表的sal<1000的僱員映射到該視圖;
create view myview as select * from emp where sal<1000;
爲簡化操做,用視圖顯示員工編號,姓名和所在部門
create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;
建立或修改視圖
create or replace view 視圖名 as select語句 [with read only];
刪除視圖
drop view 視圖名;