- 3.1, 子查詢
- 3.2, 多列子查詢
- 3.3, 在 FROM 子句中使用子查詢
- 3.4, 單列子查詢表達式
- 3.5, 使用 SET 操作符注意事項
- 3.6, 相關子查詢
- 3.7, 相關更新,相關刪除
- 3.8, WITH 子句
控制用戶權限
- 數據庫安全性:
系統安全性
數據安全性 - 系統權限:對於數據庫的權限
- 對象權限: 操作數據庫對象的權限
- 超過一百多種有效的權限,數據庫管理員具有高級權限以完成管理任務,例如:
創建新用戶
刪除用戶
刪除表
備份表
- DBA 使用 CREATE USER 語句創建用戶:
CREATE USER user
IDENTIFIED BY password;
-
用戶創建之後, DBA 會賦予用戶一些系統權限
-
以應用程序開發者爲例, 一般具有下列系統權限:
CREATE SESSION(創建會話)
CREATE TABLE(創建表)
CREATE SEQUENCE(創建序列)
CREATE VIEW(創建視圖)
CREATE PROCEDURE(創建過程) -
賦予系統權限
GRANT create session, create table,
create sequence, create view
TO scott;
- 用戶擁有create table權限之外,還需要分配相應的表空間纔可開闢存儲空間用於創建的表
ALTER USER Tommey QUOTA UNLIMITED ON users
- 創建角色
create role manager;
- 爲角色賦予權限
grant create table, create view to manager;
- 將角色賦予用戶
GRANT manager TO TOMMEY, KOCHHAR;
- DBA 可以創建用戶和修改密碼
- 用戶本人可以使用 ALTER USER 語句修改密碼
ALTER USER scott
IDENTIFIED BY root;
- 不同的對象具有不同的對象權限
- 對象的擁有者擁有所有權限
- 對象的擁有者可以向外分配權限
- 分配表 EMP 的查詢權限
GRANT select ON emp TO sue, rich;
- 分配表中各個列的更新權限
GRANT update ON scott.departments TO Tommey
- WITH GRANT OPTION 使用戶同樣具有分配權限的權利
GRANT select, insert
ON departments
TO scott
WITH GRANT OPTION;
- 向數據庫中所有用戶分配權限
GRANT select
ON zzz.emp
TO PUBLIC;
- 查詢權限分配情況
- 使用 REVOKE 語句收回權限
- 使用 WITH GRANT OPTION 子句所分配的權限同樣被收回
REVOKE select, insert
ON departments
FROM scott;
SET運算符
- UNION 操作符返回兩個查詢的結果集的並集
SELECT employee_id, job_id
FROM employees
UNION
SELECT employee_id, job_id
FROM job_history;
- UNION ALL 操作符返回兩個查詢的結果集的並集。對於兩個結果集的重複部分,不去重。
- INTERSECT 操作符返回兩個結果集的交集
- MINUS操作符:返回兩個結果集的差集
- 在SELECT 列表中的列名和表達式在數量和數據類型上要相對應
- 括號可以改變執行的順序
ORDER BY 子句: - 使用 SET 操作符注意事項
只能在語句的最後出現
可以使用第一個查詢中的列名, 別名或相對位置 - 除 UNION ALL之外,系統會自動將重複的記錄刪除
- 系統將第一個查詢的列名顯示在輸出中
- 除 UNION ALL之外,系統自動按照第一個查詢中的第一個列的升序排列
SELECT 'sing' AS "My dream", 3 a_dummy
FROM dual
UNION
SELECT 'I`d like to teach', 4
FROM dual
UNION
SELECT 'the world to', 2
FROM dual
ORDER BY 2;
高級子查詢
- 子查詢是嵌套在 SQL 語句中的另一個SELECT 語句
- 子查詢 (內查詢) 在主查詢執行之前執行
- 主查詢(外查詢)使用子查詢的結果
- 主查詢與子查詢返回的多個列進行比較
- 多列子查詢中的比較分爲兩種:
成對比較
不成對比較
---- 返回比本部門平均工資高的員工的last_name, department_id, salary及平均工資
方法一:
select a.ename,
a.deptno,
a.sal,
(select avg(c.sal)
from emp c
where c.deptno = a.deptno
group by c.deptno) avg_sal
from emp a
where a.sal > (select avg(b.sal)
from emp b
where a.deptno = b.deptno
group by b.deptno)
方法二:
select a.ename, a.deptno, a.sal, c.avg_sal
from emp a,
(select b.deptno, avg(b.sal) avg_sal from emp b group by b.deptno) c
where a.sal > c.avg_sal
and a.deptno = c.deptno
- 單列子查詢表達式是在一行中只返回一列的子查詢
- Oracle8i 只在下列情況下可以使用, 例如:
SELECT 語句 (FROM 和 WHERE 子句)
INSERT 語句中的VALUES列表中 - Oracle9i中單列子查詢表達式可在下列情況下使用:
DECODE 和 CASE
SELECT 中除 GROUP BY 子句以外的所有子句中 - 在 CASE 表達式中使用單列子查詢
----- 顯式員工的employee_id,last_name和location。其中,若員工department_id與location_id爲1800的department_id相同,則location爲’Canada’,其餘則爲’USA’。
SELECT employee_id,
last_name,
(CASE
WHEN department_id =
(SELECT department_id FROM departments WHERE location_id = 1800) THEN
'Canada'
ELSE
'USA'
END) location
FROM employees;
- 在 ORDER BY 子句中使用單列子查詢
SELECT employee_id, last_name
FROM employees e
ORDER BY (SELECT department_name
FROM departments d
WHERE e.department_id = d.department_id);
- 相關子查詢按照一行接一行的順序執行,主查詢的每一行都執行一次子查詢
---- 若employees表中employee_id與job_history表中employee_id相同的數目不小於2,輸出這些相同id的員工的employee_id,last_name和其job_id
SELECT e.employee_id, last_name, e.job_id
FROM employees e
WHERE 2 <=
(SELECT COUNT(*) FROM job_history WHERE employee_id = e.employee_id);
- EXISTS 操作符檢查在子查詢中是否存在滿足條件的行
- 如果在子查詢中存在滿足條件的行:
不在子查詢中繼續查找
條件返回 TRUE - 如果在子查詢中不存在滿足條件的行:
條件返回 FALSE
繼續在子查詢中查找
---- 查詢公司管理者的employee_id,last_name,job_id,department_id信息
SELECT employee_id, last_name, job_id, department_id
FROM employees
outer WHERE EXISTS
(SELECT 'X' FROM employees WHERE manager_id = outer.employee_id);
---- 查詢departments表中,不存在於employees表中的部門的department_id和department_name
SELECT department_id, department_name
FROM departments d
WHERE NOT EXISTS
(SELECT 'X' FROM employees WHERE department_id = d.department_id);
- 使用相關子查詢依據一個表中的數據更新另一個表的數據
UPDATE employees e
SET department_name =
(SELECT department_name
FROM departments d
WHERE e.department_id = d.department_id);
- 使用相關子查詢依據一個表中的數據刪除另一個表的數據
- 刪除表employees中,其與emp_history表皆有的數據
DELETE FROM employees E
WHERE employee_id = (SELECT employee_id
FROM emp_history
WHERE employee_id = E.employee_id);
- 使用 WITH 子句, 可以避免在 SELECT 語句中重複書寫相同的語句塊
- WITH 子句將該子句中的語句塊執行一次並存儲到用戶的臨時表空間中
- 使用 WITH 子句可以提高查詢效率
---- 查詢公司中各部門的總工資大於公司中各部門的平均總工資的部門信息
WITH dept_costs AS
(SELECT d.department_name, SUM(e.salary) AS dept_total
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY d.department_name),
avg_cost AS
(SELECT SUM(dept_total) / COUNT(*) AS dept_avg FROM dept_costs)
SELECT *
FROM dept_costs
WHERE dept_total > (SELECT dept_avg FROM avg_cost)
ORDER BY department_name;