1. 程式人生 > >Oracle中的DDL,DML,DCL總結

Oracle中的DDL,DML,DCL總結

不能 ces star n-1 jdb rec 自動 庫服務器 word

轉自http://blog.csdn.net/w183705952/article/details/7354974

DML(Data Manipulation Language,數據操作語言):用於檢索或者修改數據。
DML包括: SELECT:用於檢索數據;
INSERT:用於增加數據到數據庫;
UPDATE:用於從數據庫中修改現存的數據
DELETE:用於從數據庫中刪除數據。

DDL(Data Definition Language,數據定義語言): 用於定義數據的結構,比如 創建、修改或者刪除數據庫對象。
DDL包括:DDL語句可以用於創建用戶和重建數據庫對象。下面是DDL命令:
CREATE TABLE:創建表
ALTER TABLE
DROP TABLE:刪除表
CREATE INDEX
DROP INDEX

DCL(Data Control Language,數據控制語言):用於定義數據庫用戶的權限。
DCL包括:
ALTER PASSWORD
GRANT
REVOKE
CREATE SYNONYM

一:DCL(數據控制語言)
1、創建用戶test2,密碼也是test2(記得最有以分;號結束):
create user test2 identified by test2;
2、給test2授權:create session;(允許用戶登陸Oracle):
grant create session to test2;
3、給test2分配創建表的權限;
grant create table to test2;
4、給test2分配表空間的使用權限;
grant unlimited tablespace to test2;

二:DDL(數據定義語言練習)
1、創建表:SQL> create table t_user(
userid number(30) not null primary key,
username varchar(20) not null,
age number(3),
sex varchar(2),
departid number(30) not null,
foreign key(departid) references t_depart(departid)
);
★alter table student add primary key(userid)這樣用alter也可以創建關聯主外鍵。

2、刪除表:SQL> drop table t_depart;

3、創建序列:
create sequence seq_a minvalue 1000 maxvalue 99999999 start with 1000 increment by 1 nocache;

三:DML(數據操作語言):
1、insert插入SQL:
(1)insert into t_depart (departid,departname,createdate)
values (1,‘市場部‘,sysdate);
(2)insert into t_user values (seq_user.nextval,‘馬文濤‘,23,‘男‘);

2、delete刪除SQL:
(1)delete t_user;(太可怕了,如果在刪除時不加條件,則把此表中的所有數據都會刪除!)
(2)delete t_user where userid = 3;

3、update更新SQL:
(1) update t_user set username = ‘爭偉‘,sex = ‘男‘;
(太恐怖了,更新時不加條件表中所有行記錄的姓名都被修改了!)
(2)update t_user set username = ‘文濤‘ where userid = 7;
★小結:我發現在增、刪、改的SQL語句中用不到from關鍵字。

4、select查詢SQL:格式——>select···from···where···group by···having···order by···;
(1)查詢所有的用戶:select * from t_user;
★在oracle中這裏的表明用別名時不能加as關鍵字
如: select * from t_user u;正確
select * from t_user as u;錯誤

(2)查詢指定的列: select username,sex from t_user;

(3)as給列以別名顯示:select username as 用戶名 from t_user;(這裏的as關鍵字可以省略)

(4)distinct去掉重復的行:select distinct username from t_user;

(5)使用運算符:select age+10 from t_user;(給每個人的年齡都加10歲)

(6)連接字符串: select ‘用戶名:‘ || username from t_user;(Oracle用||做連接字符串操作符)

(7)where子句:select * from t_user where username = ‘寶寶‘;

(8)between and在···之間:
select * from t_user where userid between 9 and 10;這也等價於下面這條SQL:
select * from t_user where userid >=9 and userid <=10;

(9)in匹配集合中的任意值:select * from t_user where username in(‘馬文濤‘,‘寶寶‘);

(10)like模糊查詢:%匹配0個或多個任意字符串,_匹配1個任意字符串。

select * from t_user where username like ‘%濤%‘;

(11)null判斷某列為空:select * from t_user where sex is null;
(這裏用is,不能用=,如果要返回不為null的記錄就可以用is not null)

(12)order by排序:ASC: 升序排列(可以省略),DESC: 降序排列
升序:select u.userid,u.username from t_user u order by u.userid;
降序:select u.userid,u.username from t_user u order by u.userid desc;

(13)系統函數(對一組數據進行處理,返回一個值):
AVG–求平均值,COUNT–統計記錄數,MAX–最大值,MIN–最小值,SUM–求和
<1>返回最小和最大的用戶編號: select min(userid),max(userid) from t_user;
<2>返回總記錄數: select count(*) from t_user;
<3>返回某個字段不為空的記錄數: select count(sex) from t_user;
<4>返回不為空且不重復的記錄數: select count(distinct sex) from t_user;

(14)group by分組(分組了就不能直接返回*,經常和聚合函數count(age)一起使用):
<1>按姓名分組,並統計每組人數:select count(*),username from t_user group by username;
<2>根據多個字段分組: select username,age,count(*) from t_user group by username,age;
◆group by有一個原則,就是 select 後面的所有列中,沒有使用聚合函數的列,必須出現在 group by 後面。

(15)having過濾分組:select username from t_user group by username having count(*) > 2;

(16)子查詢(子查詢自身只能返回一個單獨的值):
<1>子查詢放在select後面,作為其中的一個字段返回。
select u.username,(select d.departname from t_depart d where d.departid = u.departid) from t_user u;
(返回用戶和所屬的部門,這中子查詢理論上先執行外面的查詢,只是我的感覺哦,嘿嘿!)
<2>子查詢放在from後面,作為一張臨時表。
select * from (select username,sex s from t_user where departid=1)
where s = ‘男‘;
(這種子查詢應該先執行裏面)
<3>子查詢放在where後面,作為條件的一部分。
select * from t_user where departid = (select departid from t_depart where departname = ‘財務部‘);
(這種子查詢也應該先執行裏面)

(17)聯合查詢(當n張表連接時, 需要n-1個連接條件):
<1>等值連接(內連接):select u.username,d.departname from t_user u,t_depart d
where u.departid = d.departid;
<2>外連接:即把不滿足條件的記錄也返回,用個+就行了,
(+)操作符在哪邊就代表另外一邊不滿足聯合條件的記錄可以被輸出。這個感覺不太常用。
select b.book_id,b.book_name from book_info as b,book_click_num as c
where b.book_id = c.book_id(+);


四、觸發器trigger:當特定事件發生時自動執行的代碼塊。
這些事件包括:
(1)DML語句(INSERT,UPDATE,DELETE):before在DML語句被執行前觸發操作,after在DML語句被執行後觸發操作。
(2)DDL語句(CREATE 及 ALTER)
(3)系統事件,例如啟動/關閉[startup/shutdown]、錯誤[error]
(4)用戶事件, 例如登錄/退出[logon/logoff]
★兩個特殊的變量——>:new新的記錄值,:old保留原來的記錄值
簡單示例:create or replace trigger update_depart_trigger
after update on t_depart for each row
begin update t_user u set u.departid = :new.departid
where u.departid = :old.departid;
end update_depart_trigger;
此示例的作用:當部門的id改變後,由於用戶中有外鍵引用了部門,所以用戶的departid這個外鍵自動執行更新操作。
(這個觸發器很奇怪,在黑窗口用sqlplus就不能創建,用plsql Developer工具就可以創建,很有意思,嘿嘿!)

五、遊標cursor:以循環取SQL語句的SELECT內容,它是存放結果集的數據對象,使用遊標,我們只能逐條記錄地得到查詢結果。
作用:查詢數據庫,獲取記錄集合(結果集)的指針,可以讓開發者一次訪問一行結果集,在每條結果集上作操作。
使用:用遊標有四種基本的步驟:聲明遊標(declare)、打開遊標(open)、提取數據(fetch)、關閉遊標(close)。
★當你要往每一行插入一個數據只能用遊標,或者更新結果集中的每行記錄時也可用遊標,用存儲過程返回一個結果集。
★觸發器和存儲過程會和數據庫綁定,即一直保存在數據庫中,而遊標不會,它是任意時刻創建再打開再執行再關閉,
與數據庫沒有任何直接關系。
★在Oracle中,不需要顯示銷毀遊標.因為在Oracle中,很多東西是由JAVA寫的.Oracle會自動銷毀遊標。

簡單示例:
-- 定義一個遊標
declare
cursor cursor_user
is
select username,age
from t_user;
//變量的定義也可以放到遊標定義上面
a t_user.username%type;//定義個a變量,類型是t_user表中username列的類型。
b t_user.age%type;//同上
begin//SQL中可執行代碼都在begin和end之間。
-- 打開遊標
open cursor_user;

-- 遍歷遊標
loop//循環抓取數據(loop是其中一種循環方式)
fetch cursor_user into a,b; -- 將一行記錄放入到變量中
dbms_output.put_line(a || ‘ ‘ || b);打印到輸出控制臺
exit when cursor_user%notfound; -- 當沒有記錄時退出循環
end loop;//退出循環
-- 關閉遊標
close cursor_user;
end;

加if條件判斷遊標示例:
declare
cursor cursor_user
is
select username,age
from t_user;
a t_user.username%type;
b t_user.age%type;
begin
open cursor_user;
loop
fetch cursor_user into a,b;
if a=‘寶寶‘and b=43 then
dbms_output.put_line(a || ‘ ‘ || b);
end if;
exit when cursor_user%notfound;
end loop;
close cursor_user;
end;



六、存儲過程procedure
概念:其實就是一組存放在數據庫中SQL語句,普通SQL操作都在項目中寫死的,而他只跟數據庫進行綁定。
更準確的說存儲過程是數據庫服務器端的一段程序,它有兩種類型。一種類似於SELECT查詢,用於檢索數據,檢索到的數據能夠以數據集的形式返回給客戶(oracle存儲過程本身沒返回值,只是用out參數代替)。另一種類似於INSERT或DELETE查詢,它不返回數據,只是執行一個動作。有的服務器允許同一個存儲過程既可以返回數據又可以執行動作。

優點:
1、提高效率。存儲過程本身的執行速度非常快,而且,調用存儲過程可以大大減少同數據庫的交互次數。
2、提高安全性。假如將SQL語句混合在JSP代碼中,代碼外漏以後,也就意味著庫結構外漏。
3、有利於SQL語句的重用。
★oracle函數有返回值,但存儲過程沒有返回值,它的所有返回值都是通過out參數來替代的。
★什麽時候需要用存儲過程
  如果服務器定義了存儲過程,應當根據需要決定是否要用存儲過程。存儲過程通常是一些經常要執行的任務,這些任務往往是針對大量的記錄而進行的。在服務器上執行存儲過程,可以改善應用程序的性能。這是因為:
.服務器往往具有強大的計算能力和速度。
.避免把大量的數據下載到客戶端,減少網絡上的傳輸量。
  例如,假設一個應用程序需要計算一個數據,這個數據需要涉及到許多記錄。如果不使用存儲過程的話,把這些數據下載到客戶端,導致網絡上的流量劇增。
不僅如此,客戶端可能是一臺老掉牙的計算機,它的運算速度很慢。而改用存儲過程後,服務器會很快地把數據計算出來,並且只需傳遞一個數據給客戶端,其效率之高是非常明顯的。


★存儲過程的參數
  要執行服務器上的存儲過程,往往要傳遞一些參數。這些參數分為四種類型:
  第一種稱為輸入參數(in),由客戶程序向存儲過程傳遞值。
  第二種稱為輸出參數(out),由存儲過程向客戶程序返回結果。
  第三種稱為輸入/輸出參數(in out),既可以由客戶程序向存儲過程傳遞值,也可以由存儲過程向客戶程序返回結果。
  第四種稱為狀態參數,由存儲過程向客戶程序返回錯誤信息。
要說明的是,並不是所有的服務器都支持上述四種類型的參數,例如,InterBase就不支持狀態參數。


簡單示例:
1、無返回值存儲過程(插入一個用戶)
create or replace procedure saveuser
( username in varchar2 ,
age in number,
departid in number
//定義兩個輸入參數,參數類型可以是自己寫死,也可以用某個列的類型
比如:username t_user.username%type;
) as
begin
insert into t_user (userid,username,age,departid) values (seq_user.nextval,username, age,departid);
end saveuser;
(1)在sql中執行存儲過程call saveuser(‘文濤‘,23,1);,也可以用execute和exec。

(2)在java裏調用時就用下面的代碼:
package com.hyq.src;

import java.sql.*;
import java.sql.ResultSet;

public class TestProcedureOne {
public TestProcedureOne() {
}
public static void main(String[] args ){
String driver = "oracle.jdbc.driver.OracleDriver";
String strUrl = "jdbc:oracle:thin:@127.0.0.1:1521:ORCLA";
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
CallableStatement cstmt = null;

try {
Class.forName(driver);
conn = DriverManager.getConnection(strUrl, " hyq ", " hyq ");
CallableStatement proc = null;
proc = conn.prepareCall("{ call saveuser(?,?,?) }");
proc.setString(1, "馬文濤");
proc.setInt(2,23);
proc.setInt(3,1);
proc.execute();
}
catch (SQLException ex2) {
ex2.printStackTrace();
}
catch (Exception ex2) {
ex2.printStackTrace();
}
finally{
try {
if(rs != null){
rs.close();
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
}
}
catch (SQLException ex1) {
}
}
}
}

2、有返回值的存儲過程(oracle存儲過程本身沒返回值)只是用out參數代替(非列表)
//獲得某部門下的所有用戶姓名和年齡
create or replace procedure pro_getUserByDepart//oracle中不區分大小寫,這裏只是為了自己方便。
( i_departid in t_user.departid%type,
o_username out t_user.username%type,
o_age out t_user.age%type
)as
begin
select username,age into o_username,o_age from t_user where departid = i_departid;
end pro_getUserByDepart;

★在pl/sql Developer中右擊存儲過程選擇測試就可以在下面輸入值直接看打印結果了。

★由於這個存儲過程會返回行記錄集,所有在Developer中為了測試成功就在此過程中加入rownum=1條件判斷,
即:select username,age into o_username,o_age from t_user where departid = i_departid and rownum=1;
如果不加那個rownum=1(當然你也可以讓它等於2),多行記錄會報“實際返回的行數超出請求的行數”這個異常。

★其實我們用上面這種存儲過程一般都只返回一行記錄集,如果是返回多行那就要用到要用包pagkage和遊標cursor了。

★在利用select...into...語法時(把查詢的結果放入輸出參數中),必須先確保數據庫中有該條記錄,否則會報出"no data found"異常。

3、返回列表(必須要用包了,package裏包含了遊標),分兩個步驟:
★為什麽要在存儲過程中用到遊標時,要把此遊標封裝到一個包中呢,個人理解:由於遊標是機開機關的一個
對象,它無法被存儲過程調用,而包中恰恰能封裝遊標、函數等這些對象,所有就把遊標放在一個包中。
(1)1, 建一個程序包。如下:
create or replace package userpackage as
type usercursor is ref cursor;
end userpackage;

(2)建立存儲過程,存儲過程為:
create or replace procedure pro_getalluser
(
pro_cursor out userpackage.usercursor
)is
begin
open pro_cursor for select * from t_user;
end pro_getalluser;
可以看到,它是把遊標(可以理解為一個指針),作為一個out 參數來返回值的。

★在java裏調用時就用下面的代碼(列出主要代碼):
package com.mwt.test;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;

import oracle.jdbc.OracleTypes;

public class TestProcedure {
public static void main(String...args){
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL9I";
String user = "test2";
String password = "test2";
Connection con = DriverManager.getConnection(url, user, password);
String sql = "{call pro_getalluser(?)}";
CallableStatement cs = con.prepareCall(sql);
cs.registerOutParameter(1, OracleTypes.CURSOR);
cs.execute();
//返回第一個存儲過程的輸出參數,我只返回了一個遊標也就只有一個輸出參數,即就是獲得第一個返輸出參數getObject(1);
ResultSet rs = (ResultSet)cs.getObject(1);
while(rs.next()){
System.out.println(rs.getString(1)+"----"+rs.getString(2)+"----"+rs.getString(3));
}
rs.close();
cs.close();
con.close();
}catch(Exception e){
e.printStackTrace();
}
}
}

Oracle中的DDL,DML,DCL總結