Ⅰ.oracle itcast
本文檔對應程序在myeclipse的jdbc/src/下
分頁查詢中的rownum可以方便刪除重複記錄等各種方便查詢
Oracle安裝自動生成sys用戶和system用戶
sys 超級用戶 具有最高權限 具有sysDBA角色,有create database權限
該用戶默認密碼是change_in_install
system 管理操作員 權限也比較大,具有sysoper角色,沒有create database權限。
該用戶默認密碼是 manager
這是通過sqlplus客戶端連接數據庫時有多個實例採用下面DOS命令:sqlplus scott/tiger@zhulin
見2.13 oracle創建數據庫實例
啓動sqlplus,然後登陸數據庫出現錯誤:TNS:協議適配器錯誤
原因有3個:
1.監聽服務沒有啓動:services.msc或開始—>程序—>管理工具—>服務,打開服務面板:
啓動oraclehome92TNSlistener服務
2.database instance沒有啓動:services.msc或開始—>程序—>管理工具—>服務 啓動oralceserviceXXX,XXX就是你databaseSID如zhulin
3.註冊表問題:
regedit.msc
進入HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb11g_home1
下的ORACLE_SID值修改爲zhulin
你的全局數據庫名字 你的數據庫SID即可。
ORACLE用SYS和SYSTEM默認密碼登錄提示ORA-01017:invalidusername/password;logond denied該怎麼解決?
|
解決辦法:
有可能是你在建數據庫的時候,
修改了默認的密碼
而自己又忘記
你可再重新修改過來
sqlplus / assysdba
alter user system identified by manager;
alter user sys identified by manager;
或者改成其他的你自己容易記住的
默認scott用戶密碼是tiger
1.oralce解鎖步驟
先使用system登錄
然後輸入alter user scott account unlock; //解鎖scott賬號
SQL語句必須帶分號!!!!!!!!!!!!!最好都分號結束
2.oralce開發工具
sqlpulsw和sqlus工具
在開始→程序→oracle oradb_home10g→application development→sqlplus
或在運行欄輸入sqlplus
pl/sqldeveloper 這款軟件用的很多 第三方軟件 需要單獨安裝
企業管理器(web) 首先保證相關服務啓動即oracleDBconsole+實例名啓動
在瀏覽器中輸入http://ip:1158//em ip是指你的具體ip地址或者你的機器名 1158是端口
一般情況下 這個服務是不啓動 很不安全
3.oracle常用sql plus命令
(1)請使用scott用戶登錄oracle數據庫實例,然後切換爲身份爲system
簡單使用 conn 用戶名/密碼
登錄後,使用 conn[ect] 用戶名/密碼@網絡 [assysdba/sysoper]
(2)showuser 顯示當前用戶名
(3) 斷開連接 disc[onnect]
(4)exit斷開連接和退出sqlplus窗口
(5) 修改密碼(前提是system或sys用戶) passw[ord]
基本用法 password 用戶名
如果給自己修改密碼 則可以不帶用戶名
如果給別人修改密碼 則需要帶用戶名
(6)& 交互命令可以替代變量的值
select* from emp where job=”&job”;
(7)edit用於編輯腳本(文本)
SQL>edit d:\
(8)spool 把屏幕上顯示的記錄,保存到文件中
spool on
spool d:/bak.sql
查詢語句
spool off
(9)linesize用戶控制每行顯示多少個字符,默認80個字符 每次都要重新設置
基本用法: set linesize 120
(10)pagesize 用於每頁顯示多少行
基本用法: set pagesize 100
4.oracle用戶管理
(1)創建用戶 只有具有DBA權限才能創建比如system sys
基本用法:create user 用戶名 identified by 密碼
舉例:create user xiaoqiang identified by hao200881037[oracle要求用戶密碼不能用數字開頭]
後面我將密碼修改爲了200881037
?爲什麼創建的用戶無法登陸
這是因爲oracle 剛剛創建的用戶是沒有任何權限,需要管理員給用戶分配適應的權限,才能夠登陸
grantcreate session to xiaoqiang //會話權限
(1)權限
系統權限:和數據庫管理相關的權限:
create session;create table;create index;createview;create sequence;create trigger
對象權限:和用戶操作數據對象相關的權限:
update;insert;delete;select
(2)角色
預定義角色:把常用的權限集中起來,形成角色(套餐)
比如dba connect resource 三種角色
自定義角色:自己定義套餐
(3)方案(schema)
在一個數據庫實例下:
當一個用戶,創建好後,如果該用戶創建了任意一個數據對象(表或觸發器等),這時我們的DBMS就會創建一個對應的方案與該用戶對應,並且該方案名字和用戶名一致。
小技巧:如果希望看到某個用戶的方案的數據對象,可以使用PL/SQL developer工具
案例1:完成一個功能;讓xiaoqiang用戶去查詢scott的emp表
步驟1:先用scott登錄
connscott/tiger
步驟2:在scott賬號上給xiaoqiang賦權限
grant select[update|delete|insert|all] on emp to xiaoqiang
這裏就可以看出來 方案A和方案B可以有相同名的數據庫,但是方案A中不可以有相同名的數據庫
步驟3:登錄xiaoqiang用戶去查詢emp表
錯誤用法:select * from emp 原因是在xiaoqiang登錄狀態下需要制定emp表來自哪裏?
正確用法:select * from scott.emp;
查詢時如果查詢其他方案 一定要用帶上其他方案名。
如果不帶,就默認是select* from xiaoqiang.emp
案例2:完成一個功能想辦法將xiaoqiang擁有的對scott.emp的權限轉給stu用戶。
scott—>xiaoqiang—>stu[權限轉移]
conn scott/tiger;
grant all on scott.emp to stu with grantoption;
//with grant option 對象權限 表示得到權限的用戶可以把權限繼續分配
//with admin option系統權限 如果是系統權限,則帶with admin iption
創建了普通賬戶 xiaoqiang 密碼hao200881037
修改密碼(前提是system或sys用戶) passw[ord]
基本用法 password 用戶名
如果給自己修改密碼 則可以不帶用戶名
如果給別人修改密碼 則需要帶用戶名
表空間:表存在的空間,一個表空間就是指向具體的數據文件
(4)用戶管理的綜合案例
創建的新用戶是沒有任何權限的,甚至連登錄(會話)的數據庫的權限都沒有,需要爲其指定響應的權限,給一個用戶賦權限使用命令grant,回收權限revoke
grant權限/角色 to 用戶
(1) 使用system創建xiaoqiang
後面我將密碼修改爲了200881037
(2) 使用system給小紅分配2個常用角色
grantconnect to xiaoqiang
grantresource to xiaoqiang
disconn //切斷連接
(3) 讓xiaoqiang登錄
conn xiaoqiang/200881037
(4) xiaoqiang修改密碼 pasw[ord] xiaoqiang即可 然要求你輸入舊密碼 當然 超級管理員不需要輸入舊密碼
(5) xiaohong創建一張最簡單的表
(6) 使用system登錄,然後回收角色。
revoke connect fromxiaoqiang
revoke resource fromxiaoqiang
(7) 刪除xiaoqiang用戶:
drop user 用戶名[cascade]
☞當我們刪除一個用戶的時候,若這個用戶自己已經創建了數據對象(表、觸發器等),需要加選項cascade表示把這個用戶刪除同時,把該用戶創建的數據對象一併刪除。
否則無法刪除該用戶,oracle用戶認爲刪除了該用戶就徹底拋棄了
(5)賬號鎖定
使用profile管理用戶口令,賬號鎖定指用戶登錄時最多可以輸入密碼的次數,也可以指定用戶鎖定的時間(天)一般用DBA的身份去執行該命令。 profile文件[規則]
eg:
create profile lock_accountlimit failed_login_attempts 3 paswword_lock_time 2;
alter user tea profilelock_account;//其中lock_account是文件名
(6)賬號解鎖
alter user 用戶名 account unlock;
(7)終止口令
eg:給tea創建一個profile文件,要求該用戶每隔10天必須修改自家的登錄密碼,款限期爲2天。
create profilemyprofile limit password_life_time 10 password_grace_time 2;
//可以繼續加限制條件
alter user tea profile myprofile;
(8)刪除profile文件
當不需要某個profile文件時,可以刪除該文件。
drop profile profile文件名。5.oracle數據庫啓動流程
oracle可以通過命令行的方式啓動,我們看看具體如何操作:
windows下:
(1)lsnrctl start (啓動監聽)
(2)oradim –startup –sid 數據庫實例名
linux下:
(1) lsnrctl start (啓動監聽)
(2) sqlplus sys/chang_on_install as sysdba(以sysdba身份登錄)
sqlplus /nolog
conn sys/chang_on_install assysdba
(3)startup
height�oml L h8H rid-mode:char;mso-layout-grid-align:none'>(8)刪除profile文件當不需要某個profile文件時,可以刪除該文件。
drop profile profile文件名。
6.oracle登錄認證方式
oracle在windows和linux下是不完全相同的:
windows下:
如果當前用戶屬於本地操作系統的ora_dba組(對於windows操作系統而言),即可通過操作系統認證。
普通用戶:默認是以數據庫方式認證,比如conn scott/tiger;
特權用戶:默認是以操作系統認證(即:只要當前用戶是在ora_dba組中則可以通過認證),比如connsystem/manager as sysdba;DBMS一看到assysdba則認爲要以特權用戶登錄,前面的用戶名和密碼不看,登錄後自動切換成sys用戶<=>connsys/manager。
如果當前用戶(win7系統賬號)不在ora_dba組中,conn sys/manager輸對了密碼還是可以登錄進去的(這時是採用了數據庫方式驗證)
sqlnet.ora文件在D:\xiaoqiang\oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN目錄下:
同時如果你安裝第三方工具PL/SQL Developer,同時也需要修改
D:\xiaoqiang\oracle\product\instantclient_11_2目錄下的sqlnet.ora文件
通過配置sqlnet.ora文件,可以修改oracle登錄認證方式:
SQLNET.AUTHENTICATION_SERVICES=(NTS)是基於操作系統驗證
SQLNET.AUTHENTICATION_SERVICES=(NONE)是基於Oracle驗證
SQLNET.AUTHENTICATION_SERVICES=(NONE,NTS)是二者共存
linux下:
默認情況下linux下的oracle數據庫sqlnet.ora文件沒有SQLNET.AUTHENTICATION_SERVICES參數,此時是基於操作系統認真和oracle密碼驗證共存,加上SQLNET.AUTHENTICATION_SERVICES參數後,不管SQLNET.AUTHENTICATION_SERVICES設置爲NONE還是NTS都是基於oracle密碼驗證。7.oracle丟失管理員密碼怎麼辦
數據庫實例名是根據實際情況命名的。
恢復辦法:把原有密碼文件刪除,生成一個新的密碼文件
恢復步驟如下:(1)搜索名爲PWD數據庫實例名.ora文件
(2)刪除該文件,爲以防萬一,建議備份
(3)生成新的密碼文件,在DOS控制檯下輸入命令
orapwdfile=原來密碼文件的全路徑\密碼文件名.ora password=新密碼 entries=10;
這裏密碼文件名是原來的密碼文件名=PWD數據庫實例名
entries 表示登錄sys的最多用戶(特權用戶)
如果希望新的密碼生效,則需要重新啓動數據庫實例服務.dos下services.exe
還有出現以下情況:
ORACLE用SYS和SYSTEM默認密碼登錄提示ORA-01017:invalidusername/password;logond denied該怎麼解決?
解決辦法:
有可能是你在建數據庫的時候,
修改了默認的密碼
而自己又忘記
你可再重新修改過來
sqlplus / assysdba
alter user system identified by manager;
alter user sys identified by manager;
或者改成其他的你自己容易記住的
默認scott用戶密碼是tiger
8.oracle表管理
類(對象)和表(記錄)之間的關係
◆創建表
基本語法
create table table_name(
列名 列類型,
……
)
◆數據類型
① char(size) 存放字符串最大2000個字符,是定長
eg:char(32) 最多隻能放入32個字符 如果超過就報錯,如果不夠’abc’則用空格補全
② varchar2(size)變長最大可以存放4000個字符
③ nchar(size) 定長 編碼方式unicode 最大字符數是2000個
一個漢字佔用nchar的一個字符空間,一個漢字,佔用char的兩個字符空間
④ nvarchar2(size)變長編碼方式unicode最大字符數是4000個
⑤ clob 字符型大對象 變長 最大8TB
⑥ blob 變長
說明:我們在實際開發中很少把文件存放在數據庫中(效率問題),實際上我們一般記錄文件的一個路徑(URL或本地路徑),然後通過IO或網絡來操作。
如果我們要求對文件安全性比較高,可以考慮放入數據庫。
⑦ number(p,s) p爲整數位,s爲小數位,範圍是1<=p<=38,-84<=s<=-127 變長
保存數據範圍:-1.0e-130<=numbervalue<=1.0e+126 保存機器位數1-22byte
e.gnumber(5,2) 表示一個小數有5位有效位,2位小數,範圍-999,99-999,99
比如你輸入 573.316則真正保存是573.32,無法保存數據1000
number(5)等價於number(5,0),表示一個5位整數,範圍-99999-99999,輸入57523.316則保存57523
原則:如果在做實際開發中,我們沒有指定數據小數位,則直接使用number
⑧date 日期類型
包含年月日,時分秒
插入數據時要使用默認格式是:'dd-mm-yyy';當然 如果用自己格式需要借用to_date函數
SQL> insert into test1 values(to_date('2005-11-11','YYYY-MM-DD'));
1 row inserted
to_char
你可以使用select ename, hiredate, sal from emp where deptno =10;顯示信息,可是,在某些情況下,這個並不能滿足你的需求。
問題:日期是否可以顯示 時/分/秒
SQL> select ename, to_char(hiredate, 'yyyy-mm-ddhh24:mi:ss') from emp;
9.oracle基本查詢
oracle的crud操作(create retrieve/read update delete)
添加一個字段
SQL>ALTER TABLE student add (classIdNUMBER(2));
修改一個字段的長度
SQL>ALTER TABLE student modify (xm VARCHAR2(30));
修改字段的類型/或是名字(不能有數據) 不建議做
SQL>ALTER TABLE student modify (xm CHAR(30));
刪除一個字段 不建議做(刪了之後,順序就變了。加就沒問題,應爲是加在後面)
SQL>ALTER TABLE student DROP COLUMN sal;
修改表的名字 很少有這種需求
SQL>RENAME studentTO stu;
刪除表
SQL>DROP TABLE student;
添加數據
所有字段都插入數據
INSERT INTOstudent VALUES('A001', '張三', '男', '01-5月-05',10);
oracle中默認的日期格式‘dd-mon-yy’ dd日子(天) mon 月份 yy 2位的年 ‘09-6月-99’ 1999年6月9日
修改日期的默認格式(臨時修改,數據庫重啓後仍爲默認;如要修改需要修改註冊表)
ALTER SESSIONSETNLS_DATE_FORMAT ='yyyy-mm-dd';
修改後,可以用我們熟悉的格式添加日期類型:
INSERT INTOstudent VALUES('A002', 'MIKE', '男','1905-05-06', 10);
插入部分字段
INSERT INTOstudent(xh, xm, sex) VALUES ('A003', 'JOHN', '女');
插入空值
INSERT INTOstudent(xh, xm, sex, birthday) VALUES ('A004', 'MARTIN', '男', null);
問題來了,如果你要查詢student表裏birthday爲null的記錄,怎麼寫sql呢?
錯誤寫法:select * from student wherebirthday = null;
正確寫法:select * from student wherebirthday is null;
如果要查詢birthday不爲null,則應該這樣寫:
select * from student wherebirthday is not null;
修改數據
修改一個字段
UPDATE student SETsex = '女'WHERE xh = 'A001';
修改多個字段
UPDATE student SETsex = '男',birthday = '1984-04-01' WHERE xh = 'A001';
修改含有null值的數據
不要用 = null 而是用 is null;
SELECT * FROM student WHEREbirthday IS null;
刪除數據
DELETE FROMstudent;
刪除所有記錄,表結構還在,寫日誌,可以恢復的,速度慢。
Delete 的數據可以恢復。
savepoint a; --創建保存點
DELETE FROMstudent;
rollback to a; --恢復到保存點
一個有經驗的DBA,在確保完成無誤的情況下要定期創建還原點。
DROP TABLE student; --刪除表的結構和數據;
delete fromstudent WHERExh = 'A001'; --刪除一條記錄;
truncate TABLE student; --刪除表中的所有記錄,表結構還在,不寫日誌,無法找回刪除的記錄,速度快。
oracle基本所有查詢案例
在我們講解的過程中我們利用scott用戶存在的幾張表(emp,dept)爲大家演示如何使用select語句,select語句在軟件編程中非常有用,希望大家好好的掌握。
查看錶結構
DESC emp;
查詢所有列
SELECT * FROM dept;
切忌動不動就用select*
SET TIMINGON;打開顯示操作時間的開關,在下面顯示查詢時間。
CREATE TABLE users(userId VARCHAR2(10),uName VARCHAR2 (20), uPassw VARCHAR2(30));
INSERT INTO users VALUES('a0001', '啊啊啊啊', 'aaaaaaaaaaaaaaaaaaaaaaa');
--從自己複製,加大數據量大概幾萬行就可以了 可以用來測試sql語句執行效率
INSERT INTO users (userId,UNAME,UPASSW)SELECT * FROM users;
SELECT COUNT (*) FROM users;統計行數
查詢指定列
SELECT ename, sal, job, deptno FROM emp;
如何取消重複行DISTINCT
SELECT DISTINCT deptno, job FROM emp;
查詢SMITH所在部門,工作,薪水
SELECT deptno,job,sal FROM emp WHERE ename= 'SMITH';
注意:oracle對內容的大小寫是區分的,所以ename='SMITH'和ename='smith'是不同的
使用算術表達式 nvl null
問題:如何顯示每個僱員的年工資?
SELECT sal*13+nvl(comm, 0)*13 "年薪" , ename, comm FROM emp;
使用列的別名
SELECT ename "姓名", sal*12 AS "年收入" FROM emp;
如何處理null值使用nvl函數來處理
如何連接字符串(||)
SELECT ename || ' is a ' || job FROMemp;
使用where子句
問題:如何顯示工資高於3000的 員工?
SELECT * FROM emp WHERE sal > 3000;
問題:如何查找1982.1.1後入職的員工?
SELECT ename,hiredate FROM emp WHEREhiredate >'1-1月-1982';
問題:如何顯示工資在2000到3000的員工?
SELECT ename,sal FROM emp WHERE sal>=2000 AND sal <= 3000;
如何使用like操作符
%:表示0到多個字符 _:表示任意單個字符
問題:如何顯示首字符爲S的員工姓名和工資?
SELECT ename,sal FROM emp WHERE ename like'S%';
如何顯示第三個字符爲大寫O的所有員工的姓名和工資?
SELECT ename,sal FROM emp WHERE ename like'__O%';
在where條件中使用in
問題:如何顯示empno爲7844, 7839,123,456 的僱員情況?
SELECT * FROM emp WHERE empno in (7844,7839,123,456);
使用is null的操作符
問題:如何顯示沒有上級的僱員的情況?
錯誤寫法:select *from emp where mgr = '';
正確寫法:SELECT *FROM emp WHERE mgr is null;
使用邏輯操作符號
問題:查詢工資高於500或者是崗位爲MANAGER的僱員,同時還要滿足他們的姓名首字母爲大寫的J?
SELECT * FROM emp WHERE (sal >500 or job= 'MANAGER') and ename LIKE 'J%';
使用order by字句 默認asc
問題:如何按照工資的從低到高的順序顯示僱員的信息?
SELECT * FROM emp ORDER by sal;
問題:按照部門號升序而僱員的工資降序排列
SELECT * FROM emp ORDER by deptno, sal DESC;
使用列的別名排序
問題:按年薪排序
select ename, (sal+nvl(comm,0))*12 "年薪" from emp order by "年薪" asc;
別名需要使用“”號圈中,英文不需要“”號
Clear清屏命令
數據分組 ——max,min, avg, sum, count
問題:如何顯示所有員工中最高工資和最低工資?
SELECT MAX(sal),min(sal) FROM emp e;
最高工資那個人是誰?
錯誤寫法:selectename, sal from emp where sal=max(sal);
正確寫法:selectename, sal from emp where sal=(select max(sal) from emp);
注意:selectename, max(sal) from emp;這語句執行的時候會報錯,說ORA-00937:非單組分組函數。因爲max是分組函數,而ename不是分組函數.......
但是selectmin(sal), max(sal) from emp;這句是可以執行的。因爲min和max都是分組函數,就是說:如果列裏面有一個分組函數,其它的都必須是分組函數,否則就出錯。這是語法規定的問題:如何顯示所有員工的平均工資和工資總和?
問題:如何計算總共有多少員工問題:如何
擴展要求:
查詢最高工資員工的名字,工作崗位
SELECT ename, job, sal FROM emp e where sal= (SELECT MAX(sal) FROM emp);
顯示工資高於平均工資的員工信息
SELECT * FROM emp e where sal > (SELECTAVG(sal) FROM emp);
groupby 和 having子句
groupby用於對查詢的結果分組統計 having子句用於限制分組顯示結果
問題:如何顯示每個部門的平均工資和最高工資?
SELECT AVG(sal), MAX(sal), deptno FROM empGROUP by deptno;
(注意:這裏暗藏了一點,如果你要分組查詢的話,分組的字段deptno一定要出現在查詢的列表裏面,否則會報錯。因爲分組的字段都不出現的話,就沒辦法分組了)
問題:顯示每個部門的每種崗位的平均工資和最低工資?
SELECT min(sal), AVG(sal), deptno, job FROMemp GROUP by deptno, job;
問題:顯示平均工資低於2000的部門號和它的平均工資?
SELECT AVG(sal), MAX(sal), deptno FROM empGROUP by deptno having AVG(sal) < 2000;
對數據分組的總結
1 分組函數只能出現在選擇列表、having、order by子句中(不能出現在where中)
2 如果在select語句中同時包含有groupby, having, order by 那麼它們的順序是group by, having, order by
3 在選擇列中如果有列、表達式和分組函數,那麼這些列和表達式必須有一個出現在group by 子句中,否則就會出錯。
如SELECTdeptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) < 2000;
這裏deptno就一定要出現在group by 中
問題:顯示僱員名,僱員工資及所在部門的名字【笛卡爾集】?
規定:多表查詢的條件是 至少不能少於 表的個數-1 才能排除笛卡爾集
(如果有N張表聯合查詢,必須得有N-1個條件,才能避免笛卡爾集合)
SELECT e.ename, e.sal, d.dname FROM emp e,dept d WHERE e.deptno = d.deptno;
問題:顯示部門號爲10的部門名、員工名和工資?
SELECT d.dname, e.ename, e.sal FROM emp e,dept d WHERE e.deptno = d.deptno and e.deptno = 10;
問題:顯示各個員工的姓名,工資及工資的級別?
先看salgrade的表結構和記錄
SQL>select * from salgrade;
GRADE LOSAL HISAL
------------- ------------- ------------
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999
SELECT e.ename, e.sal, s.grade FROM emp e,salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;
擴展要求:
問題:顯示僱員名,僱員工資及所在部門的名字,並按部門排序?
SELECT e.ename, e.sal, d.dname FROM emp e,dept d WHERE e.deptno = d.deptno ORDER by e.deptno;
(注意:如果用groupby,一定要把e.deptno放到查詢列裏面)
自連接
自連接是指在同一張表的連接查詢
問題:顯示某個員工的上級領導的姓名?
比如顯示員工‘FORD’的上級
SELECT worker.ename, boss.ename FROM emp worker,emp boss WHERE worker.mgr = boss.empno AND worker.ename ='FORD';
請思考:顯示與SMITH同部門的所有員工?
思路:
1 查詢出SMITH的部門號
select deptno from emp WHERE ename = 'SMITH';
2 顯示
SELECT * FROM emp WHERE deptno = (select deptno from emp WHERE ename= 'SMITH');
數據庫在執行sql 是從左到右掃描的, 如果有括號的話,括號裏面的先被優先執行。
請思考:如何查詢和部門10的工作相同的僱員的名字、崗位、工資、部門號
SELECT DISTINCT job FROM emp WHERE deptno = 10;
SELECT * FROM emp WHERE job IN(SELECT DISTINCT job FROM emp WHERE deptno = 10);
(注意:不能用job=..,因爲等號=是一對一的)
在多行子查詢中使用all操作符
問題:如何顯示工資比部門30的所有員工的工資高的員工的姓名、工資和部門號?
SELECT ename, sal, deptno FROM emp WHERE sal > all (SELECT sal FROM emp WHERE deptno = 30);
擴展要求:
大家想想還有沒有別的查詢方法。
SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30);
執行效率上, 函數高得多
在多行子查詢中使用any操作符
問題:如何顯示工資比部門30的任意一個員工的工資高的員工姓名、工資和部門號?
SELECT ename, sal, deptno FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30);
擴展要求:
大家想想還有沒有別的查詢方法。
SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT min(sal)FROM emp WHERE deptno = 30);
多列子查詢
單行子查詢是指子查詢只返回單列、單行數據,多行子查詢是指返回單列多行數據,都是針對單列而言的,而多列子查詢是指查詢返回多個列數據的子查詢語句。
請思考如何查詢與SMITH的部門和崗位完全相同的所有僱員。
SELECT deptno, job FROM emp WHERE ename = 'SMITH';
SELECT * FROM emp WHERE (deptno, job) = (SELECT deptno, job FROM empWHERE ename = 'SMITH');
在from子句中使用子查詢
請思考:如何顯示高於自己部門平均工資的員工的信息
思路:
1. 查出各個部門的平均工資和部門號
SELECT deptno, AVG(sal) mysal FROM empGROUP by deptno;
2. 把上面的查詢結果看做是一張子表
SELECT e.ename, e.deptno, e.sal, ds.mysalFROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) ds WHEREe.deptno = ds.deptno AND e.sal > ds.mysal;
如何衡量一個程序員的水平?
網絡處理能力, 數據庫, 程序代碼的優化程序的效率要很高
小總結:
在這裏需要說明的當在from子句中使用子查詢時,該子查詢會被作爲一個視圖來對待,因此叫做內嵌視圖,當在from子句中使用子查詢時,必須給子查詢指定別名。
注意:別名不能用as,如:SELECT e.ename, e.deptno, e.sal,ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno)as ds WHERE e.deptno = ds.deptno AND e.sal > ds.mysal;
在ds前不能加as,否則會報錯 (給表取別名的時候,不能加as;但是給列取別名,是可以加as的)
10.oracle分頁查詢
mysql: select * from 表名 where 條件 limit 從第幾條取,取幾條 見mysql分頁查詢
sql server: select top 取幾條 * from 表名 where id notin(select top 4 id from 表名 where 條件) 也可以使用行集函數 見3.sql server分頁查詢
排除前4條,再取4條,這個案例實際上是取5-8條
oracle:
以scott/tiger賬號登陸進行查詢:[分頁查詢模板]
select t2.* from
(selectt1.*,rownum rn from
(select * from emp) t1
where rownum<=6) t2 where rn>=4;
先找到小於6的然後找到大於4的
【順序可以反】
select t2.* from
(selectt1.*,rownum rn from
(select * from emp) t1
where rownum>=4) t2 where rn<=6;
oracle使用三層過濾:
第一層:select * fromemp
第二層:selectt1.*,rownum rn from (select * from emp) t1
whererownum<=6
第三層: select t2.* from
(selectt1.*,rownum rn from
(select * from emp) t1
where rownum<=6) t2 where rn>=4;
上面是一個分頁模板,6表示取到第幾條,4表示從第幾條取
(1)刪除重複記錄
在幾千條記錄裏,存在着些相同的記錄,請用sql語句刪除。
【注意】1.表中肯定是沒有主鍵的,這才叫記錄相同
2.若有主鍵(主鍵肯定不同),那請你把其他字段變成一個臨時表,再使用下面方法
準備:
--創建表
create table people(
peopleId number,
peopleName varchar(50),
peopleAge number);
--插入數據
insert into people values(1,'haozl',22);
insert into people values(2,'wangx',23);
insert into people values(3,'liwr',24);
insert into people values(4,'zhanggh',25);
insert into people values(5,'cheng',26);
--自我複製
insert into people(peopleId,peopleName,peopleAge) (select peopleId,peopleName,peopleAge from people);
insert into people values(6,'hancl',27);
insert into people values(7,'yangqp',22);
insert into people values(8,'wangt',23);
insert into people values(9,'nieyp',18);
insert into people values(10,'tianx',19);
insert into people(peopleId,peopleName,peopleAge) (select peopleId,peopleName,peopleAge from people);
insert into people values(11,'hansm',41);
insert into people values(12,'haog',31);
insert into people values(13,'chengyy',51);
insert into people values(14,'chenmm',61);
insert into people values(15,'xujf',11);
insert into people(peopleId,peopleName,peopleAge) (select peopleId,peopleName,peopleAge from people);
insert into people values(16,'wanggl',23);
insert into people values(17,'dujl',32);
insert into people values(18,'gaozg',28);
insert into people values(19,'haow',27);
insert into people values(20,'lizy',25);
--統計重複個數
select peopleId,COUNT(peopleId) from people group by peopleId having COUNT(peopleId)>1;
--查詢具體重複記錄(單個字段)
select distinct * from people where peopleId in
(select peopleId from people group by peopleId having COUNT(peopleId)>1);
--查詢具體重複記錄(多個字段)
select distinct * from people a where (peopleId,a.peoplename) in
(select peopleId,peoplename from people group by peopleId,peoplename having COUNT(*)>1);
savepoint savepoint1;--使用事務
--刪除表中多餘記錄(多個字段)
delete from people a where (a.peopleId,a.peoplename) in
(select peopleId,peoplename from people group by peopleId,peoplename having COUNT(*)>1)
and
rowid not in
(select min(rowid) from people group by peopleId,peoplename having COUNT(*)>1);
rollback to savepoint1;--還原
11.oracle合併查詢
有時在實際應用中,爲了合併多個select語句的結果,可以使用集合操作符號union,union all,intersect,minus 多用於數據量比較大的數據局庫,運行速度快。
1).union
該操作符用於取得兩個結果集的並集。當使用該操作符時,會自動去掉結果集中重複行。
SELECT ename, sal, job FROM emp WHERE sal>2500
UNION
SELECT ename, sal, job FROM emp WHERE job ='MANAGER';
2).unionall
該操作符與union相似,但是它不會取消重複行,而且不會排序。
SELECT ename, sal, job FROM emp WHERE sal>2500
UNION ALL
SELECT ename, sal, job FROM emp WHERE job ='MANAGER';
該操作符用於取得兩個結果集的並集。當使用該操作符時,會自動去掉結果集中重複行。
3).intersect 使用該操作符用於取得兩個結果集的交集。
SELECT ename, sal, job FROM emp WHERE sal>2500
INTERSECT
SELECT ename, sal, job FROM emp WHERE job ='MANAGER';
4).minus 使用改操作符用於取得兩個結果集的差集,他只會顯示存在第一個集合中,而不存在第二個集合中的數據。
SELECT ename, sal, job FROM emp WHERE sal>2500
MINUS
SELECT ename, sal, job FROM emp WHERE job ='MANAGER';
(MINUS就是減法的意思)12.oracle連接
(1)內連接:使我們用的最多的一種連接,前面我們使用的都是內連接。
eg:顯示員工的信息和部門名稱
select emp.ename,dept.dname fromemp,dept whereemp.deptno=dept.deptno;
等價於
select emp.ename,dept.dname from emp inner join deptonemp.deptno=dept.deptno;
基本語法:select 字段1, 字段2… from表名1inner join表名2on條件
(2)外連接:
我們創建2種表做測試:
--表stu
id name
1 Jack
2 Tom
3 Kity
4 Nono
create tablestu(id number,
name varchar2(4));
insert into stuvalues(1,'Jack');
insert into stuvalues(2,'Tom');
insert into stuvalues(3,'Kity');
insert into stuvalues(4,'Nono');--表exam
id grade
1 56
2 76
11 80
3 65
create tableexam(id number,
grade number);
insert into examvalues(1,56);
insert into examvalues(2,76);
insert into examvalues(11,80);
insert into examvalues(3,65);
①左外連接(顯示所有人的成績,如果沒有成績,也要顯示該人的姓名和id號,成績顯示爲空)
selectstu.id,stu.name,exam.grade from stuleftjoinexam on stu.id=exam.id;
有的程序員喜歡這樣寫 左外連接:
select stu.id,stu.name,exam.grade from stu,exam wherestu.id=exam.id(+);
ID NAME GRADE
左外連接------ ------------
1 Jack 56
2 Tom 76
3 Kity 65
4 Nono
ID NAME GRADE
右外連接------ ------------
1 Jack 56
2 Tom 76
3 Kity 65
80
②右外連接(顯示所有成績,如果沒有名字匹配,顯示爲空)
selectstu.id,stu.name,exam.grade from sturightjoinexam onstu.id=exam.id;
有的程序員喜歡這樣寫 左外連接:
select stu.id,stu.name,exam.gradefrom stu,examwhere stu.id(+)=exam.id;
③完全外連接(顯示所有成績和所有人的名字,如果響應的匹配值,則顯示爲空)不管有無匹配均顯示
selectstu.id,stu.name,exam.grade from stufullouterjoin exam on stu.id=exam.id;
13.oracle函數
(1)字符函數
字符函數是oracle中最常用的函數,我們來看看有哪些字符函數:
lower(char):將字符串轉化爲小寫的格式.
upper(char):將字符串轉化爲大寫的格式.
length(char):返回字符串的長度。
substr(char,m,n):取字符串的子串;n代表取n個的意思,不是代表取到第n個
replace(char1,search_string,replace_string)
instr(char1,char2,[,n[,m]])取子串在字符串的位置
問題:將所有員工的名字按小寫的方式顯示
SQL> select lower(ename) from emp;
問題:將所有員工的名字按大寫的方式顯示。
SQL> select upper(ename) from emp;
問題:顯示正好爲5個字符的員工的姓名。
SQL> select * from emp where length(ename)=5;
問題:顯示所有員工姓名的前三個字符。
SQL> select substr(ename,1,3) from emp;
問題:以首字母大寫,後面小寫的方式顯示所有員工的姓名。
SQL> select upper(substr(ename,1,1)) || lower(substr(ename,2,length(ename)-1)) from emp;
問題:以首字母小寫,後面大寫的方式顯示所有員工的姓名。
SQL> select lower(substr(ename,1,1)) || upper(substr(ename,2,length(ename)-1)) from emp;
問題:顯示所有員工的姓名,用“我是老虎”替換所有“A”
SQL> select replace(ename,'A', '我是老虎') from emp;
(2)數學函數
數學函數的輸入參數和返回值的數據類型都是數字類型的。數學函數包括cos,cosh,exp,ln, log,sin,sinh,sqrt,tan,tanh,acos,asin,atan,round,我們講最常用的:
round(n,[m])該函數用於執行四捨五入,如果省掉m,則四捨五入到整數,如果m是正數, 則四捨五入到小數點的m位後。如果m是負數,則四捨五入到小數點的m位前。
trunc(n,[m]) 該函數用於截取數字。若省掉m,就截去小數部分(等價於trunc(n,0)),如 果m是正數就截取到小數點的m位後,若m是負數,則截取到小數點的前m位。
mod(m,n)
floor(n) 返回小於或是等於n的最大整數
ceil(n) 返回大於或是等於n的最小整數
問題:顯示在一個月爲30天的情況下,所有員工的日薪金,忽略餘數。
SQL> select trunc(sal/30), ename from emp;
or
SQL> select floor(sal/30), ename from emp;
在做oracle測試的時候,可以使用dual表
select mod(10,2) from dual;結果是0
select mod(10,3) from dual;結果是1
其它的數學函數,有興趣的同學可以自己去看看:abs(n): 返回數字n的絕對值
select abs(-13) from dual;
acos(n): 返回數字的反餘弦值
asin(n): 返回數字的反正弦值
atan(n): 返回數字的反正切值
cos(n):
exp(n): 返回e的n次冪
log(m,n): 返回對數值
power(m,n): 返回m的n次冪
(3)日期函數
日期函數用於處理date類型的數據。
默認情況下日期格式是dd-mon-yy即12-7月-78
(1)sysdate: 該函數返回系統時間
(2)add_months(d,n)在日期d上增加n個月
(3)last_day(d):返回指定日期所在月份的最後一天
問題:查找已經入職8個月多的員工
SQL> select * from emp wheresysdate>=add_months(hiredate,8);
問題:顯示滿10年服務年限的員工的姓名和受僱日期。
SQL> select ename, hiredate from emp
where sysdate>=add_months(hiredate,12*10);
問題:對於每個員工,顯示其加入公司的天數。
SQL> select floor(sysdate-hiredate) "入職天數",ename fromemp;
or
SQL> select trunc(sysdate-hiredate) "入職天數",ename fromemp;
(4)給表取別名的時候,不能加as;但是給列取別名,是可以加as
問題:找出各月倒數第3天受僱的所有員工。
SQL> select hiredate,ename from emp wherelast_day(hiredate)-2=hiredate;
(5)轉換函數
轉換函數用於將數據類型從一種轉爲另外一種。在某些情況下,oracle server允許值的數據類型和實際的不一樣,這時oracle server會隱含的轉化數據類型
比如:
create table t1(idint);//這裏 注意int不是關鍵字在oracle下
insert into t1 values('10');-->這樣oracle會自動的將10 -->'10 ’
create table t2 (id varchar2(10));
insert into t2 values(1); -->這樣oracle就會自動的將1 -->'1';
我們要說的是儘管oracle可以進行隱含的數據類型的轉換,但是它並不適應所有的情況,爲了提高程序的可靠性,我們應該使用轉換函數進行轉換。
(6) to_char(date,'format')
你可以使用select ename, hiredate, sal from emp where deptno =10;顯示信息,可是,在某些情況下,這個並不能滿足你的需求。
問題:日期是否可以顯示 時/分/秒
SQL> select ename, to_char(hiredate, 'yyyy-mm-ddhh24:mi:ss') from emp;
問題:薪水是否可以顯示指定的貨幣符號
SQL>
yy:兩位數字的年份2004-->04
yyyy:四位數字的年份 2004年
mm:兩位數字的月份 8月-->08
dd:兩位數字的天 30號-->30
hh24: 8點-->20
hh12:8點-->08
mi、ss-->顯示分鐘\秒
SQL> select to_char(sysdate,'day') from dual;
顯示:星期五
set serveroutput on;
if to_char(sysdate,'day') in ('星期日','星期六') then
dbms_output.put_line('對不起,休息日不能刪除員工');
end if;
9:顯示數字,並忽略前面0
0:顯示數字,如位數不足,則用0補齊
.:在指定位置顯示小數點
,:在指定位置顯示逗號
$:在數字前加美元
L:在數字前面加本地貨幣符號
C:在數字前面加國際貨幣符號
G:在指定位置顯示組分隔符、
D:在指定位置顯示小數點符號(.)
問題:顯示薪水的時候,把本地貨幣單位加在前面
SQL> select ename, to_char(hiredate,'yyyy-mm-dd hh24:mi:ss'), to_char(sal,'L99999.99')from emp;
問題:顯示1980年入職的所有員工
SQL> select * from emp where to_char(hiredate, 'yyyy')=1980;
問題:顯示所有12月份入職的員工
SQL> select * from emp where to_char(hiredate, 'mm')=12;
這裏的12和1980可以加''也可以不加,因爲Oracle會自動轉換,但是最好加。
(7) to_date(string,'format')
函數to_date用於將字符串轉換成date類型的數據。
問題:能否按照中國人習慣的方式年—月—日添加日期。
SQL> create table test1(id date);
SQL> insert into test1 values(to_date('2005-11-11','YYYY-MM-DD'));
1 row inserted
(8)系統函數
sys_context
1)terminal:當前會話客戶所對應的終端的標示符
2)lanuage: 語言
3)db_name: 當前數據庫名稱
4)nls_date_format: 當前會話客戶所對應的日期格式
5)session_user: 當前會話客戶所對應的數據庫用戶名
6)current_schema:當前會話客戶所對應的默認方案名
7)host: 返回數據庫所在主機的名稱
通過該函數,可以查詢一些重要信息,比如你正在使用哪個數據庫?
SQL>select sys_context('USERENV','db_name') fromdual;
SYS_CONTEXT('USERENV','DB_NAME
--------------------------------------------------------------------------------
zhulin
注意:USERENV是固定的,不能改的,db_name可以換成其它,比如lanuage SQL>sys_context('USERENV','lanuage') from dual;
SYS_CONTEXT('USERENV','LANGUAG
--------------------------------------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK
SQL>sys_context('USERENV','current_schema')from dual;
SYS_CONTEXT('USERENV','CURRENT
--------------------------------------------------------------------------------
XIAOQIANG
14.oracle創建數據庫實例
1). 通過oracle提供的嚮導工具。
database Configuration Assistant 【數據庫配置助手】
2).我們可以用手工步驟直接創建。
☞但我們創建完一個新的數據庫實例後,在服務中(services.exe)中就會有兩個新的服務創建,這時,你根據實際需要去啓動相應的數據庫實例。
☞在同一臺機器允許同時啓動多個數據庫實例,我們在登錄或鏈接的時候需要指定主機字符串(SID )
這是通過sqlplus客戶端連接數據庫時有多個實例採用下面DOS命令:sqlplus scott/tiger@zhulin
15.java操作oracle
補充一下:
SQL語句分類:
DML語句:數據操作語句(insert、update、delete)
DDL語句:數據定義語言(create table、drop table..)
DQL語句:數據查詢語言(select)
對於使用java去查詢oracle會出現一個很奇怪的現象?
PL/SQL Developer看到的數據庫,可能和java程序中看到的數據不一致,這是事務控制引起的。
對java連接oracle 封裝成一個OracleSQLHelper類。
//3.創建 PrepareedStatement或Statement接口引用對象
//Statement用處:主要用於發送sql語句到數據庫
//PrepareedStatement:會進行預編譯,適合批量的sql語句,有效防止危險字符注入
//PrepareedStatement支持在sql語句中出現問號?作爲參數帶進去!!!!!!!!!!!!!!!!!!!!!!
我們把連接數據庫的配置信息寫到一個文件中去,這樣代碼更加靈活。
這裏有一個Java技巧,快速提供類的get和set方法:
然後彈出一個窗口:
最後OK。
(2)JDBC-ODBC連接
配置數據源——管理工具(Administrativetools)——ODBC——userDSN——Add添加ODBC數據源
java代碼做相應的修改:【與SQLServer一樣的】//sun.jdbc.odbc.JdbcOdbcDriver本身自帶
Class.Forname("sun.jdbc.odbc.JdbcOdbcDriver");
Connectionct=DriverManager.getConnection("jdbc:odbc:hsporc","scott","tiger");
這裏hsporc就是你ODBC數據源名稱了。。。。。。
什麼時候用JDBC或JDBC-ODBC?
原則:若java程序和DB不在同一機器上,我們一般使用JDBC
若java程序和DB在同一機器上,我們一般使用JDBC-ODBC
16.oracle事務處理
什麼是事務
事務用於保證數據的一致性,它由一組相關的dml語句組成,該組的dml(數據操作語言,增刪改,沒有查詢)語句要麼全部成功,要麼全部失敗。
如:網上轉賬就是典型的要用事務來處理,用於保證數據的一致性。
dml 數據操作語言 銀行轉賬、QQ申請、車票購買
事務和鎖
當執行事務操作時(dml語句),oracle會在被作用的表上加鎖,防止其它用戶修改表的結構。這裏對我們的用戶來來講是非常重要的。
.....其它進程排序,知道1號進程完成,鎖打開,2號進程進入。依次進行,如果有進程級別較高的,可以插隊。
提交事務
當執行用commit語句可以提交事務。當執行了commit語句之後,會確認事務的變化、結束事務。刪除保存點、釋放鎖,當使用commit語句結束事務之後,其它會話將可以查看到事務變化後的新數據。
保存點就是爲回退做的。保存點的個數沒有限制
回退事務
在介紹回退事務前,我們先介紹一下保存點(savepoint)的概念和作用。保存點是事務中的一點。用於取消部分事務,當結束事務時,會自動的刪除該事務所定義的所有保存點。當執行rollback時,通過指定保存點可以回退到指定的點,這裏我們作圖說明。
事務的幾個重要操作
1.設置保存點 savepoint a
2.取消部分事務 rollback to a
3.取消全部事務 rollback
每個保存點都只有一次回退的機會 設置保存點是有資源開銷的 一旦commit了事務則不能回退
注意:這個回退事務,必須是沒有commit前使用的;如果事務提交了,那麼無論你剛纔做了多少個保存點,都統統沒有。 如果沒有手動執行commit,而是exit了,那麼會自動提交
java程序中如何使用事務 ./src/oracle_test/test_oracle_transaction_vital.java
//事先先設置成不自動提交
//事務開始
update emp set=?
insert…
update…
commit();
如果一個事務中,只有select則事務可以忽略,若一個事務有多個(update,insert,delete)則需要考慮事務。
事務的隔離級別:定義了事務與事務之間的隔離程度。
ANSI/ISOSQL92國際標準化組織定義了一個標準,不同的數據庫在實現時有所不同。
隔離級別 |
髒讀 |
不可重複讀 |
幻讀 |
讀未提交(Read uncommitted) |
√ |
√ |
√ |
讀已提交(Read committed) |
× |
√ |
√ |
可重複讀(Repeatable read) |
× |
× |
√ |
可串行化(Serializable) |
× |
× |
× |
×不會出現 √可能出現
oracle提供了三種隔離級別:讀已提交、可串行化、(Read Only 非ANSI/ISO SQL92標準)
髒讀(dirty read):當事務A讀取事務B尚未提交的修改時,產生髒讀。在oracle中不會出現
不可重複讀(nonrepeatable read):同一查詢在同一事務中多次進行,由於其他提交事務所在的修改或刪除,每次返回不同的結果集,此時發生非重複讀。
幻讀(phantom read):同一查詢在同一事務中多次進行,由於其他提交事務所做的插入操作,每次返回不同的結果集(結果集到底是對還是錯?),此時發生幻讀。
oracle中設置事務隔離級別:
設置一個事務的隔離級別:
set transactionisolation level read committed;(默認級別)
set transactionisolation level serializable;(手動)
設置整個會話的隔離級別:
alter session setisolation_level serializable;
alter session setisolation_level read committed;
java程序中設置事務隔離級別: public Connection ct=null;
說明:一般情況下,我們java程序員無需設置事務的隔離級別。
17.oracle數據完整性
約束:用於確保數據庫數據滿足特定的商業規則。在oracle中,約束包括:not null、 unique, primary key, foreign key,和check五種。
not null(非空)
如果在列上定義了not null,那麼當插入數據時,必須爲列提供數據。
unique(唯一)
當定義了唯一約束後,該列值是不能重複的,但是可以爲null。
primary key(主鍵)n
用於唯一的標示錶行的數據,當定義主鍵約束後,該列不但不能重複而且不能爲null。
需要說明的是:一張表最多只能有一個主鍵,但是可以有多個unqiue約束。
foreign key(外鍵)
用於定義主表和從表之間的關係。外鍵約束要定義在從表上,主表則必須具有主鍵約束或是unique約束,當定義外鍵約束後,要求外鍵列數據必須在主表的主鍵列存在或是爲null。
check
用於強制行數據必須滿足的條件,假定在sal列上定義了check約束,並要求sal列值在1000-2000之間如果不在1000-2000之間就會提示出錯。
商店售貨系統表設計案例
現有一個商店的數據庫,記錄客戶及其購物情況,由下面三個表組成:商品goods(商品號goodsId,商品名goodsName,單價 unitprice,商品類別category,供應商provider);
客戶customer(客戶號customerId,姓名name,住在address,電郵email,性別sex,身份證cardId);
購買purchase(客戶號customerId,商品號goodsId,購買數量nums);
請用SQL語言完成下列功能:
1. 建表,在定義中要求聲明:
(1). 每個表的主外鍵;
(2). 客戶的姓名不能爲空值;
(3). 單價必須大於0,購買數量必須在1到30之間;
(4). 電郵不能夠重複;
(5). 客戶的性別必須是 男 或者 女,默認是男;
SQL> createtable goods(goodsId char(8) primary key,--主鍵
goodsName varchar2(30),
unitprice number(10,2) check(unitprice>0),
category varchar2(8),
provider varchar2(30)
);
SQL> createtable customer( customerId char(8) primary key, --主鍵
name varchar2(50) not null, --不爲空
address varchar2(50),
email varchar2(50) unique,
sex char(2) default'男' check(sex in ('男','女')),
-- 一個char能存半個漢字,兩位char能存一個漢字
cardId char(18)
);
SQL> createtable purchase( customerId char(8) referencescustomer(customerId),
goodsId char(8) referencesgoods(goodsId),
nums number(10)check (nums between 1 and 30)
);
表是默認建在SYSTEM表空間的
維護
商店售貨系統表設計案例(2)
如果在建表時忘記建立必要的約束,則可以在建表後使用alter table命令爲表增加約束。但是要注意:增加not null約束時,需要使用modify選項,而增加其它四種約束使用add選項。
1. 增加商品名也不能爲空
SQL> altertable goods modify goodsName notnull;
2. 增加身份證也不能重複
SQL> altertable customer add constraint xxxxxx unique(cardId);
3. 增加客戶的住址只能是’海淀’,’朝陽’,’東城’,’西城’,’通州’,’崇文’,’昌平’;
SQL> altertable customer add constraint yyyyyycheck (address in (’海淀’,’朝陽’,’東城’,’西城’,’通州’,’崇文’,’昌平’));
刪除約束
當不再需要某個約束時,可以刪除。
alter table 表名 drop constraint 約束名稱;
特別說明一下:
在刪除主鍵約束的時候,可能有錯誤,比如:
alter table 表名 drop primary key;
這是因爲如果在兩張表存在主從關係,那麼在刪除主表的主鍵約束時,必須帶上cascade選項 如像:
alter table 表名 drop primary key cascade;
顯示約束信息
1.顯示約束信息
通過查詢數據字典視圖user_constraints,可以顯示當前用戶所有的約束的信息。
selectconstraint_name, constraint_type, status, validated from user_constraints where table_name = '表名';
2.顯示約束列
通過查詢數據字典視圖user_cons_columns,可以顯示約束所對應的表列信息。
selectcolumn_name, position from user_cons_columnswhere constraint_name = '約束名';
3.當然也有更容易的方法,直接用pl/sql developer查看即可。簡單演示一下下...
表級定義 列級定義
列級定義
列級定義是在定義列的同時定義約束。
如果在department表定義主鍵約束
create tabledepartment4(dept_id number(12) constraintpk_department primary key,
name varchar2(12),loc varchar2(12));
表級定義
表級定義是指在定義了所有列後,再定義約束。這裏需要注意:
not null約束只能在列級上定義。
外鍵:
以在建立employee2表時定義主鍵約束和外鍵約束爲例:
create tableemployee2(emp_id number(4), name varchar2(15),
dept_id number(2),constraint pk_employee primary key(emp_id),
constraint fk_department foreign key (dept_id) referencesdepartment4(dept_id));
18.oracle 序列(sequence)
需求:在某張表中,存在一個id列(整數),我們希望添加記錄的時候,該列從1開始,自動的增長
解決方式:oracle是利用(sequence)來完成的
序列特點:由用戶創建數據庫對象,可由多個用戶共享(system可以使用scott創建的序列),一般用於主鍵或唯一列,可爲表中的列自動產生值。
問題:若system使用scott的序列,從什麼開始增長? 答案:接着增長
insert into test1values(scott.myseq.nextval,'kkk');
eg:創建一個序列:
create sequencemyseq --創建開始
start with 1 --從1開始
increment by 1 --每次增長1
minvalue 1 --最小值
maxvalue 30000 --最大值
cycle //cycle表示當序列增加30000,重新從1開始,如果不希望,就nocycle
nocache; --不緩存,而 cache 10;表示一次產生10個號共你使用,缺點可能會跳號,但提供效率
使用序列創建一張表:
create tabletest1(id number primary key,name varchar2(32));
insert into test1values(myseq.nextval,'abc');
insert into test1values(myseq.nextval,'dc');
insert into test1values(myseq.nextval,'ac');
insert into test1values(myseq.nextval,'ec');
說明:myseq:表示序列名字,nextval:這是一個關鍵字,序列的一個函數
[序列不是在表定義中附加]是在添加數據時使用
selectscott.myseq.currvalfrom dual; 查看當前序號
何時使用sequence:
不包含子查詢、snapshot、view、select的語句中,經常使用在insert(子查詢)、update語句中。
在sql server和mysql中都是可以在定義表的時候,直接給指定自增長:
sql server:
create table temp1(
id int primary key identity(1,1),
name varchar(36));
mysql:
create table temp1(
id int primary key auto_incrment,
name varchar(36));
19.oracle 索引
索引是用於加速數據存取的數據對象。合理的使用索引可以大大降低i/o次數,從而提高數據訪問性能。索引有很多種我們主要介紹常用的幾種:
爲什麼添加了索引後,會加快查詢速度呢?
創建索引
單列索引
單列索引是基於單個列所建立的索引,比如:
create index 索引名 on 表名(列名);
複合索引
複合索引是基於兩列或是多列的索引。在同一張表上可以有多個索引,但是要求列的組合必須不同,比如:
create indexemp_idx1 on emp (ename, job);
create indexemp_idx1 on emp (job, ename);
使用原則
1. 在大表上建立索引纔有意義
2. 在where子句或是連接條件上經常引用的列上建立索引
3. 索引的層次不要超過4層
索引的缺點
索引缺點分析
索引有一些先天不足:
1. 建立索引,系統要佔用大約爲表1.2倍的硬盤和內存空間來保存索引。
2. 更新數據的時候,系統必須要有額外的時間來同時對索引進行更新,以維持數據和索引的一致性。
實踐表明,不恰當的索引不但於事無補,反而會降低系統性能。因爲大量的索引在進行插入、修改和刪除操作時比沒有索引花費更多的系統時間。
比如在如下字段建立索引應該是不恰當的:
1. 很少或從不引用的字段;
2. 邏輯型的字段,如男或女(是或否)等。
綜上所述,提高查詢效率是以消耗一定的系統資源爲代價的,索引不能盲目的建立,這是考驗一個DBA是否優秀的很重要的指標。
其它索引
介紹
按照數據存儲方式,可以分爲B*樹、反向索引、位圖索引;
按照索引列的個數分類,可以分爲單列索引、複合索引;
按照索引列值的唯一性,可以分爲唯一索引和非唯一索引。
此外還有函數索引,全局索引,分區索引...
對於索引我還要說:
在不同的情況,我們會在不同的列上建立索引,甚至建立不同種類的索引,請記住,技術是死的,人是活的。比如:
B*樹索引建立在重複值很少的列上,而位圖索引則建立在重複值很多、不同值相對固定的列上。
顯示索引信息
顯示錶的所有索引
在同一張表上可以有多個索引,通過查詢數據字典視圖dba_indexs和user_indexs,可以顯示索引信息。其中dba_indexs用於顯示數據庫所有的索引信息,而user_indexs用於顯示當前用戶的索引信息:
select index_name,index_type from user_indexes where table_name ='表名';
顯示索引列
通過查詢數據字典視圖user_ind_columns,可以顯示索引對應的列的信息
select table_name,column_name from user_ind_columns where index_name = 'IND_ENAME';
你也可以通過pl/sqldeveloper工具查看索引信息
20.oracle管理權限和角色
這一部分我們主要看看oracle中如何管理權限和角色,權限和角色的區別在那裏。
當剛剛建立用戶時,用戶沒有任何權限,也不能執行任何操作。如果要執行某種特定的數據庫操作,則必須爲其授予系統的權限;如果用戶要訪問其它方案的對象,則必須爲其授予對象的權限。爲了簡化權限的管理,可以使用角色。這裏我們會詳細的介紹。看圖:
權限是指執行特定類型sql命令或是訪問其它方案對象的權利,包括系統權限和對象權限兩種。
系統權限是指執行特定類型sql命令的權利。它用於控制用戶可以執行的一個或是一組數據庫操作。比如當用戶具有createtable權限時,可以在其方案中建表,當用戶具有create any table權限時,可以在任何方案中建表。oracle提供了100多種系統權限。
常用的有:
英文 |
中文 |
英文 |
中文 |
create session |
連接數據庫 |
create table |
建表 |
create view |
建視圖 |
create public synonym |
建同義詞 |
create procedure |
建過程、函數、包 |
create trigger |
建觸發器 |
create cluster |
建簇 |
|
|
顯示系統權限
oracle提供了100多種系統權限,而且oracle的版本越高,提供的系統權限就越多,我們可以查詢數據字典視圖system_privilege_map,可以顯示所有系統權限。
select * from system_privilege_maporder by name;
授予系統權限
一般情況,授予系統權限是由DBA完成的,如果用其他用戶來授予系統權限,則要求該用戶必須具有grantany privilege的系統權限。在授予系統權限時,可以帶有with admin option選項,這樣,被授予權限的用戶或是角色還可以將該系統權限授予其它的用戶或是角色。爲了讓大家快速理解,我們舉例說明:
1.創建兩個用戶ken,tom。初始階段他們沒有任何權限,如果登錄就會給出錯誤的信息。
create user ken identfied by ken;
2 給用戶ken授權
1). grant createsession, create table to ken with adminoption;
2). grant createview to ken;
3 給用戶tom授權
我們可以通過ken給tom授權,因爲with admin option是加上的。當然也可以通過dba給tom授權,我們就用ken給tom授權:
1. grant createsession, create table to tom;
2. grant createview to ken; --ok嗎?不ok ,因爲沒有帶上withadmin option
回收系統權限
一般情況下,回收系統權限是dba來完成的,如果其它的用戶來回收系統權限,要求該用戶必須具有相應系統權限及轉授系統權限的選項(with admin option)。回收系統權限使用revoke來完成。
當回收了系統權限後,用戶就不能執行相應的操作了,但是請注意,系統權限級聯收回的問題?[不是級聯回收]
system--------->ken ---------->tom
(createsession)(create session)( create session)
用system執行如下操作:
revoke createsession from ken; --請思考tom還能登錄嗎?
答案:能,可以登錄
對象權限
指訪問其它方案對象的權利,用戶可以直接訪問自己方案的對象,但是如果要訪問別的方案的對象,則必須具有對象的權限。比如smith用戶要訪問scott.emp表(scott:方案,emp:表)
常用的有:
英文 |
中文 |
英文 |
中文 |
alter |
修改 |
delete |
刪除 |
select |
查詢 |
insert |
添加 |
update |
修改 |
index |
索引 |
references |
引用 |
execute |
執行 |
顯示對象權限
通過數據字段視圖可以顯示用戶或是角色所具有的對象權限。視圖爲dba_tab_privs
SQL> connsystem/manager;
SQL> selectdistinct privilege from dba_tab_privs;
SQL> selectgrantor, owner, table_name, privilege from dba_tab_privs wheregrantee = 'BLAKE';
授予對象權限
在oracle9i前,授予對象權限是由對象的所有者來完成的,如果用其它的用戶來操作,則需要用戶具有相應的(withgrant option)權限,從oracle9i開始,dba用戶(sys,system)可以將任何對象上的對象權限授予其它用戶。授予對象權限是用grant命令來完成的。
對象權限可以授予用戶,角色,和public。在授予權限時,如果帶有with grant option選項,則可以將該權限轉授給其它用戶。但是要注意with grant option選項不能被授予角色。
1.monkey用戶要操作scott.emp表,則必須授予相應的對象權限
1). 希望monkey可以查詢scott.emp表的數據,怎樣操作?
grant select on emp to monkey;
2). 希望monkey可以修改scott.emp的表數據,怎樣操作?
grantupdate on emp to monkey;
3). 希望monkey可以刪除scott.emp的表數據,怎樣操作?
grantdelete on emp to monkey;
4). 有沒有更加簡單的方法,一次把所有權限賦給monkey?
grant all on emp to monkey;
2.能否對monkey訪問權限更加精細控制。(授予列權限)
1). 希望monkey只可以修改scott.emp的表的sal字段,怎樣操作?
grantupdate on emp(sal) to monkey
2).希望monkey只可以查詢scott.emp的表的ename,sal數據,怎樣操作?
grantselect on emp(ename,sal) to monkey
...
3.授予alter權限
如果black用戶要修改scott.emp表的結構,則必須授予alter對象權限
SQL> connscott/tiger
SQL> grantalter on emp to blake;
當然也可以用system,sys來完成這件事。
4.授予execute權限
如果用戶想要執行其它方案的包/過程/函數,則須有execute權限。
比如爲了讓ken可以執行包dbms_transaction,可以授予execute權限。
SQL> connsystem/manager
SQL> grant execute on dbms_transaction to ken;
5.授予index權限
如果想在別的方案的表上建立索引,則必須具有index對象權限。
如果爲了讓black可以在scott.emp表上建立索引,就給其index的對象權限
SQL> connscott/tiger
SQL> grant index on scott.emp to blake;
6.使用with grant option選項
該選項用於轉授對象權限。但是該選項只能被授予用戶,而不能授予角色
SQL> connscott/tiger;
SQL> grantselect on emp to blake with grant option;
SQL> connblack/shunping
SQL> grantselect on scott.emp to jones;
回收對象權限
在oracle9i中收回對象的權限可以由對象的所有者來完成,也可以用dba用戶(sys,system)來完成。
這裏要說明的是:收回對象權限後,用戶就不能執行相應的sql命令,但是要注意的是對象的權限是否會被級聯收回?【級聯回收】
如:scott------------->blake-------------->jones
select on emp select onemp select on emp
SQL> connscott/tiger@accp
SQL> revokeselect on emp from blake
請大家思考,jones能否查詢scott.emp表數據。
答案:查不了了(和系統權限不一樣,剛好相反)
最後總結:
系統權限 with admin option 回收時不級聯回收
對象權限 with grantoption 回收時級聯回收
角色的管理:
一組權限的集合,目的是爲了簡化對權限的管理。
請看一個問題:假設有用戶123,爲了讓他們擁有權限:
連接數據庫,在scott.emp表上select,insert,update,如果採用直接授權,則需要12次授權。
解決辦法:角色 解決具體方法見後面
角色的分類:
①預定義角色(33種)
常用的有(connect,dba,resource)
?查詢某個角色具有哪些權限?//查詢時名字一定要大寫
SQL>select* from dba_sys_privs where grantee='DBA';//查詢時名字一定要大寫
SQL>select* from dba_sys_privs where grantee='CONNECT';
SQL>select * from dba_sys_privs where grantee='RESOURCE';
system和sys是用戶,但是可以如是查詢:
?如何知道某個用戶具有什麼角色?
SQL>select * from dba_sys_privs where grantee='SYSTEM';
SQL>select * from dba_sys_privs where grantee='SYS';
SQL>select * from dba_sys_privs where grantee='XIAOQIANG';
具有應用開發人員需要的大部分權限,只要給用於授予connect和resource權限即可。
需要注意的是:resource角色隱含了unlimited tablespace(表空間無限制),查詢不出來。
案例:
創建一個用戶,然後賦給connect角色:
create user aaa identified bym123;
grant connect to aaa;
DBA角色:具有所有的系統權限,with admin option選項,默認dba用戶爲sys和system他們可以將任何系統權限授予給其他用戶,但是注意DBA不具備啓動和關閉數據庫。
案例:
創建一個用戶,然後賦給DBA角色:
create user jack identified bym123;
grant dba to jack;
②自定義角色
oracle設計者,認爲33種預定義角色可能不能滿足所有需求,所以可以使用自定義角色。
建立角色(不驗證):如果角色是公用的角色,可以採用不驗證的方式建立角色(常用):
create role 角色名 not identified;
create role 角色名 identified by 密碼;
案例:
請看一個問題:假設有用戶123,爲了讓他們擁有權限:
連接數據庫,在scott.emp表上select,insert,update,如果採用直接授權,則需要12次授權。
解決辦法:
create role myrole not identified;
grant create session to myrole;
grant select on scott.emp to myrole;
grant insert on scott.emp to myrole;
grant update on scott.emp to myrole;
grant myrole to 123;
分配角色:
grant 角色名 to 用戶名 [with admin option];
一般分配角色是由DBA(即sys/system)來完成的,若要求其他用戶身份分配角色,則要求用戶必須具有grant any role系統權限。
with admin option 授予權限的用戶或是角色還可以將該系統權限授予其它的用戶
刪除角色:
drop role 角色名;(DBA來執行,其他用戶要求具有drop any role系統權限)
21.PL/SQL
以下在scott/tiger賬號下演示:
pl/sql(procedural language/sql):oracle在標準的sql語言上的擴展,允許使用條件和循環語句。
缺點:移植性不好,無法誇平臺
優點:提供應用程序運行性能,模塊化設計思想[分頁過程,訂單過程,轉賬過程],減少網絡帶寬,提供安全性
(1)存儲過程簡單版本
eg:開發一個簡單的存儲過程,可以完成向某表中添加一條記錄:
創建存儲過程基本語法:
create procedure 過程名(參數1…)
is
begin
執行語句;
end;
create procedure proc1
is
begin
insertinto emp(empno,ename) values(444,'4444');
end;
調用存儲過程基本語法:
1.sqlplus控制檯
execute/call 過程名(參數1…);
2.java程序調用 src裏面
使用collableStatement接口
返回可能是一個值也可能是一個集合
create procedure proc2(in_empnonumber)
is
begin
deletefrom emp where empno=in_empno;
end;
塊(編程):過程(存儲過程)、函數、包(包體)、觸發器。塊是他們的基本編程單元。
|
編寫規範
註釋:單行註釋--
多行註釋/*……*/
表示符號的命名規範:塊(block)的開發
PL/SQL塊由3個部分構成:定義部分、執行部分、例外處理部分declare
/*定義部分--定義常量、變量、遊標、複雜數據類型*/
begin
/*執行部分--要執行的pl/sql語句和sql語句*/
exception
/*例外處理部分--處理運行的各種錯誤*/
end;
相關說明:dbms_output是oracle所提供的包(類似java),該包包含一些過程,put_line就是dbms_output包的一個過程。
特別說明:在默認情況下,“hello world”不輸出,需要setserveroutput on;
declare
--定義變量的格式是:變量名稱 變量的類型
--和建表一樣
v_ename varchar2(10);
begin
--把指定僱員編號查詢得到的姓名值放入v_ename變量中
select ename into v_ename from emp where empno=&empno;
dbms_output.put_line('僱員名字是'||v_ename);
end;
將上面的塊改爲過程:
create procedure pro4(in_empno number)
is
--declare 這個就不要了 塊才需要declare指定
--定義變量的格式是:變量名稱 變量的類型
--和建表一樣
v_ename varchar2(10);
begin
--把指定僱員編號查詢得到的姓名值放入v_ename變量中
select ename into v_ename from emp where empno=in_empno;
dbms_output.put_line('僱員名字是'||v_ename);
end;
【特別注意】:
&:表示要接受從控制檯輸入的變量
||:表示兩個字符串拼接
declare
v_ename varchar2(10);
begin
select ename into v_ename from emp where empno=110;
dbms_output.put_line('僱員名字是'||v_ename);
end;
oracle只提示“未找到數據”,不準確,爲此,我們加入exception異常處理機制:
declare
v_ename varchar2(10);
begin
select ename into v_ename from emp where empno=110;
dbms_output.put_line('僱員名字是'||v_ename);
exception
when no_data_found then
dbms_output.put_line('朋友,你輸入的編號有誤!');
end;
對該案例的細節異常說明:
案例:請考慮編寫一個過程,可以輸入僱員名,新工資,可修改僱員的工資
--請考慮編寫一個過程,可以輸入僱員名,新工資,可修改僱員的工資
create or replace procedure pro5(in_ename in varchar2,in_new_sal in number)
is
begin
update emp set sal=in_new_sal where ename=in_ename;
end;
(3)函數
eg:開發一個簡單的存儲過程,可以完成向某表中添加一條記錄:創建函數基本語法:
create function 函數名(參數1…)
return 數據類型
is
定義變量;
begin
執行語句;
end;
案例:編寫一個函數,可以接受用戶名並返回該用戶的年薪
create or replace function fun1(in_v_ename varchar2)
return number--這裏不要分號
is
--定義一個變量來接受年薪
v_annual_sal number;
begin
select sal+nvl(comm,0)*13 into v_annual_sal from emp
where ename=in_v_ename;
return v_annual_sal;
end;
sqlplus調用:select fun1('KING') from dual;
(4)包
使用包可以更好的管理 自己寫的函數、過程
①包的規範只包含了過程和函數的說明,沒有具體實現代碼。
創建包基本語法:
createor replace package 包名
is
--聲明過程
function 過程名(參數1…) return 返回類型;
--聲明過程
procedure 函數名(參數1…) return 返回類型;
end;
create or replace package mypackage1
is
--聲明一個過程
procedure pro5(v_in_ename varchar2,v_in_newsal number);
--聲明一個函數
function fun1(v_in_ename varchar2) return number;
end;
②包體用於實現包規範中的過程和函數。之前首先得建立包規範
創建包體基本語法:
create or replace package body 包名
is
--實現過程
function 過程名(參數1…) return 返回類型
is
--定義變量
begin
--執行語句
end;
--實現函數
procedure 函數名(參數1…) return 返回類型
is
--定義變量
begin
--執行語句
end;
end;
create or replace package body mypackage1
is
--實現一個過程
procedure pro5(v_in_ename varchar2,v_in_newsal number)
is
v_empno varchar2(32);
begin
select empno into v_empno from emp where ename=v_in_ename;
update emp set sal=v_in_newsal where ename=v_in_ename;
exception
when no_data_found then
dbms_output.put_line('朋友,你輸入的編號有誤!');
end;
--實現一個函數
function fun1(v_in_ename varchar2) return number
is
--定義一個變量來接受年薪
v_annual_sal number;
begin
select sal+nvl(comm,0)*13 into v_annual_sal from emp
where ename=v_in_ename;
return v_annual_sal;
end;
end;
在PL/SQLDeveloper下,用賬號scott/tiger登錄後
New—>Command Window—>然後在Edit窗口複製
上面命令,按F8運行,然後按/和Enter,後,出現
編譯錯誤,請運行show error
運行:
execmypackage1.pro5('KING',12);
selectscott.mypackage1.fun1('KING') from dual;
最後總結:先聲明包規範,再進行創建包體。
(5)觸發器
觸發器就是隱含的執行的存儲過程,類似監聽事件。定義觸發器時要指定觸發的事件和操作。
不是由程序員/DBA來顯示調用,而是因爲某個操作引發執行的。
常用觸發器事件:insert/update/delete,實際就是一個PL/SQL塊。
【提出問題】
①當用戶登錄時,自動記錄該用戶名字,登錄時間,ip…
②當用戶在星期天對某張表進行delete時,我們提示不能這樣操作
③當用戶刪除某條記錄的時候,自動將該記錄保存到另外一張表去
【解決辦法】觸發器
觸發器的分類
DM(數據操作語言,關於表中數據操作)L觸發器:
DDL(數據定義語言,關於表的操作)觸發器:
系統觸發器(與胸相關的觸發器,比如用戶登錄退出,關閉啓動數據庫)
procedure raise_application_error(error_number_inin number,error_msg_invarchar2);
error_number_in[自定義] 從-20000到-20999之間,這樣就不會與oracle的任何錯誤代碼發生衝突。
error_msg_in[自定義]不能超過2K,否則截取2K。
--②當用戶在星期天對某張表進行delete時,我們提示不能這樣操作
create or replace trigger tri1
before delete on scott.emp
begin
if to_char(sysdate,'day') in ('星期五','星期六') then
dbms_output.put_line('對不起,休息日不能刪除員工');
raise_application_error(-20001,'對不起,休息日不能刪除員工');
end if;
end;
使用條件謂詞case…when和insert等詞:
--②當用戶在星期天對某張表進行delete時,我們提示不能這樣操作
create or replace trigger tri1
before insert or update or delete on scott.emp
begin--更加精準的告訴你正在做什麼
case
when inserting then
dbms_output.put_line('請不要添加');
raise_application_error(-20001,'請不要添加');
when updating then
dbms_output.put_line('請不要修改');
raise_application_error(-20002,'請不要修改');
when deleting then
dbms_output.put_line('請不要刪除');
raise_application_error(-20003,'請不要刪除');
end case;
end
使用:old和:new
【提出問題】當觸發器被觸發時,要使用被插入、更新或刪除的記錄中的列值,有時要使用操作前、後列值
:old:修飾符訪問操作完成後列的值
:new:修飾符訪問操作完成前列的值
特性 |
insert |
update |
delete |
old |
null |
有效 |
有效 |
new |
有效 |
有效 |
null |
案例:
①在修改emp表僱員薪水時,顯示僱員工資修改前和修改後的值
②如何確保修改員工工工資不能低於原有工資
create or replace trigger tri4
before update on scott.emp
for each row--這個一定要 是行級 不是表級
begin
if :new.sal<:old.sal then
dbms_output.put_line('工資不能低於原來工資');
raise_application_error(-2005,'工資不能低於原來工資');
else
dbms_output.put_line('原來工資是'||:old.sal||'現在工資'||:new.sal);
end if;
end;
案例:
編寫一個觸發器,保證當用戶刪除一張表(emp)記錄的時候,自動把刪除的記錄備份到另外一張表(emp_bak)
--1.實現建立一張備份表
create table SCOTT.emp_bak
( "EMPNO" NUMBER(4,0),
"ENAME" VARCHAR2(10),
"JOB" VARCHAR2(9),
"MGR" NUMBER(4,0),
"HIREDATE" DATE,
"SAL" NUMBER(7,2),
"COMM" NUMBER(7,2),
"DEPTNO" NUMBER(2,0)
);
--2.建立觸發器
create or replace trigger tri5
before delete on scott.emp
for each row--這個一定要 是行級 不是表級
begin
--執行語句
insert into emp_bak values(:old.empno,
:old.ename,:old.job,:old.mgr,
:old.hiredate,:old.sal,:old.comm,:old.deptno);
end;
這裏我們設計的時候,可以保存一個還原點:
savepoint a; --創建保存點
DELETE FROMstudent;
rollback to a; --恢復到保存點
一個有經驗的DBA,在確保完成無誤的情況下要定期創建還原點。
DROP TABLE student; --刪除表的結構和數據;
delete fromstudent WHERExh = 'A001'; --刪除一條記錄;
truncate TABLE student; --刪除表中的所有記錄,表結構還在,不寫日誌,無法找回刪除的記錄,速度快。
見p
案例:
編寫一個觸發器,如何控制員工薪水不能低於原來工資,同時也不能高出原來工資的20%,使用約束顯然無法實現該規則。
create or replace trigger tri6
before update on scott.emp
for each row--這個一定要 是行級 不是表級
begin
--執行語句
if :new.sal<:old.sal || :new.sal>:old.sal*1.2 then
dbms_output.put_line('工資範圍不對!');
--阻止執行
raise_application_error(-20010,'工資範圍不對');
end if;
end;
系統觸發器
(由DBA創建系統觸發器) 一般由系統管理員來完成
系統時間指基於Oracle事件(startup,startdown等)所建立的觸發器,通過使用系統事件觸發器,提供了跟蹤系統或數據庫變化的機制。下面這個5個屬性可以直接返回值,直接使用
ora_client_ip_address//返回客戶端的ip
ora_database_name//返回數據庫名
ora_login_user//返回登錄用戶名
ora_sysevent//返回觸發器的系統事件名
ora_des_encrypted_password//返回用戶des(md5)加密後的密碼
基本語法:
create [or replace] trigger觸發器名
{before | after}
{logon|logoff}
on database
begin
--觸發器內容
end;
案例:
記錄用戶的登錄和退出事件,我們可以建立登錄和退出觸發器,爲了記錄用戶名稱,事件,ip地址,我們首先建立一張信息表。
--完成登錄(logon)和退出(logoff)的系統觸發器
--1.創建一張表,來保存用戶登錄信息
create table log_table(
username varchar2(20),
logon_time date,
logoff_time date,
address varchar2(20));
--2.創建觸發器
--登錄觸發器
create or replace trigger tri8
after logon on database--登錄後就記錄
begin
insert into log_table(username,logon_time,address)
values(ora_login_user,sysdate,ora_client_ip_address);
end;
--退出觸發器
create or replace trigger tri9
before logoff on database--退出前就記錄
begin
insert into log_table(username,logoff_time,address)
values(ora_login_user,sysdate,ora_client_ip_address);
end;
DDL觸發器
(對錶定義刪除的相關信息記錄 需要DBA創建) 一般由系統管理員來完成
基本語法:
create [or replace] trigger觸發器名
{before | after} ddl
on 方案名.schema
begin
--觸發器內容
end;
【最後強調】
在oracle中,DML語句需要手動提交
DDL語句(創建觸發器、表、過程)自動提交
當oracle退出時,會自動提交DML語句
案例:
--編寫一個觸發器,編寫某一個用戶進行的ddl操作
--1.創建一張表,來保存用戶登錄信息
create table ddl_record(
event varchar2(64),
username varchar2(64),
ddl_time);
--2.創建觸發器
create or replace trigger tri9
after ddl on scott.schema
begin
insert into ddl_record values(ora_sysevent,ora_login_user,sysdate);
end;
管理觸發器
禁止觸發器:讓觸發器臨時失效
alter trigger 觸發器名 disable;
激活觸發器:
alter trigger 觸發器名 enable;
禁止或激活觸發表的所有觸發器:
alter table emp disable alltrigger;
alter table emp enable alltrigger;
刪除觸發器:
drop trigger 觸發器名;
PL/SQL語法數據類型
①標量類型(scalar)
名稱 [constant] 數據類型 [not null] [:=初始值]
constant:指定常量,需要指定它的初始值,且其值是不能改變的
e.g:
定義一個變長字符串 v_enamevarchar2(10)
定義一個小數 範圍-9999.99-9999.99 v_sal number(6,2);
定義一個小數並給一個初始值5.4 v_salnumber(6,2):=5.4 := 是pl/sql的賦值號
定義一個日期類型的數據 v_hiredate date;
定義一個布爾變量,不能爲空初始值爲false v_valid Boolean:=false
案例:以輸入員工號,顯示僱員姓名、工資、個人所得稅(稅率爲0.03)
create or replace procedure pro2(v_in_empno in number) is
--定義變量
v_tax_rate number(3,2):=0.03;
v_sal number;
v_ename varchar2(32);
v_tax number;
begin
select ename,sal into v_ename,v_sal from emp
where empno=v_in_empno;
--計算個人所得稅
v_tax:=v_sal*v_tax_rate;
dbms_output.put_line(v_ename||'工資='||v_sal||'個人所得稅:'||v_tax);
end;
sqlplus調用:exec pro2(7839);
爲了讓v_ename類型更加靈活,我們使用%type v_ename emp.ename%type;
讓我們在PL/SQL編程中,讓變量類型和大小與表的列的大小和類型一致。
②複合類型(composite)
PL/SQL記錄
類似與高級語言中的結構體,但當引用pl/sql記錄成員時,必須要加記錄變量作爲前綴。
基本語法:
type 自定義的pl/sql記錄名 is record(
變量名 變量類型,
變量名 變量類型
)
//使用自定義的pl/sql記錄名
變量名 自定義的pl/sql記錄名;
案例:請編寫一個過程,該過程可以接受一個用戶編號,並顯示該用戶名字,薪水,工作崗位
create or replace procedure pro3(v_in_empno in number)is
--定義一個記錄數據類型
type emp_record is record(
v_ename emp.ename%type,
v_sal emp.sal%type,
v_job emp.job%type
);
--定義一個變量,其類型是emp_record
v_emp_record emp_record;
begin
select ename,sal,job into v_emp_record from emp
where empno=v_in_empno;
dbms_output.put_line('名字'||v_emp_record.v_ename||'薪水'||v_emp_record.v_sal||'崗位'||v_emp_record.v_job);
end;
sqlplus調用:exec pro3(7902);
PL/SQL表
相當於java中的數組
基本語法:
type 自定義的pl/sql數據類型istableof emp.sal%type index by binary_integer;
定義一個這樣變量
//使用自定義的pl/sql記錄名
變量名 自定義的pl/sql記錄名;
declare
type hao_table_type is table of emp.ename%type index by binary_integer;
--定義一個變量:sp_table:類型
hao_table hao_table_type;
begin
select ename into hao_table(-1) from emp where empno=7788;
dbms_output.put_line('員工'||hao_table(-1));
end;
--說明 hao_table_type 是pl/sql類型
-------emp.ename%type 指定了表的類型和長度
-------sp_table爲pl/sql表變量
-------hao_table(0)則表示下標爲0的元素 pl/sql下標都可以爲負數
③參照類型(遊標)(reference)
遊標變量:通過遊標,我們可以取得返回結果集(往往是select結果)的任何一行數據,從而提供共享的效率
--②在①基礎上,若某個員工的工資低於200元,就增加100元
create or replace procedure pro1(v_in_deptno number) is
--先定義一個遊標變量類型 一個變量類型可以定義多個變量
type emp_cursor is ref cursor;
--定義1個遊標變量
v_emp_cursor emp_cursor;
--定義2個變量
v_ename emp.ename%type;
v_sal emp.sal%type;
v_empno emp.empno%type;
begin--兩個空格
--執行語句
--打開遊標
open v_emp_cursor for select ename,sal,empno from emp
where deptno=v_in_deptno;
--取出遊標指向的每行數據,用循環語句
loop
fetch v_emp_cursor into v_ename,v_sal,v_empno;--這句 導致遊標往下移
--判斷當前遊標是否達到最後
exit when v_emp_cursor%notfound;
--輸出 輸出在判斷之後,先判斷,否則重複輸出(最後一行)
dbms_output.put_line('用戶名'||v_ename||' 薪水'||v_sal);
----------------------------更改地方-----------------------------
if v_sal<200 then
update emp set sal=sal+100 where empno=v_empno;
end if;
end loop;
--關閉遊標[完後一定要關閉遊標]
close v_emp_cursor;
end;
(6)PL/SQL進階控制結構
①條件分支語句
pl/sql中提供了三種條件分支語句:if——then if——then——else if——then——elsif——else
案例:編寫一個過程,輸入一個僱員,如果該僱員的補助不是0就在原來基礎上增加100,如果補助爲0就把補助設爲200,空的話就設爲150.
create or replace procedure pro6(v_in_ename varchar2) is
v_comm emp.comm%type;
begin
--查詢補助
select comm into v_comm from emp where ename=v_in_ename;
--if v_comm is null
if v_comm<>0 then--這裏把comm空值也加進去了
update emp set comm=comm+100 where ename=v_in_ename;
else
update emp set comm=200 where ename=v_in_ename;
end if;
end;
②循環語句loop|while|for
見PL/SQL語法數據類型--參照類型案例,可以進行循環插入記錄利用存儲過程
基本語法:
loop
--執行語句;
exit when 條件表達式;
--執行語句;
end loop;
基本語法:
while 條件表達式loop
--執行語句;
end loop;
基本語法:
begin
for iin reverse 1..10 loop
insert into users values(i,);
end loop;
end;--我們看到控制變量i隱形增加
【最終完結】
1)在is……begin間不能對變量賦值,如果要重新賦值,則需要在begin……end間。
2)PL/SQL中,不能對輸入參數的值,重新賦值。
②goto|null
goto語句用於跳轉到特定標號去執行語句,最好不要用。
null語句不會執行任何操作,只是提高代碼可讀性。
declare
i number:=1;
begin
<<start_loop>>
loop
dbms_output.put_line('輸出i='||i);
if i=12 then
goto end_loop;
end if;
i:=i+1;
if i=10 then
goto start_loop;
end if;
end loop;
<<end_loop>>
dbms_output.put_line('循環結束');
end;
declare
v_sal emp.sal%type;
v_ename emp.ename%type;
begin
select ename,sal into v_ename,v_sal
from emp
where empno=&no;
if v_sal<3000 then
update emp set comm=sal*0.1
where ename=v_ename;
else null;
end if;
end;
(7)PL/SQL進階分頁過程
【注意事項】
oracle存儲過程沒有返回值,它的所有返回值都是通過out參數來替代的
若返回是結果集,就不必須用package關於存儲過程java調用的程序 詳細請見src/oracle_itcast
(8)PL/SQL進階例外
基本語法:
begin
--執行語句
exception
when 例外名稱 then
--執行語句
when 例外名稱 then
--執行語句;
when others then
--其他
end;
--編寫一個過程,輸入僱員編號,顯示僱員姓名,若編號不存在就會有異常
create or replace procedure pro10(v_in_empno in number) is
v_ename emp.ename%type;
begin
select ename into v_ename from emp where empno=v_in_empno;
dbms_output.put_line('名字是'||v_ename);
Exception
when no_data_found then
dbms_output.put_line('朋友!你輸入的編號不存在');
when others then
dbms_output.put_line('不明錯誤');
end;
記得:set serveroutput on;
常見的幾種例外:
例外情況名稱 |
錯誤代碼 |
描述 |
no_data_found |
ora-01403 |
對於select敘述沒有傳回任何值 |
too_many_rows |
ora_01427 |
只允許傳回一筆記錄的select敘述結果卻多餘一筆 |
invalid_cursor |
ora-01001 |
使用非法的光標操作 |
value_error |
ora-06502 |
出現數值、數據形態轉換、截取字符串或強制性的錯誤 |
invalid_number |
ora-01722 |
字符串到數值的轉換失敗 |
zero_divide |
ora-01476 |
被零除 |
dup_val_on_index |
ora-00001 |
視圖向具有唯一鍵值的索引中插入一個重複鍵值 |
case_not_found |
ora-06592 |
沒有case條件匹配 |
cursor_not_open |
ora-06511 |
遊標沒有打開 |
(9)視圖
oracle的又一種數據對象,虛擬表,視圖的主要用處是簡化操作,提高安全,滿足不同用戶查詢需求,視圖不是一個真正存在的物理表。它是根據別的表動態生成的。
基本語法:
創建視圖:
createview 視圖名 as select 語句[withread only];
創建或修改視圖:
create or replace view 視圖名 asselect 語句[with read only];
刪除視圖:
drop view視圖名;
需要DBA給scott授予創建視圖權限:grantcreate view to scott;
視圖與表的區別:
1.表需佔磁盤空間視圖不需
2.視圖不能添加索引
3.使用視圖可簡化複雜查詢
4.視圖有利於提供安全性
with read only可以進行只讀
22.數據庫管理+表的邏輯備份與恢復
數據庫管理員
每個oracle數據庫應該至少有一個數據庫管理員(dba),對於一個小的數據庫,一個dba就夠了,但是對於一個大的數據庫可能需要多個dba分擔不同的管理職責。那麼一個數據庫管理員的主要工作是什麼呢:
職責
1.安裝和升級oracle數據庫
2.建庫,表空間,表,視圖,索引…
3.制定並實施備份和恢復計劃
4.數據庫權限管理,調優,故障排除
5.對於高級dba,要求能參與項目開發,會編寫sql語句、存儲過程、觸發器、規則、約束、包
管理數據庫的用戶主要是sys和system
(sys好像是董事長,system好像是總經理,董事長比總經理大,但是通常是總經理幹事)
在前面我們已經提到這兩個用戶,區別主要是:
1.最重要的區別,存儲的數據的重要性不同
sys:所有oracle的數據字典的基表和視圖都存放在sys用戶中,這些基表和視圖對於oracle的運行是至關重要的,由數據庫自己維護,任何用戶都不能手動更改。sys用戶擁有dba,sysdba,sysoper角色或權限,是oracle權限最高的用戶。
system:用於存放次一級的內部數據,如oracle的一些特性或工具的管理信息。system用戶擁有dba,sysdba角色或系統權限。
sysdba角色可以建數據庫,sysoper不能建數據庫
2. 其次的區別,權限的不同。
sys用戶必須以as sysdba或as sysoper形式登錄。不能以normal方式登錄數據庫
system如果正常登錄,它其實就是一個普通的dba用戶,但是如果以as sysdba登錄,其結果實際上它是作爲sys用戶登錄的,從登錄信息裏面我們可以看出來。
sysdba和sysoper權限區別圖,看圖:
sysdba>sysoper>dba
可以看到:只要是sysoper擁有的權限,sysdba都有;藍色是它們區別的地方。(它們的最大區別是:sysdba可以創建數據庫,sysoper不可以創建數據庫)
dba權限的用戶
dba用戶是指具有dba角色的數據庫用戶。特權用戶可以執行啓動實例,關閉實例等特殊操作,而dba用戶只有在啓動數據庫後才能執行各種管理工作。(相當於說dba連startup和shutdown這兩個權限都沒有)
兩個主要的用戶,三個重要權限,他們的區別和聯繫,大家要弄清楚
管理初始化參數
管理初始化參數(調優的一個重要知識點,憑什麼可以對數據庫進行調優呢?是因爲它可以對數據庫的一些參數進行修改修正)
初始化參數用於設置實例或是數據庫的特徵。oracle9i提供了200多個初始化參數,並且每個初始化參數都有默認值。
顯示初始化參數
(1) show parameter命令
如何修改參數
需要說明的如果你希望修改這些初始化的參數,可以到文件D:\oracle\admin\myoral\pfile\init.ora文件中去修改比如要修改實例的名字
數據庫(表)的邏輯備份與恢復
介紹
邏輯備份是指使用工具export將數據對象的結構和數據導出到文件的過程,邏輯恢復是指當數據庫對象被誤操作而損壞後使用工具import利用備份的文件把數據對象導入到數據庫的過程。
物理備份即可在數據庫open的狀態下進行也可在關閉數據庫後進行,但是邏輯備份和恢復只能在open的狀態下進行。
導出
導出具體的分爲:導出表,導出方案,導出數據庫三種方式。
導出使用exp命令來完成的,該命令常用的選項有:
userid: 用於指定執行導出操作的用戶名,口令,連接字符串
tables: 用於指定執行導出操作的表
owner: 用於指定執行導出操作的方案
full=y: 用於指定執行導出操作的數據庫
inctype: 用於指定執行導出操作的增量類型
rows: 用於指定執行導出操作是否要導出表中的數據
file: 用於指定導出文件名
導出表
1.導出自己的表
expuserid=scott/tiger@myoral tables=(emp,dept) file=d:\e1.dmp
2.導出其它方案的表
如果用戶要導出其它方案的表,則需要dba的權限或是exp_full_database的權限,比如system就可以導出scott的表
E:\oracle\ora92\bin>expuserid=system/manager@myoral tables=(scott.emp) file=d:\e2.emp
特別說明:在導入和導出的時候,要到oracle目錄的bin目錄下。
3. 導出表的結構
exp userid=scott/tiger@accptables=(emp) file=d:\e3.dmp rows=n
4. 使用直接導出方式
exp userid=scott/tiger@accptables=(emp) file=d:\e4.dmp direct=y
這種方式比默認的常規方式速度要快,當數據量大時,可以考慮使用這樣的方法。
這時需要數據庫的字符集要與客戶端字符集完全一致,否則會報錯...
導出方案
導出方案是指使用export工具導出一個方案或是多個方案中的所有對象(表,索引,約束...)和數據。並存放到文件中。
1. 導出自己的方案
exp userid=scott/tiger@myorclowner=scott file=d:\scott.dmp
2. 導出其它方案
如果用戶要導出其它方案,則需要dba的權限或是exp_full_database的權限,比如system用戶就可以導出任何方案
expuserid=system/manager@myorcl owner=(system,scott) file=d:\system.dmp
導出數據庫
導出數據庫是指利用export導出所有數據庫中的對象及數據,要求該用戶具有dba的權限或者是exp_full_database權限
增量備份(好處是第一次備份後,第二次備份就快很多了)
expuserid=system/manager@myorcl full=y inctype=complete file=d:\all.dmp
導入
導入就是使用工具import將文件中的對象和數據導入到數據庫中,但是導入要使用的文件必須是export所導出的文件。與導出相似,導入也分爲導入表,導入方案,導入數據庫三種方式。
imp常用的選項有
userid: 用於指定執行導入操作的用戶名,口令,連接字符串
tables: 用於指定執行導入操作的表
formuser: 用於指定源用戶
touser: 用於指定目標用戶
file: 用於指定導入文件名
full=y: 用於指定執行導入整個文件
inctype: 用於指定執行導入操作的增量類型
rows: 指定是否要導入錶行(數據)
ignore: 如果表存在,則只導入數據
導入表
1. 導入自己的表
impuserid=scott/tiger@myorcl tables=(emp) file=d:\xx.dmp
2. 導入表到其它用戶
要求該用戶具有dba的權限,或是imp_full_database
impuserid=system/tiger@myorcl tables=(emp) file=d:\xx.dmp touser=scott
3. 導入表的結構
只導入表的結構而不導入數據
impuserid=scott/tiger@myorcl tables=(emp) file=d:\xx.dmp rows=n
4. 導入數據
如果對象(如比表)已經存在可以只導入表的數據
impuserid=scott/tiger@myorcl tables=(emp) file=d:\xx.dmp ignore=y
導入方案
導入方案是指使用import工具將文件中的對象和數據導入到一個或是多個方案中。如果要導入其它方案,要求該用戶具有dba的權限,或者imp_full_database
1. 導入自身的方案
impuserid=scott/tiger file=d:\xxx.dmp
2. 導入其它方案
要求該用戶具有dba的權限
impuserid=system/manager file=d:\xxx.dmp fromuser=system touser=scott
導入數據庫n
在默認情況下,當導入數據庫時,會導入所有對象結構和數據,案例如下:
impuserid=system/manager full=y file=d:\xxx.dmp
23.數據字典和動態性能視圖
數據字典是oracle數據庫中最重要的組成部分,它提供了數據庫的一些系統信息。
動態性能視圖記載了例程啓動後的相關信息。
數據字典
數據字典記錄了數據庫的系統信息,它是隻讀表和視圖的集合,數據字典的所有者爲sys用戶。
用戶只能在數據字典上執行查詢操作(select語句),而其維護和修改是由系統自動完成的。
這裏我們談談數據字典的組成:數據字典包括數據字典基表和數據字典視圖,其中基表存儲數據庫的基本信息,普通用戶不能直接訪問數據字典的基表。數據字典視圖是基於數據字典基表所建立的視圖,普通用戶可以通過查詢數據字典視圖取得系統信息。數據字典視圖主要包括user_xxx,all_xxx,dba_xxx三種類型。
user_tables;
用於顯示當前用戶所擁有的所有表,它只返回用戶所對應方案的所有表
比如:selecttable_name from user_tables;
all_tables;
用於顯示當前用戶可以訪問的所有表,它不僅會返回當前用戶方案的所有表,還會返回當前用戶可以訪問的其它方案的表:
比如:selecttable_name from all_tables;
dba_tables;
它會顯示所有方案擁有的數據庫表。但是查詢這種數據庫字典視圖,要求用戶必須是dba角色或是有select any table系統權限。
例如:當用system用戶查詢數據字典視圖dba_tables時,會返回system,sys,scott...方案所對應的數據庫表。
用戶名,權限,角色
在建立用戶時,oracle會把用戶的信息存放到數據字典中,當給用戶授予權限或是角色時,oracle會將權限和角色的信息存放到數據字典。
通過查詢dba_users可以顯示所有數據庫用戶的詳細信息;
通過查詢數據字典視圖dba_sys_privs,可以顯示用戶所具有的系統權限;
通過查詢數據字典視圖dba_tab_privs,可以顯示用戶具有的對象權限;
通過查詢數據字典dba_col_privs可以顯示用戶具有的列權限;
通過查詢數據庫字典視圖dba_role_privs可以顯示用戶所具有的角色。
這裏給大家再講講角色和權限的關係。
例如:要查看scott具有的角色,可查詢dba_role_privs;
SQL> select *from dba_role_privs where grantee='SCOTT';
//查詢orale中所有的系統權限,一般是dba
select * fromsystem_privilege_map order by name;
//查詢oracle中所有對象權限,一般是dba
select distinctprivilege from dba_tab_privs;
//查詢oracle中所有的角色,一般是dba
select * fromdba_roles;
//查詢數據庫的表空間
selecttablespace_name from dba_tablespaces;
問題1:如何查詢一個角色包括的權限?
a.一個角色包含的系統權限
select * from dba_sys_privs where grantee='角色名'
另外也可以這樣查看:
select * from role_sys_privs where role='角色名'
b.一個角色包含的對象權限
select * from dba_tab_privs where grantee='角色名'
問題2:oracle究竟有多少種角色?
SQL> select *from dba_roles;
問題3:如何查看某個用戶,具有什麼樣的角色?
select * fromdba_role_privs where grantee='用戶名'
顯示當前用戶可以訪問的所有數據字典視圖。n
select * from dictwhere comments like '%grant%';
顯示當前數據庫的全稱n
select * fromglobal_name;
其它說明
數據字典記錄有oracle數據庫的所有系統信息。通過查詢數據字典可以取得以下系統信息:比如
1.對象定義情況
2.對象佔用空間大小
3.列信息
4.約束信息
...
但是因爲這些個信息,可以通過pl/sqldeveloper工具查詢得到,所以這裏我就飄過。
動態性能視圖
動態性能視圖用於記錄當前例程的活動信息,當啓動oracle server時,系統會建立動態性能視圖;當停止oracle server時,系統會刪除動態性能視圖。oracle的所有動態性能視圖都是以v_$開始的,並且oracle爲每個動態性能視圖都提供了相應的同義詞,並且其同義詞是以V$開始的,例如v_$datafile的同義詞爲v$datafile;動態性能視圖的所有者爲sys,一般情況下,由dba或是特權用戶來查詢動態性能視圖。
因爲這個在實際中用的較少,所以飛過。
24.oracle的卸載
一般的應用程序,安裝後,可以通過uninstall工具來卸載,但是oracle沒有,oracle卸載步驟如下:
1.先停止oracle的所有服務
2.使用Oracle universal installer(OUI)來完成初步卸載(該工具不會把oracle註冊表信息清除,所以會把我們後續安裝oracle或升級oracle帶來麻煩)
3.到註冊表中刪除oracle的註冊信息(regedit命令),刪除下面內容:
①HKEY_LOCAL_MACHINE—>Software—>Oracle 刪除此鍵
②HKEY_LOCAL_MACHINE—>System—> CurrentControlSet—>Services刪除Services鍵下所有以oracle爲首的鍵
③HKEY_LOCAL_MACHINE—>System—> CurrentControlSet—>Services—>Eventlog—>Application刪除此鍵下的所有以oracle爲首的鍵
④HKEY_CLASSES_ROOT刪除此鍵下的所有以Ora、Oracle、EnumOra爲前綴的鍵
⑤HKEY_CURRENT_USER—>Software—>Microsoft—>Windows—>CurrentVersion—>Explorer—>MenuOrder—>StartMenu—>Programs刪除此鍵下的所有以Oracle爲首的鍵
⑥HKEY_LOCAL_MACHINE—>Software—>ODBC—>ODBCINST.INI註冊鍵,刪除Microsoft ODBC FORORACLE註冊表鍵以外的所有有Oracle字樣的鍵值。
⑦HKEY_LOCAL_MACHINE—>System—>CurrentControlSet—>Services刪除以Oracle或OraWeb爲前綴的鍵
4.刪除環境變量CLASSPATH,PATH中含有Oracle字樣的值
5.最後再文件系統內刪除ORACLE相關的文件及目錄,刪除系統盤符:\Program Files\Oracle目錄;刪除ORCLE_BASE目錄
我無法刪除D:\oracle目錄,重新啓動機器之後才刪除
在默認情況下,oracle卸載並不會刪除你的數據庫文件,所以你手動刪除出現錯誤,如果刪除出現錯誤,則重啓後再刪除
25.尚學堂SQL簡單講解
descemp 描述表信息
desc dept
desc salgrade
select ename,sal*12 as 年薪 from emp;
數據庫中兩個單引號來替代一個單引號
selectename || 'adfa''s' from emp;
||連接字符串
selectdistinct deptno,job from emp;
lower函數
chr(65) accii碼轉換成字符
ascii(A) 字符轉換成accii碼
round(23.54) 四捨五入
round(23.236,2)四捨五入到小數點後面2位
round(23.236,-1) 四捨五入到十位數
在oracle中先將scott賬戶解鎖,然後使用scott賬戶可以看到emp表
Oracle常用函數
(1)trunc(for date)
這裏注意 to_date date是日期值 所以轉換後是不含有時間
TRUNC(for date)TRUNC函數爲指定元素而截去的日期值。
其具體的語法格式如下: TRUNC(date[,fmt])
其中:date一個日期值,fmt日期格式,該日期將由指定的元素格式所截去。忽略它則由最近的日期截去
下面是該函數的使用情況:(mi minute 分鐘的意思)
select trunc(to_date('2012-03-2323:59:59','yyyy-mm-dd hh24:mi:ss')) from dual
系統定義表,只有一筆記錄.可以用來返回函數值.select user from dual;返回當前用戶.dual爲了完善語義,因爲沒有from oracle中是報錯的
-- return date : 2012-3-23
trunc(sysdate,'yyyy') --返回當年第一天.
trunc(sysdate,'mm') --返回當月第一天.
trunc(sysdate,'d') --返回當前星期的第一天(如2012-07-11所在星期的第一天是2012-07-08)
(2)trunc(number)
TRUNC函數返回處理後的數值,其工作機制與ROUND函數極爲類似,只是該函數不對指定小數前或後的部分做相應舍入選擇處理,而統統截去。
其具體的語法格式如下TRUNC(number[,decimals])
其中:number待做截取處理的數值,decimals指明需保留小數點後面的位數。可選項,忽略它則截去所有的小數部分
下面是該函數的使用情況:
TRUNC(89.985,2)=89.98
TRUNC(89.985)=89
TRUNC(89.985,-1)=80
注意:第二個參數可以爲負數,表示爲小數點左邊指定位數後面的部分截去,即均以0記。與取整類似,比如參數爲1即取整到十分位,如果是-1,則是取整到十位,以此類推;如果所設置的參數爲負數,且負數的位數大於整數的字節數的話,則返回爲0。如:TRUNC(89.985,-3)=0.
(3)to_char
把日期或數字轉換爲字符串;to_date是把字符串轉換爲數據庫中得日期類型
使用TO_CHAR函數處理數字:TO_CHAR(number, '格式');TO_CHAR(salary,’$99,999.99’);
使用TO_CHAR函數處理日期: TO_CHAR(date,’格式’);
(4)to_date
使用TO_DATE函數將字符轉換爲日期:TO_DATE(char[, '格式'])
e.g selectto_date('2011-11-5 4:39:57','yyyy-mm-dd hh24:mi ss') as col from dual
(5)to_number
使用TO_NUMBER函數將字符轉換爲數字:TO_NUMBER(char[, '格式'])
各種格式:
數字格式格式 |
日期格式 |
9代表一個數字 0強制顯示0 $放置一個$符 L放置一個浮動 本地貨幣符 .顯示小數點 ,顯示千位指示符
|
格式控制描述 YYYY、YYY、YY分別代表4位、3位、2位的數字年,YEAR年的拼寫 MM數字月,MONTH月的全拼,MON月的縮寫 DD數字日,DAY星期的全拼,DY星期的縮寫,AM表示上午或者下午 HH24、HH12 12小時制或24小時制,MI分鐘,SS秒鐘 SP數字的拼寫,TH數字的序數詞 “特殊字符”假如特殊字符 HH24:MI:SS AM 15:43:20 PM DD “OF” MONTH 12 OF OCTOBER DDSPTH fourteenth Date的格式 ’18-5月-84’ |
(6)instr
INSTR方法的格式爲:INSTR(源字符串,目標字符串,起始位置,匹配序號)
查詢是否匹配目標字符串
例如:INSTR('CORPORATE FLOOR','OR', 3, 2)中,源字符串爲'CORPORATE FLOOR',目標字符串爲'OR',起始位置爲3,取第2個匹配項的位置。
默認查找順序爲從左到右。當起始位置爲負數的時候,從右邊開始查找。
所以SELECT INSTR('CORPORATE FLOOR', 'OR', -1, 1) "Instring" FROM DUAL的顯示結果是:14
別名Instring
(7)substr
取得字符串中指定起始位置和長度的字符串substr( string, start_position, [ length ] )
如:
substr('This is a test', 6,2) return 'is'
substr('This is a test',6) return 'is a test'
substr('TechOnTheNet', -3,3) return 'Net'
substr('TechOnTheNet', -6,3) return 'The'select substr('Thisisatest', -4, 2) valuefrom dual
舉個例子更容易區分這兩個函數:
(8)trim
Oracle中的trim函數是用來刪除給定字符串或者給定數字中的頭部或者尾部的給定字符。
trim函數具有如下的形式trim([leading/trailing/both][匹配字符串或數值][from][需要被處理的字符串或數值])這裏如果
① 指明瞭leading表示從刪除頭部匹配的字符串
② 如果指明瞭trailing表示從刪除尾部匹配的字符串
③ 如果指明瞭both,或者不指明任何位置,則兩端都將被刪除
④如果不指明任何匹配字符串或數值則認爲是空格,即刪除前面或者後面的空格。
trim函數返回的類型是varchar2下面是一些例子:
各種情況 |
例子 |
結果 |
指明leading表示從刪除頭部匹配的字符串 |
select trim(leading '1' from '12321Tech11') from dual; |
2321Tech11 |
指明trailing表示從刪除尾部匹配的字符串 |
select trim(trailing '1' from '12321Tech11') from dual; |
12321Tech |
如果指明瞭both,或者不指明任何位置,則兩端都將被刪除 |
select trim(‘中’from‘中秋八月中‘) as詩from dual; select trim(both '1' from '12321Tech 111') from dual;
|
秋八月 2321Tech |
如果不指明任何匹配字符串或數值則認爲是空格,即刪除前面或者後面的空格 |
select trim(' tech ') as詩from dual; select trim(' ' from ' tech ') as詩from dual; select trim(0 from 7500) from dual; |
tech tech 75 |
LTRIM, RTRIM 不但可以去掉空格,還可以去掉指定字符, 如LTRIM(',aaaa',',')
ltrim rtrim
(9)translate
語法:TRANSLATE(char, from, to)
用法:返回將出現在from中的每個字符替換爲to中的相應字符以後的字符串。
若from比to字符串長,那麼在from中比to中多出的字符將會被刪除。
三個參數中有一個是空,返回值也將是空值。
舉例:SQL> select translate('abcdefga','abc','wo')返回值from dual;
返回值------- wodefgw
分析:該語句要將'abcdefga'中的'abc'轉換爲'wo',
由於'abc'中'a'對應'wo'中的'w',故將'abcdefga'中的'a'全部轉換成'w';
而'abc'中'b'對應'wo'中的'o',故將'abcdefga'中的'b'全部轉換成'o';
而'abc'中的'c'在'wo'中沒有與之對應的字符,故將'abcdefga'中的'c'全部刪除;
簡單說來,就是將from中的字符轉換爲to中與之位置對應的字符,若to中找不到與之對應的字符,返回值中的該字符將會被刪除。
在實際的業務中,可以用來刪除一些異常數據,比如表a中的一個字段t_no表示電話號碼,而電話號碼本身應該是一個由數字組成的字符串,
爲了刪除那些含有非數字的異常數據,就用到了translate函數:
SQL> delete from a, where length(translate(trim(a.t_no),'0123456789' ||a.t_no, '0123456789'))<> length(trim(a.t_no));
(10)replace
語法:REPLACE(char, search_string,replacement_string)
用法:將char中的字符串search_string全部轉換爲字符串replacement_string,沒有匹配的字符串就都不變。
舉例:
SQL> select REPLACE('fgsgswsgs', 'fk' ,'j')from dual;返回值from dual;
結果是fgsgswsgs
SQL>select REPLACE('fgsgswsgs', 'sg' ,'eeerrrttt')返回值from dual;
結果是fgeeerrrtttsweeerrrttts
分析:第一個例子中由於'fgsgswsgs'中沒有與'fk'匹配的字符串,故返回值仍然是'fgsgswsgs';
第二個例子中將'fgsgswsgs'中的字符串'sg'全部轉換爲'eeerrrttt'。
總結:綜上所述,replace與translate都是替代函數,只不過replace針對的是字符串,而translate針對的是單個字符。
(11)decode()
DECODE函數,它將輸入數值與函數中的參數列表相比較,根據輸入值返回一個對應值。函數的參數列表是由若干數值及其對應結果值組成的若干序偶形式。當然,如果未能與任何一個實參序偶匹配成功,則函數也有默認的返回值。
區別於SQL的其它函數,DECODE函數還能識別和操作空值。
語法:DECODE(control_value,value1,result1[,value2,result2…][,default_result]);
試圖處理的數值。DECODE函數將該數值與後面的一系列的偶序相比較,以決定返回值。
value1 是一組成序偶的數值。如果輸入數值與之匹配成功,則相應的結果將被返回。對應一個空的返回值,可以使用關鍵字NULL於之對應。
result1 是一組成序偶的結果值。
default_result 未能與任何一個值匹配時,函數返回的默認值。
例如:
select decode(x,1,'x is 1',2,'xis 2','others') from dual
當x等於1時,則返回‘x is 1’。
當x等於2時,則返回‘x is 2’。
否則,返回others’。
需要,比較2個值的時候,可以配合sign()函數一起使用。
SELECT DECODE( SIGN(5-6), 1 'Is Positive',-1, 'Is Nagative', 'Is Zero')from dual;
同樣,也可以用CASE實現:
SELECT CASE SIGN(5-6)
WHEN 1 THEN 'Is Positive'
WHEN-1 THEN 'Is Nagative'
ELSE'Is Zero' END
FROM DUAL
此外,還可以在Order by中使用Decode。
例如:表subject,有subject_name列。要求按照:語、數、外的順序進行排序。這時,就可以非常輕鬆的使用Decode完成要求了。
select * fromsubject order by decode(subject_name, '語文',1, '數學',2, '外語',3)
(12)nvl
nvl( ) 函數(類似於SQLSERVER的isnull)
語法: 1. NVL(eExpression1,eExpression2)
參數: 1. eExpression1,eExpression2
如果eExpression1的計算結果爲null值,則NVL( )返回eExpression2。
如果eExpression1的計算結果不是null值,則返回eExpression1。
eExpression1和eExpression2可以是任意一種數據類型。
如果eExpression1與eExpression2的結果皆爲null值,則NVL( )返回.NULL.。
1. select nvl(a.name,'空得') as namefrom student a join school b on a.ID=b.ID