1. 程式人生 > 其它 >shiro(1)-簡介

shiro(1)-簡介

/*空值不同於0,凡是空值參與的運算,結果都為空(null)
DML:Data Manipulation Language 資料操作語言
DDL:Data Definition Language 資料定義語言
DCL:Data Control Language 資料控制語言

select employee_id,salary,commission_pct,salary*(1+commission_pct)
from employees
--別名
select employee_id as id,last_name name,12*salary annual_sal
from employees
select employee_id as "id",last_name "Name",12*salary annual_sal
from employees
--“||”連線符
select last_name||'`s job is '||job_id as "detail"
from employees
select last_name||'`s hire_date is '||hire_date as "details"
from employees
--“distinct”去重
select distinct department_id from employees

select employee_id,last_name,salary
from employees
where employee_id > 200
and salary > 500

select employee_id,last_name,salary
from employees
where last_name = 'Higgins'

select last_name,hire_date
from employees
where hire_date = '7-6月-1994'

select last_name,hire_date
from employees
where to_char(hire_date,'yyyy-mm-dd') = '1994-06-07'


--between包含邊界
select last_name,hire_date,salary
from employees
--where salary >= 4000 and salary <=7000
where salary between 4000 and 7000

--in的使用
select last_name,department_id,salary
from employees
--where department_id = 90 and department_id = 80 and department_id = 70
where department_id in(70,80,90)

--like的使用,'%'表示任意字元,'_'表示任何一個字元
select last_name,department_id,salary
from employees
--員工名字中末尾含有a的員工有哪些
--where last_name like '%a'
--員工名字中含有a的員工有哪些
--where last_name like '%a%'
--員工名字中第二位含有a的員工有哪些
--where last_name like '_a%'
--員工名字中第三位含有a的員工有哪些
where last_name like '__a%'

--escape後的“\”表示轉義字元,“\”可以是任意字元
select last_name,department_id,salary
from employees
where last_name like '%\_%' escape '\'

select last_name,department_id,salary,commission_pct
from employees
where commission_pct is null

優先順序:
算術運算子>連線符>比較符>is [not] null,like,[not] in>[not] between>not>and>or

--排序:desc從大到小,asc從小到大(預設排序)
select last_name,department_id,salary
from employees
where department_id = 80
order by salary desc

select last_name,department_id,salary
from employees
where department_id = 80
order by salary asc

select last_name,department_id,salary
from employees
where department_id = 80
order by salary

select last_name,department_id,salary
from employees
where department_id = 80
order by salary asc,last_name asc
--按照別名來排序
select last_name,department_id,salary,12*salary "annual_sal"
from employees
order by "annual_sal"


--查詢5000和一萬的工資的員工
select last_name,salary
from employees
--where salary >= 5000 and salary <= 10000
where salary between 5000 and 10000


--查詢工資等於6000,7000,8000,9000,10000的員工資訊
select * from employees
--where salary = 6000 or salary = 7000 or salary = 8000 or salary = 9000 or salary =10000;
where salary in(6000,7000,8000,9000,10000)

--lower 小寫,upper 大寫,initcap 首字母大寫
select lower('ATGUIGUJAVA'),UPPER('AtGuiGu Java'),initcap('ATGUIGU java')
from dual

--select * from employees where lower(last_name) = 'king'
select * from employees where upper(last_name) = 'KING'

--concat 連線字串,substr 擷取,length 字串長度
select concat('Hello','World!'),substr('HelloWorld',2,4),length('HelloWorld!')
from dual;

select instr('HelloWorld!','d') from dual;
select instr('HelloWorld!','c') from dual;

--左填充,右填充:
select employee_id,last_name,lpad(salary,10,'*'),rpad(salary,10,'*')
from employees;
select employee_id,last_name,lpad(salary,10,' '),rpad(salary,'10',' ')
from employees

--trim刪除(只刪除前後)
select trim('h' from 'hhhellohhWroldhhh') from dual;

--替換:replace
select replace('abcdab','b','m') from dual;

--round 保留位數,預設保留整數。
select round(435.45,1),round(435.45),round(435.45,-1) from dual;
--trunc截斷
select trunc(435.45,1),trunc(435.45),trunc(435.45,-1) from dual;
--mod :餘數
select mod(1100,300) from dual

--日期可以做加減
select sysdate,sysdate + 1,sysdate - 3 from dual;

select employee_id,last_name,trunc(sysdate-hire_date) worked_days
from employees
order by worked_days;

select employee_id,last_name,(sysdate-hire_date)/30 month_days
from employees
order by month_days;

--months_between 兩個日期之間有幾個月
select employee_id,last_name,(sysdate-hire_date)/30 month_days,months_between(sysdate,hire_date)
from employees
order by month_days;


--向指定日期中加上若干月數 add_months
--指定日期的下一個星期“對應的日期” next_day
星期:
一:monday
二:tuesday
三:wednesday
四:thursday
五:friday
六;saturday
日:sunday
select add_months(sysdate,3),add_months(sysdate,-1),next_day(sysdate,'sunday') from dual;

--本月的最後一天 last_day
select last_name,hire_date
from employees
where hire_date = last_day(hire_date) - 1;

select last_day(sysdate) from dual;
--日期四捨五入 round
select round(sysdate,'year'),round(sysdate,'month'),round(sysdate,'day'),round(sysdate,'hh') from dual;
--日期截斷 trunc
select trunc(sysdate,'year'),trunc(sysdate,'month'),trunc(sysdate,'day'),trunc(sysdate,'hh') from dual;

--資料型別轉換: date <===> varchar2 <===> number (to_date,to_number,to_char)
select sysdate + 2 from dual;

select employee_id,hire_date from employees
--where hire_date = '7-6月-94'
--where to_char(hire_date,'yyyy-mm-dd')='1994-06-07'
where to_date('1994-06-07','yyyy-mm-dd') = hire_date

select employee_id,to_char(hire_date,'yyyy"年"mm"月"dd"日"') from employees
where to_char(hire_date,'yyyy-mm-dd')='1994-06-07';
--to_char函式中經常使用的幾種格式(9:數字,0:零,$美元符,L:本地貨幣符號,.:小數點,,:千位符)
select to_char(1234334432432.7979,'999,999,999,999,999.9999') from dual;
select to_char(1234334432432.7979,'000,000,000,000,000.0000') from dual;

select to_char(1234334432432.7979,'$000,000,000,000,000.0000') from dual;
select to_char(1234334432432.7979,'L000,000,000,000,000.0000') from dual;

select to_number('¥001,234,567.89','L000,000,999.99') + 1 from dual;
select to_number('$001,234,567.89','$000,000,999.99') from dual;

select employee_id,last_name,salary*12*(1 + nvl(commission_pct,0)) "annual sal"
from employees;

select last_name,nvl(to_char(department_id,'99999999999'),'沒有部門') from employees;
-- 不為空返回 為空返回
select last_name,commission_pct,nvl2(commission_pct,commission_pct + 0.015,0.01) from employees;

--nullif(expr1,expr2);相等返回null,不相等返回expr1

coalesce(expr1,expr2,expr3,……):一個值為空返回下一個值

--根據條件處理資料
select employee_id,last_name,department_id,case department_id when 10 then salary * 1.1
when 20 then salary * 1.2
else salary * 1.3 end
as nwe_sal
from employees
where department_id in(10,20,30);

select employee_id,last_name,department_id,case department_id when 10 then salary * 1.1
when 20 then salary * 1.2
when 30 then salary * 1.3
else salary end
as nwe_sal
from employees;


select employee_id,last_name,department_id,decode(department_id,10,salary * 1.1,
20,salary * 1.2,
salary) as new_sal
from employees
where department_id in(10,20,30);

--練習
--列印輸出格式為"2009年10月14日 9:25:40" 格式的當前系統的日期和時間。
select to_char(sysdate,'yyyy"年"mm"月"dd"日" hh:mi:ss')
from dual

--等值連線,內連線,都滿足條件
select employee_id,employees.department_id,department_name
from employees,departments
where employees.department_id=departments.department_id

select e.employee_id,e.department_id,d.department_name
from employees e,departments d
where e.department_id=d.department_id

select employee_id,e.department_id,department_name,city
from employees e,departments d,locations l
where e.department_id=d.department_id and d.location_id=l.location_id

--非等值連線,內連線,都滿足條件
select employee_id,last_name,salary,lpad(grade_level,10,' ') "nwe grade_level"
from employees e,job_grades j
where salary between lowest_sal and highest_sal

--外連線(左外連線),返回左邊不滿足條件得行
select e.last_name,e.department_id,d.department_name
from employees e,departments d
where e.department_id=d.department_id(+)

--外連線(右外連線),返回右表中不滿足條件得行
select last_name,e.department_id,department_name
from employees e,departments d
where e.department_id(+)=d.department_id

--使用SQL:1999語法連線
--預設以相同欄位作為連線條件,缺點:如果有多個連線條件時,預設以多個條件作為連線條件,無法指定用哪個欄位作為連線條件
select employee_id,department_id,department_name
from employees natural join departments

--可以指定以哪個欄位作為連線條件。缺點:欄位名和資料型別要一樣
select employee_id,department_id,department_name
from employees join departments
using(department_id)

select employee_id,e.department_id,department_name
from employees e join departments d
on e.department_id=d.department_id

select employee_id,e.department_id,department_name,city
from employees e join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id

--左外連線
select employee_id,e.department_id,department_name
from employees e left outer join departments d
on e.department_id=d.department_id

--右外連線
select employee_id,e.department_id,department_name
from employees e right outer join departments d
on e.department_id=d.department_id

--滿外連線
select employee_id,e.department_id,department_name
from employees e full outer join departments d
on e.employee_id = d.department_id

--自連線
--查詢公司中員工'Chen'的manager的資訊
select emp.last_name,manager.last_name,manager.salary,manager.email
from employees emp,employees manager
where emp.manager_id=manager.employee_id and lower(emp.last_name)='chen'


練習題:
1、顯示所有員工的姓名,部門號和部門名稱

select last_name,e.department_id,department_name
from employees e left outer join departments d
on e.department_id=d.department_id

select last_name,e.department_id,department_name
from employees e , departments d
where e.department_id=d.department_id(+)

2、查詢90號部門員工的job_id和90號部門的location_id

select last_name,m.department_id,job_id,location_id
from employees m,departments d
where m.department_id = d.department_id and m.department_id=90

select last_name,d.department_id,job_id,location_id
from departments d join employees e
on d.department_id=e.department_id
where e.department_id=90

select department_id,job_id,location_id
from departments join employees
using(department_id)
where department_id=90

select d.department_id,job_id,location_id
from departments d left outer join employees e
on d.department_id=e.department_id
where e.department_id=90

select d.department_id,job_id,location_id
from departments d right outer join employees e
on d.department_id=e.department_id
where e.department_id=90

select d.department_id,job_id,location_id
from departments d,employees e
where d.department_id=e.department_id(+)
and e.department_id=90

3、選擇所有有獎金的員工的 last_name,department_name,location_id,city

select last_name,department_name,d.location_id,city
from employees e,departments d,locations l
where e.department_id=d.department_id
and d.location_id=l.location_id
and commission_pct is null

select last_name,department_name,d.location_id,city
from employees e join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
where commission_pct is null

4、選擇city在Toronto工作的員工的 last_name,job_id,department_id,department_name

select last_name,job_id,e.department_id,department_name
from employees e join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
where lower(city)='toronto'

select last_name,job_id,e.department_id,department_name
from employees e,departments d,locations l
where e.department_id=d.department_id
and d.location_id=l.location_id
and lower(city)='toronto'
5、選擇指定員工的姓名,員工號,以及他的管理者的姓名和員工號,結果類似於下面的格式
employees Emp# manager Mgr#
kochhar 101 king 100

select e1.last_name "employees",e2.employee_id "Emp#",e1.last_name "manager",e2.employee_id Mgr#
from employees e1,employees e2
where e1.manager_id = e2.employee_id(+)

select e1.last_name,e1.employee_id,e2.last_name,e2.employee_id
from employees e1 join employees e2
on e1.manager_id=e2.employee_id(+)

--select中有的欄位,group by 中必須有(除了組函式中的欄位arg())
--group by 中有的欄位select中不必有 即非組行數的列必須放在group by 中
select department_id,job_id,avg(salary)
from employees
group by department_id,job_id

select department_id,avg(salary)
from employees
--where department_id in (40,60,70)
--where avg(salary) > 6000 --where和組函式不能同時使用
having avg(salary) > 6000
group by department_id
order by department_id asc

--組函式可以互相巢狀
select max(lpad(round(avg(salary),2),10,' ')),min(trunc(avg(salary),2))
from employees
group by department_id

--有多少個部門
select count(distinct department_id) from employees
--計算全公司的獎金的值

select avg(nvl(commission_pct,0)) from employees
--查詢各個部門的平均工資

select department_id,avg(salary) from employees
group by department_id
order by department_id asc
--Toronto這個城市的平均工資

select avg(salary),city
from employees e join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
having lower(city)='toronto'
group by city

select 'Toronto',avg(salary)
from employees e join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
where lower(city)='toronto'

select 'Toronto',avg(salary)
from employees e,departments d,locations l
where e.department_id=d.department_id
and d.location_id=l.location_id
and l.city='Toronto'
--(有員工的城市)各個城市的平均工資

select city,avg(salary)
from employees e,departments d,locations l
where e.department_id=d.department_id
and d.location_id=l.location_id
group by city
--平均工資高於8000的部門id和它的平均工資

select e.department_id,avg(salary)
from employees e
having avg(salary) > 8000
group by e.department_id
--查詢平均工資高於6000的job_title 有哪些

select job_title
from employees e natural join jobs
having avg(salary) > 6000
group by job_title


--查詢所有部門的名字,location_id,員工數量和工資平均值

select department_name,location_id,count(employee_id),avg(salary)
from employees e right outer join departments d
on e.department_id=d.department_id
group by department_name,location_id

--查詢公司在1995~1998年之間,每年僱傭的人數,結果類似下面的格式
total 1995 1996 1997 1998
20 3 4 6 7
答案:
select count(*) "total",
count(decode(to_char(hire_date,'yyyy'),'1995',1,null)) "1995",
count(decode(to_char(hire_date,'yyyy'),'1996',1,null)) "1996",
count(decode(to_char(hire_date,'yyyy'),'1997',1,null)) "1997",
count(decode(to_char(hire_date,'yyyy'),'1998',1,null)) "1998"
from employees e
where to_char(HIRE_DATE,'yyyy') in ('1995','1996','1997','1998')

--誰的工資比Abel高
select last_name,salary
from employees where salary >
(select salary from employees where lower(last_name)='abel')

--返回job_id與141號員工相同,salary比143號員工多的員工姓名,job_id和工資

select last_name,job_id,salary
from employees
where job_id=(select job_id from employees where employee_id = 141)
and salary>(select salary from employees where employee_id = 143)
--返回公司工資最少的員工的last_name,job_id和salary

select last_name,job_id,salary
from employees
where salary = (select min(salary) from employees)
--查詢最低工資大於50號部門最低工資的部門id和其最低工資

select department_id,min(salary)
from employees
group by department_id
having min(salary) > (
select min(salary)
from employees
where department_id=50
)
多行子查詢:
操作符 含義
in 等於列表中的任意一個
any 和子查詢返回的某一個值比較
all 和子查詢返回的所有值比較
--返回其它部門中比job_id為'IT_PROG'部門任一工資低的員工的員工號、姓名、job_id以及salary

select employee_id,last_name,job_id,salary
from employees
where salary < any
(select salary
from employees
where job_id = 'IT_PROG')
AND job_id <> 'IT_PROG'
--返回其它部門中比job_id為'IT_PROG'部門所有工資低的員工的員工號、姓名、job_id以及salary

select employee_id,last_name,job_id,salary
from employees
where salary < all
(select salary
from employees
where job_id = 'IT_PROG')
AND job_id <> 'IT_PROG'

--查詢工資最低的員工資訊:last_name,salary
select last_name,salary
from employees
where salary=(select min(salary) from employees)

select min(salary)
from employees
--查詢平均工資最低的部門資訊

select * from departments where department_id=(select department_id
from employees
having avg(salary)=(select min(avg(salary))
from employees
group by department_id)
group by department_id)
--查詢平均工資最低的部門資訊和該部門的平均工資
select d.*,(select avg(salary) from employees where department_id=d.department_id)
from departments d where department_id=(
select department_id from employees having avg(salary)=(
select min(avg(salary))
from employees
group by department_id)
group by department_id)
--查詢平均工資最高的job資訊

select * from jobs where job_id=(
select job_id from employees having avg(salary)=(
select max(avg(salary))
from employees e
group by job_id)
group by job_id)
--查詢平均工資高於公司平均工資的部門有哪些?

select department_id,avg(salary) from employees
having avg(salary) > (select avg(salary) from employees)
group by department_id
--查詢出公司中所有manager的詳細資訊。

select * from employees
where employee_id in (select manager_id from employees)
--各個部門中最高工資中最低的那個部門的最低工資是多少?

select min(salary) from employees where department_id=(
select department_id from employees having max(salary)=(
select min(max(salary)) from employees
group by department_id)
group by department_id)
--查詢平均工資最高的部門的manager的詳細資訊: last_name,department_id,email,salary

select last_name,department_id,email,salary,manager_id from employees where manager_id in (
select distinct manager_id
from employees
where department_id=(
select department_id from employees
having avg(salary)=(
select max(avg(salary)) from employees
group by department_id)
group by department_id))
--查詢1999年來公司的員工中最高工資的那個員工的資訊

select * from employees
where salary = (
select max(salary) from employees where to_char(hire_date,'yyyy') = '1999'
)
and to_char(hire_date,'yyyy') = '1999'
--查詢和Zlotkey相同部門的員工姓名和僱傭日期
--查詢工資比公司平均工資高的員工的員工號,姓名和工資。
--查詢各部門中工資比本部門平均工資高的員工的員工號,姓名和工資
--查詢和姓名中包含字母u的員工在相同部門的員工的員工號和姓名
--查詢在部門的location_id為1700的部門工作的員工的員工號

1.查詢和Zlotkey相同部門的員工姓名和僱傭週期

select last_name,hire_date
from employees
where department_id=(select department_id from employees where lower(last_name)='zlotkey')
and lower(last_name)<>'zlotkey'
2.查詢工資比公司平均工資高的員工的員工號,姓名和工資
select last_name,employee_id,salary
from employees
where salary>(select avg(salary) from employees)
3.查詢各部門中工資比本部門平均工資高的員工的員工號,姓名和工資

select employee_id,last_name,salary from employees e1
where salary > (select avg(salary)
from employees e2
where e1.department_id=e2.department_id
group by department_id)
4.查詢姓名中包含字母u的員工在相同部門的員工的員工號和姓名
select employee_id,last_name
from employees where department_id in
(select department_id from employees
where last_name like '%u%')
and last_name not like '%u%'
5.查詢在部門的location_id為1700的部門工作的員工的員工號
select employee_id
from employees
where department_id in(
select department_id
from departments
where location_id =1700)
6.查詢管理者是king的員工姓名和工資
select last_name,salary
from employees
where manager_id in(
select employee_id
from employees
where lower(last_name)= 'king')

通過本章的學習,您將可以:
1.描述主要的資料庫物件
2.建立表
3.描述各種資料型別
4.修改表的定義
5.刪除,重新命名和清空表

常見的資料庫物件
物件 描述
表 基本的資料儲存集合,由行和列組成
檢視 從表中抽出的邏輯上相關的資料集合
序列 提供有規律的數值
索引 提高查詢的效率
同義詞 給物件起別名

select * from user_tables
select * from user_catalog
select distinct object_type
from user_objects

命名規則
必須以字母開頭
必須在 1 - 30 個字元之間
必須只能包含 A-Z,a-z,0-9,_,$和#
必須不能和使用者定義的其他物件重名
必須不能是Oracle的保留字

$abc,2dbc,_abc,a-b
a#b

--建立表的第一種方式(白手起家)
create table emp1(
ID NUMBER(10),
NAME VARCHAR2(20),
SALARY NUMBER(10,2),
HIRE_DATE DATE
)

--建立表的第二種方式(依託於現有的表)
create table emp2
as
select employee_id id,last_name name ,hire_date,salary
from employees

create table emp3
as
select employee_id id,last_name name ,hire_date,salary
from employees where department_id = 80
--如果只需要表結構,就用where過濾資料。
create table emp3
as
select employee_id id,last_name name ,hire_date,salary
from employees where department_id = 800

create table emp3
as
select employee_id id,last_name name ,hire_date,salary
from employees where 1=2

資料型別

資料型別 描述
VARCHAR2(SIZE) 可變長字元資料
CHAR(SIZE) 定長字元資料
NUMBER(P,S) 可變長數值資料
DATE 日期型資料
LONG 可變長字元資料,最大可達到2G
CLOB 字元資料,最大可達到4G
RAW(LONG RAW) 原始的二進位制資料
BLOB 二進位制資料,最大可達到4G
BFILE 儲存外部檔案的二進位制資料,最大可達到4G
ROWID 行地址

ALTER TABLE語句
使用ALTER TABLE 語句可以:
追加新的列
修改現有的列
為新追加的列定義預設值
刪除一個列
重命名錶的一個列名

使用ALTER TABLE 語句追加,修改,或者刪除列的語法
ALTER TABLE table_name
ADD (column datatype [DEFAULT expr])
[,column datatype]……);

ALTER TABLE table_name
MODIFY (column datatype [DEFAULT expr])
[,column datatype]……);

ALTER TABLE table_name
DROP COLUMN column_name;

ALTER TABLE table_name RENAME COLUMN old_column_name
TO new_column_name;

truncate table table_name --清空表,不能回滾
--刪除表種的所有資料
--釋放表的儲存空間
delete from table_name --刪除資料,可以回滾

truncate 不可以rollback
delete 可以rollback

改變物件的名稱:(表,檢視,序列,同義詞……)
RENAME dept TO detail_dept; --必須是物件的擁有者。

drop table table_name --刪除表


DDL語句
語句 描述
CREATE TABLE 建立表
ALTER TABLE 修改表結構
DROP TABLE 刪除表
RENAME TO 重新命名
TRUNCATE TABLE 刪除表種的所有資料,並釋放儲存空間
以上的DDL命令,操作除外,皆不可回滾!

使用DML語句
向表種插入資料
更新表中資料
從表中刪除資料
控制事務
事務是由完成若干項工作的DML語句組成的

INSERT INTO table [(column [,column [,column……]])]
VALUES (value [,value……]);


create table emp1 (
employee_id number(6),
last_name varchar2(25),
hire_date date,
salary number(8,2)
)

insert into emp1
values(1001,'AA',sysdate,10000)

insert into emp1
values(1002,'BB',to_date('1992-4-10','yyyy-mm-dd'),20000)

insert into emp1
values(1003,'CC',to_date('1999-4-10','yyyy-mm-dd'),null)

insert into emp1(last_name,employee_id,hire_date)
values('DD',1004,to_date('1993-10-10','yyyy-mm-dd'))

insert into emp1(employee_id,last_name,hire_date,salary)
select employee_id,last_name,hire_date,salary
from employees
where employee_id=80

insert into emp1(employee_id,last_name,salary,hire_date)
values(1005,'FF',3400,'21-3月-1995')

insert into emp1(employee_id,last_name,salary,hire_date)
values(&id,'&last_name',&salary,'&hire_date')

--update後要commit一下。在commit前可以rollback
update emp1
set salary = 12000
where employee_id=1001;

--更新114號員工的工作和工資使其與205號員工的相同
select employee_id,job_id,salary
from employees
where employee_id in(114,205)

update employees
set job_id=(
select job_id from employees where employee_id=205
)
,salary=(
select salary from employees where employee_id=205
)
where employee_id=114

delete from table_name
where condition;

資料庫事務
事務:一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。
資料庫事務由以下的部分組成:
一個或多個DML語句
一個DDL語句
一個DCL語句

以下面的其中之一作為結束:
commit 或 rollback 語句
DDL語句(自動提交)
使用者會話正常結束
系統異常終止

savepoint A --儲存點
rollback savepoint A; --可以回滾到儲存點。

約束是表級的強制規定
有以下五種約束:
NOT NULL
UNIQUE
PRIMARY KEY
FOREIGN KEY
CHECK

如果不指定約束名,Oracle server 自動按照SYS_Cn 的格式指定約束名
建立和修改約束:
建立表的同時建立約束
建表之後建立約束
可以在表級或列級定義約束
可以通過資料字典檢視檢視約束
作用範圍:
列級約束只能作用在一個列上
表級約束可以作用在多個列上(表級約束也可以作用在一個列上)
定義方式:列約束必須跟在列的定義後面,表級約束不與列一起,而是單獨定義。
非空約束只能定義在列上。
--非空(not null)
create table emp2(
id number(10) constraint emp2_id_nn not null,
name varchar2(20) not null,
salary number(10,2)
)

--唯一鍵(unique)
create table emp3(
--列級約束
id number(10) constraint emp3_id_uk unique,
name varchar2(20) constraint emp3_name_nn not null,
email varchar2(20),
salary number(10,2),
--表級約束
constraint emp3_email_uk unique(email)
)
insert into emp3
values(1001,'AA','[email protected]',2000);
insert into emp3
values(1002,'BB',null,3000);
insert into emp3
values(1003,'CC',null,4000);

--主鍵(promary key)(非空,不能重複)
create table emp4(
--列級約束
id number(10) constraint emp4_id_pk primary key,
name varchar2(20) constraint emp4_name_nn not null,
email varchar2(20),
salary number(10,2),
--表級約束
constraint emp4_email_uk unique(email)
)

insert into emp4
values(1001,'AA',null,2000);

insert into emp4
values(1001,'BB',null,3000);

create table emp5(
--列級約束
id number(10),
name varchar2(20) constraint emp5_name_nn not null,
email varchar2(20),
salary number(10,2),
--表級約束
constraint emp5_email_uk unique(email),
constraint emp5_id_pk primary key(id)
)

--外來鍵(foreign key)
create table emp6(
--列級約束
id number(10),
name varchar2(20) constraint emp6_name_nn not null,
email varchar2(20),
salary number(10,2),
department_id number(10),
--表級約束
constraint emp6_email_uk unique(email),
constraint emp6_id_pk primary key(id),
constraint emp6_dept_id_fk foreign key(department_id) references departments(department_id) on delete cascade --級聯刪除
或者
constraint emp6_dept_id_fk foreign key(department_id) references departments(department_id) on delete set null --級聯置空
)

--check
create table emp8(
--列級約束
id number(10),
name varchar2(20) constraint emp8_name_nn not null,
email varchar2(20),
salary number(10,2) constraint emp8_salary_ck check(salary > 1500 and salary < 30000),
department_id number(10),
--表級約束
constraint emp8_email_uk unique(email),
constraint emp8_id_pk primary key(id),
constraint emp8_dept_dept_id_fk foreign key(department_id) references departments(department_id) on delete set null
)

使用 ALTER TABLE 語句:
新增或刪除約束,但是不能修改約束
有效化或無效化約束
新增 NOT NULL 約束要使用 MODIFY 語句
--修改約束
alter table emp4
modify(salary number(10,2) constraint emp4_salary_nn not null)
--刪除約束
alter table emp4
drop constraint emp4_name_nn
alter table emp4
drop constraint sys_c0028540
--新增約束
alter table emp4
add constraint emp4_name_uk unique(name);

有效化和有效化
在 ALTER TABLE 語句中使用 DISABLE 子句將約束無效化
ALTER TABLE table_name
DISABLE CONSTRAINT constraint_name;
--disable 使約束失效
alter table emp3
disable constraint emp3_email_uk;
--使約束生效或啟用約束
alter table emp3
enable constraint emp3_email_uk;

從資料字典中查詢約束:
查詢資料字典檢視:USER_CONSTRAINTS
select constraint_name,constraint_type,search_condition
from user_constraints
where table_name='employees';

查詢定義約束的列
查詢資料字典檢視:USER_CONS_COLUMNS
SELECT column_name,constraint_name
FROM user_cons_columns
WHERE table_name = 'EMPLOYEES';


create table emp2 as select employee_id id,last_name name,salary from employees;

create table dept2 as select department_id id,department_name dept_name from departments;
1、向表emp2的id列中新增PRIMARY KEY 約束(my_emp2_id_pk)
alter table emp2
add constraint my_emp2_id_pk PRIMARY KEY(id);

2、向表dept2的id列中新增PRIMARY KEY 約束(my_dept2_id_pk)
alter table dept2
add constraint my_dept2_id_pk PRIMARY KEY(ID);

3、向表emp2中新增列dept_id,並在其中定義FORIEGN KEY約束,
與之相關聯的列是dept2表中的id列。
alter table emp2 add(dept_id number(10) constraint emp2_dept_id_fk references dept2(id) on delete set null);

檢視
檢視是一種虛表
檢視建立在已有表的基礎上,檢視賴以建立的這些表稱為基表。
向檢視提供資料內容的語句為 SELECT 語句,可以將檢視理解為儲存起來的 SELECT 語句。
檢視向用戶提供基表資料的另一種表現形式
建立檢視語法:
create view view_name
as
select column_name
from table_name;

目標:
描述檢視
建立和修改檢視的定義,刪除檢視
從檢視中查詢資料
通過檢視插入,修改和刪除資料
使用“Top-N”分析

為什麼使用檢視:
- 控制資料訪問
- 簡化查詢
- 避免重複訪問相同的資料

--重置欄位
create view empview1
as
select employee_id id,last_name name,salary
from employees
where department_id=80

--基於多表建立檢視
create view empview2
as
select employee_id id,last_name name,salary,department_name
from employees e,departments d
where d.department_id = e.department_id

--刪除
delete from empview
where employee_id = 176

--修改檢視
使用create or replace view 子句修改檢視
create or replace view empview2
as
select employee_id id,last_name name,salary
from employees e,departments d
where d.department_id = e.department_id

create view 子句中各列的別名應和子查詢中各列相對應

遮蔽DML操作
可以使用 WITH READ ONLY 選項遮蔽對檢視的DML操作
任何 DML 操作都會返回一個Oracle server錯誤
create or replace view empview2
as
select employee_id id,last_name name,salary
from employees e,departments d
where d.department_id = e.department_id
with read only

簡單檢視和複雜檢視
特性 簡單檢視 複雜檢視
表的數量 一個 一個或多個
函式 沒有 有
分組 沒有 有
DML操作 可以 有時可以

--複雜檢視
create or replace view empview3
as
select department_name dept_name,avg(salary) avg_sal
from employees e ,departments d
where e.department_id = d.department_id
group by department_name

檢視中使用DML的規定
可以在簡單檢視中執行 DML 操作
當檢視定義中包含以下元素之一時不能使用delete:
- 組函式
- GROUP BY子句
- DISTINCT 關鍵字
- ROWNUM 偽列

--刪除檢視
drop view empview;

Top-N分析
Top-N 分析查詢一個列中最大或最小的 n 個值:
- 銷售量最高的十種產品是什麼?
- 銷售量最差的十種產品是什麼?
最大和最小的值的集合是 Top-N 分析所關心的

select rownum,employee_id,last_name,salary
from (select employee_id,last_name,salary
from employees
order by salary desc
)
where rownum<=10

注意:
對 ROWNUM 只能使用 < 或 <=, 而用 =,>,>= 都將不能返回任何資料。
select rn,employee_id,last_name,salary
from (
select rownum rn,employee_id,last_name,salary
from (select employee_id,last_name,salary
from employees
order by salary desc
))
where rn<=50 and rn >40

練習:
--查詢員工表中salary前10的員工資訊。
/*
select rn,employee_id,last_name,salary from (
select rownum rn,employee_id,last_name,salary
from employees
order by salary desc)
where rownum <= 10

--查詢員工表中 salary 10 ~ 20 的員工資訊。
select rn,employee_id,last_name,salary from (
select rownum rn,employee_id,last_name,salary
from employees
order by salary desc)
where rn <= 20 and rn >= 10

--1.使用表 employees 建立檢視 employee_vu,其中包括姓名(LAST_NAME),員工號(EMPLOYEE_ID),部門號(DEPARTMENT_ID)
create or replace view employee_vu
as
select last_name,employee_id,department_id
from employees
--將檢視中的資料限定在部門號是80的範圍內
create or replace view employee_vu
as
select last_name,employee_id,department_id
from employees
where department_id = 80
--將檢視改變成只讀檢視
create or replace view employee_vu
as
select last_name,employee_id,department_id
from employees
where department_id = 80
with read only

什麼是序列
序列:可供多個使用者用來產生唯一數值的資料庫物件
- 自動提供唯一的數值
- 共享物件
- 主要使用者提供主鍵值
- 將序列值裝入記憶體可以提高訪問效率

create sequence 語句
定義序列:
create sequence sequence_name
[INCREMENT BY n] --每次增長的數值
[START WITH n] --從哪個值開始
[{MAXVALUE n | NOMAXVALUE}]
[{MINVALUE n | NOMAXVALUE}]
[{CYCLE | NOCYCLE}] --是否需要迴圈
[{CACHE n | NOCACHE}]; --是否快取登入

create sequence empseq
increment by 10 --每次增長10
start with 10 --從10開始增長
maxvalue 100 --最大值100
cycle --需要迴圈
nocache --不需要快取

修改序列的注意事項
- 必須是序列的擁有者或對序列有 alter 許可權
- 只有將來的序列值會被改變
- 改變序列的初始值只能通過刪除序列之後重建序列的方法實現
alter sequence empseq
increment by 1
nocycle;
--檢視下一個序列
select empseq.nextval from dual;
--檢視當前序列
select empseq.currval from dual;

使用序列
- 將序列值裝入記憶體可提高訪問效率
- 序列在下列情況下出現裂縫:
- 回滾
- 系統異常
- 多個表同時使用同一序列
- 如果不將序列的值裝入記憶體(NOCACHE),可使用表 USER_SEQUENCES 檢視序列當前的有效值

--檢視使用者中的序列
select sequence_name,min_value,max_value,
increment_by,last_number
from user_sequences;

--刪除序列
drop sequence empseq;

索引
索引:
- 一種獨立於表的模式物件,可以儲存在與表不同的磁碟或表空間中
- 索引被刪除或損壞,不會對錶產生影響,其影響的只是查詢的速度
- 索引一旦建立,Oracle 管理系統會對其進行自動維護,而且由 Oracle 管理系統決定何時使用索引。使用者不用在查詢語句中指定使用哪個索引
- 在刪除一個表時,所有基於該表的索引會自動被刪除
- 通過指標加速 Oracle 伺服器的查詢速度
- 通過快速定位資料的方法,減少磁碟 I/O

建立索引
自動建立:在定義 PRIMARY KEY 或 UNIQUE 約束後系統自動在相應的列上建立唯一性索引
手動建立:使用者可以在其它列上建立非唯一的索引,以加速查詢。
--在一個或多個列上建立索引
create index index_name
on table (column[,column]... )

create index emp01_id_ix
on emp01(employee_id);

--在表 EMPLOYEES的列 LAST_NAME 上建立索引
CREATE INDEX emp_last_name_idx
ON employees(last_name);

--刪除索引
drop index emp01_id_ix;

什麼時候建立索引
以下情況可以建立索引:
- 列中資料值分佈範圍很廣(存的資料很長)
- 列經常在 WHERE 子句或連線條件中出現
- 表經常被訪問而且資料量很大,訪問的資料大概佔資料總量的2%~4%

什麼時候不要建立索引
下列情況不要建立索引:
- 表很小
- 列不經常作為連線條件或出現在WHERE子句中
- 查詢的資料大於2%~4%
- 表經常更新

同義詞-synonym
使用同義詞訪問相同的物件:
- 方便訪問其它使用者的物件
- 縮短物件名字的長度(即給資料庫物件重新命名)

CREATE [PUBLIC] SYNONYM synonym
FOR objext;

CREATE SYNONYM e FOR employees;

學習過程:
what-----why-----how

建立序列:
create sequence hs
increment by 10
start with 10

netvalue 應在 currval 之前指定,二者應同時有效

--1.建立序列dept_id_seq,開始值為200,每次增長10,最大值為10000
create sequence dept_id_seq
increment by 10
start with 200
maxvalue 10000

create table dept01 as
select department_id id,department_name name
from departments
where 1=2
--使用序列向表dept中插入資料
insert into dept01
values(dept_id_seq.nextval,'account')

通過本章學習,您將可以:
· 書寫多例子查詢
· 在 FROM 子句中使用子查詢
· 在SQL中使用單例子查詢
· 書寫相關子查詢
· 使用 EXISTS 和 NOT EXISTS 操作符
· 使用子查詢更新和刪除資料
· 使用 WITH 子句

子查詢是巢狀在SQL語句中的另一個SELECT語句
SELECT .... --主查詢(外查詢)
FROM ...
WHERE ... (SELECT ...
FROM ...
WHERE ...) --子查詢(內查詢)

SELECT select_list
FROM table
WHERE expr operator (SELECT select_list
FROM table;)
· 子查詢(內查詢)在主查詢執行之前執行
· 主查詢(外查詢)使用子查詢的結果

一、多列子查詢
Main query
WHERE (MANAGER_ID,DEPARTMENT_ID) IN
Subquery
100 90
102 60
124 50
主查詢與子查詢返回的多個列進行比較

不成對比較舉例
select employee_id,manager_id,department_id
from employees
where manager_id in
(select manager_id
from employees
where employee_id in (174,141))
and department_id in
(select department_id
from employees
where employee_id in (171,141))

成對比較舉例
問題:查詢與141號或174號員工的manager_id和department_id相同的其他員工的employee_id,manager_id,department_id
select employee_id,manager_id,department_id
from employees
where (manager_id,department_id) in
(select manager_id,department_id
from employees
where employee_id in (141,174))
and employee_id not in (141,174);

二、在FROM子句中使用子查詢
問題:返回比本部門平均工資高的員工的last_name,department_id,salary及平均工資
select last_name,department_id,salary,(select avg(salary) from employees e3
where e1.department_id = e3.department_id
group by department_id) avg_salaty
from employees e1
where salary > (select avg(salary)
from employees e2
where e1.department_id = e2.department_id
group by department_id)

select last_name,e1.department_id,salary,e2.avg_sal
from employees e1,(select department_id,avg(salary) avg_sal from employees group by department_id) e2
where e1.department_id = e2.department_id
and salary>e2.avg_sal

--顯示員工的employee_id,last_name或location.
--其中,若員工department_id與location_id為1800的department_id相同,則location為'Canada',其餘則為'USA'.
SELECT employee_id,last_name,
(case department_id when (select department_id from departments where location_id = 1800)then 'Canada'
else 'USA' end) location
from employees;

單列子查詢應用舉例
在 ORDER BY 子句中使用單列子查詢
問題:查詢員工的employee_id,last_name,要求按照員工的department_name排序
SELECT employee_id,last_name
FROM employees e
ORDER BY (select department_name
from departments d
where e.department_id = d.department_id
);

四、相關子查詢
相關子查詢按照一行接一行的順序執行,主查詢的每一行都執行一次子查詢
GET
-------->從主查詢中過去候選列
| |
| EXECUTE
| 子查詢使用主查詢的資料
| |
| USE
|-------如果滿足內查詢的條件則返回該行

SELECT columnl,column2,....
FROM table1 outer
WHERE column1 operator
(SELECT colum1,column2
FROM table2
WHERE expr1 =
outer.expr2
);
子查詢中使用主查詢中的列

--若employees表中employee_id與job_history表中employee_id相同的數目不小於2,輸出這些相同id的員工的employee_id,last_name和其job_id
select employee_id,last_name,job_id
from employees e1
where 2 <= (
select count(1)
from job_history
where employee_id = e1.employee_id
)

五、EXISTS操作符
· EXISTS 操作符檢查在子查詢中是否存在滿足條件的行
· 如果在子查詢中存在滿足條件的行:
- 不在子查詢中繼續找
- 條件返回TRUE
· 如果在子查詢中不存在滿足條件的行:
- 條件返回FALSE
- 繼續在子查詢中查詢
--查詢公司管理者的employee_id,last_name,job_id,department_id資訊
select employee_id,last_name,job_id,department_id
from employees e1
where e1.employee_id in (
select manager_id
from employees e2
where e1.employee_id = e2.manager_id
)

select employee_id,last_name,job_id,department_id
from employees e1
where exists (
select 'A'
from employees e2
where e1.employee_id = e2.manager_id
)

NOT EXITSTS 操作符應用舉例
--查詢departments表中,不存在於employees表中的部門的department_id和department_name
select department_id,department_name
from departments d
where not exists(
select 'C'
from employees
where department_id = d.department_id
)
六、相關更新
update table1 alias1
set column = (select expression
from table2 alias2
where alias1.column =
alias2.column);
使用相關子查詢依據一個表中的資料更新另一個表的資料

相關更新應用舉例
1)
alter table employees
add(department_name varchar2(14));
2)
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子句
· 使用WITH子句,可以避免在SELECT語句中重複書寫相同的語句塊
· WITH子句將該子句中的語句塊執行一次並存儲到使用者的臨時表空間中
· 使用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;

2022.3.30
練習題:
1.查詢員工的last_name,department_id,salary.其中員工的salary,department_id與有獎金的任何一個員工的salary,department_id相同即可
select last_name,department_id,salary from employees where (salary,department_id) in (select salary,department_id from employees where commission_pct is not null)
2.選擇工資大於所有JOB_ID = 'SA_MAN'的員工的工資的員工的last_name,job_id,salary
select last_name,job_id,salary
from employees
where salary > all(select salary
from employees
where job_id = 'SA_MAN')

select last_name,job_id,salary
from employees
where salary > (select max(salary)
from employees
where job_id = 'SA_MAN')
3.選擇所有沒有管理者的員工的last_name
select last_name
from employees
where manager_id is null

select last_name
from employees e1
where not exists(select 'A'
from employees e2
where e1.manager_id=e2.employee_id)

PL/SQL語言
PL/SQL塊
PL/SQL程式由三個塊組成,即宣告部分、執行部分、異常處理部分
PL/SQL塊的結構如下:
DECLARE
/*宣告部分:在此宣告PL/SQL用到的變數,型別及遊標,以及區域性的儲存過程和函式*/
BEGIN
/*執行部分:過程及SQL語句,即程式的主要部分*/
EXCEPTION
/*執行異常部分:錯誤處理*/
END;
其中執行部分是必須的。

set serveroutput on
最簡單的PL/SQL
begin
dbms_output.put_line('Helloworld');
end;

declare
--宣告變數
v_sal number(20);
begin
--sql語句的操作;select ... into ... from ... where ...;
select salary into v_sal from employees where employee_id = 100;
--列印
dbms_output.put_line(v_sal);
end;

declare
v_sal number(10,2);
v_email varchar2(20);
v_hire_date date;
begin
select salary,email,hire_date into v_sal,v_email,v_hire_date from employees where employee_id = 100;
dbms_output.put_line(v_sal||','||v_email||','||v_hire_date);
end;

declare
v_sal employees.salary%type; --從源表表中獲取資料型別
v_email employees.email%type;--從源表表中獲取資料型別
v_hire_date employees.hire_date%type;--從源表表中獲取資料型別
begin
--用into存入變數中
select salary,email,hire_date into v_sal,v_email,v_hire_date from employees where employee_id = 100;
dbms_output.put_line(v_sal||','||v_email||','||v_hire_date);
end;
*/