SQL的類型
- DML(Data Manipulation Language 數(shù)據(jù)操作語言): insert update delete select
- DDL(Data Definition Language 數(shù)據(jù)定義語言): create/alter/drop/truncate table
? create/drop view,sequence,index,synonym(同義詞) - DCL(Data Control Language 數(shù)據(jù)控制語言): grant(授權(quán)) revoke(撤銷權(quán)限)
DDL
- 創(chuàng)建表:
create table tname(c1 t1 default v,c2 t2,,);
- 子查詢:
create table ttemp as select * from emp where 1=2;(不要數(shù)據(jù))
create table ttemp as select * from emp;(要數(shù)據(jù))
- 修改表:
alter table tname add col type;--追加列
alter table tname modify col newtype;--修改類的類型
alter table tname drop column col; --刪除列
alter table tname rename column cname to cnewname;--修改列名
rename tname to tnewname--修改表名
- 刪除表:
drop table tname; 把表放入回收站
truncate table tname;把表刪除重建
- 表的重構(gòu)(去掉因刪除造成的碎片):
alter table emp move
- 回收站:
select * from user_recyclebin; 查看回收站
purge recyclebin; 清空回收站
select * from "回收站的表名";可以看到數(shù)據(jù)
flashback table tname to before drop;--恢復(fù)表(閃回)
DML
- insert語句
insert into dept(deptno,dname) values(70,'oracle');
- 通過子查詢插入數(shù)據(jù)
insert into tname select .. from tname2;
- update語句
update dept set dname='c++' where deptno=80;
- delete語句
delete from dept where deptno=80;
delete 和truncate區(qū)別
- delete 逐條刪除,truncate先刪除表,再重建
- delete是DML(可以回滾) truncate是DDL(不可以回滾)
- delete 不會釋放空間;truncate會
- delete會產(chǎn)生碎片 truncate不會
- delete可以閃回(flashback) truncate不可以
基本查詢
- 當前用戶
- show user;
- 用戶下所有的表
- select * from tab;
- 列的別名
- col as "別名" (col as 別名)
- col "別名" (原名顯示)
- cal 別名 (自動轉(zhuǎn)大寫,不能和oracle關(guān)鍵字沖突)
- 列的別名最好用雙引號括起來
- 數(shù)據(jù)字典
- select * from v$nls_parameters;
- 修改日期格式
- alter session set NLS_DATE_FORMAT='yyyy-mm-dd';
- between and
- 1.含邊界 2. 小值在前 大值在后
- 查詢薪資大于等于1000并且小于等于2000的員工信息
- select * from emp where sal between 1000 and 2000;
- 去掉重復(fù)行
- select distinct deptno from emp;
- 連接字符串 concat() or ||
- select concat('your name:',ename) from emp;
- select 'your name:'||ename from emp;
- 模糊查詢like 和轉(zhuǎn)義字符 escape (%零或多個,_一個)
- 查詢名字A打頭的員工信息
- select * from emp where ename like 'A%';
- 查詢名字第二個字母是L的員工信息
- select * from emp where ename like '_L%';
- 查詢出名字中帶_字符的信息
- select * from emp where name like '%{_%' ESCAPE '{'
- null條件查詢 is null 或 is not null
- select * from emp where COMM is null; 沒有獎金的員工
- null值最大,所以desc的時候,null排在最前面
- select * from emp order by comm desc nulls last
- desc 查看對象的定義信息
- desc dept; 查看表
Oracle中的函數(shù)查詢
基本格式:
- select 函數(shù)名 from dual;
數(shù)字函數(shù)
round(number,小數(shù)位數(shù)正負都行) 四舍五入
- round(125.315) would return 125
trunc(number,小數(shù)位數(shù)) 截斷
- trunc(-125.815, 2) would return -125.81
字符函數(shù)
- substr(a,b) 從a中,第b為開始
- substr(a,b,c) 從a中,第b開始,取c個
- length(a) 字符長度
- lengthb(a) 字節(jié)長度
- instr(a,b) 在a中查詢b的位置
- lpad(a,n,c) 左填充
- rpad(a,n,c) 右填充
- trim('H' from 'HsssH') 去掉前后指定的字符
- replace('hello','l','*') 替換
日期函數(shù)
- sysdate:系統(tǒng)時間(格式),格式化顯示時間
- select to_char(sysdate,'yyyy-mm-dd') from dual;
- systimestamp:系統(tǒng)時間戳 :精度更高,格式化顯示時間
- select to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss:ff') from dual;
日期的運算:計算員工工齡
- months_between (sysdate,hiredate)月
- sysdate-hiredate 天
- 加月 add_months(sysdate,n) n可正負
- 月最后一天 last_day(sysdate)
- 下一個星期: next_day(sysdate,'星期一')下個星期一的日期
- 四舍五入 針對日期函數(shù):round(to_date ('22-AUG-03'),'YEAR') would return '01-JAN-04'
- 截斷 針對日期函數(shù):trunc(to_date('22-AUG-03'), 'YEAR') would return '01-JAN-03'
轉(zhuǎn)換函數(shù)
- number--> character to_char(sal,'L9,999.99') 人民幣格式字符串
- select to_char(sal,'L9,999.99') from emp;
- character--->number to_number('99.99')
- select to_number('99.99') from dual;
- date---->character to_char(sysdate,'yyyy-mm-dd hh24:mi:ss "今天"day')
- select to_char(sysdate,'yyyy-mm-dd') from dual;
- character-->dateto_date('2016-11-23','yyyy-mm-dd')
- select to_date('2016-11-13','yyyy-mm-dd') from dual;
其他函數(shù)
nvl(e1,e2) e1為null時返回e2
nvl2(e1,e2,e3) e1為null 返回e3 否則返回e2
nullif(a,b) 當a=b的時候 返回null 否則返回a
coalesce(e1,e2,e3,,,) 從左到右 找第一個不為null的值
-
decode函數(shù)
語法:decode(exp,ser1,res1,ser2,res2,,,,defualt);
案例:decode(job,'manager',sal+1000,,,,,sal+100);
decode函數(shù)的原理是case語句:
語法: case exp when com_epr then return_exp when com_epr then return_exp when com_epr then return_exp else return_exp end; 案例: select sal 漲前, case job when 'manager' then sal + 100 when .... else sal+300 end 漲后
-
行轉(zhuǎn)列wm_concat()
- select deptno,wm_concat(ename) from emp group by deptno;
-
exists函數(shù),是否有記錄的函數(shù)
- select * from dept where exists(select 1 from emp where emp.deptno=dept.deptno)
分組查詢
按列或者函數(shù)分組,分組后select后面只能跟分組之后的列,或聚合函數(shù),或子查詢
--統(tǒng)計每年入職的員工人數(shù)
select to_char(hiredate,'yyyy') y, count(1) from emp group by to_char(hiredate,'yyyy');
--每個部門的平均工資
select avg(sal),deptno from emp group by deptno;
多表查詢
--等值連接
select * from emp,dept where emp.deptno = dept.deptno;
--不等值連接
select * from emp,dept where emp.deptno <> dept.deptno;
--內(nèi)連接
select * from emp e inner join dept d on e.deptno = d.deptno;
--外連接
--左外連接
select * from emp e left join dept d on e.deptno = d.deptno;
--左外連接
select * from emp e , dept d where e.deptno = d.deptno(+);
--右外連接
select * from emp e right join dept d on e.deptno = d.deptno;
--右外連接
select * from emp e , dept d where e.deptno(+) = d.deptno;
--全外連接
select * from emp e full join dept d on e.deptno = d.deptno;
自連接不適合操作大表
Oracle中的事務(wù)
- 起始標志:事務(wù)中第一題DML語句
- 結(jié)束標志: 提交: 顯式 commit
? 隱式 正常退出exit,DDL,DCL
? 回滾 顯式 rollback
? 隱式 非正常退出,掉電,宕機
--定義保存點
savepoint a;
—回滾到a;
rollback to savepoint a;
oracle分頁
select *
from (select rownum r,e1.*
from (select * from emp order by sal) e1
where rownum <=8
)
where r >=5;
子查詢
注意的問題
- 括號
- 合理的書寫風(fēng)格
- 可以在主查詢的where select having from后面放置子查詢
- 不可以在group by后面放置子查詢
- 強調(diào)from后面的子查詢
- 主查詢和子查詢可以不是同一張表;只要子查詢返回的結(jié)果主查詢可以使用即可
- 一般不在子查詢中排序;但在Top-N分析問題中,必須對子查詢排序
- 一般先執(zhí)行子查詢,再執(zhí)行主查詢;但相關(guān)子查詢例外
- 單行子查詢只能使用單行操作符;多行子查詢只能使用多行操作符
- 子查詢中的null
可以在主查詢的where select having from后面放置子查詢
select empno,ename,sal,(select job from emp where empno=7839) 第四列
2 from emp;
EMPNO ENAME SAL 第四列
---------- ---------- ---------- ---------
7369 SMITH 800 PRESIDENT
7499 ALLEN 1600 PRESIDENT
7521 WARD 1250 PRESIDENT
7566 JONES 2975 PRESIDENT
7654 MARTIN 1250 PRESIDENT
7698 BLAKE 2850 PRESIDENT
7782 CLARK 2450 PRESIDENT
7788 SCOTT 3000 PRESIDENT
7839 KING 5000 PRESIDENT
7844 TURNER 1500 PRESIDENT
7876 ADAMS 1100 PRESIDENT
強調(diào)from后面的子查詢
查詢員工信息:員工號 姓名 月薪
select * 2 from (select empno,ename,sal from emp);
EMPNO ENAME SAL
---------- ---------- ----------
7369 SMITH 800
7499 ALLEN 1600
7521 WARD 1250
7566 JONES 2975
7654 MARTIN 1250
7698 BLAKE 2850
7782 CLARK 2450
7788 SCOTT 3000
7839 KING 5000
7844 TURNER 1500
7876 ADAMS 1100
EMPNO ENAME SAL
---------- ---------- ----------
7900 JAMES 950
7902 FORD 3000
7934 MILLER 1300
in 在集合中
查詢部門名稱是SALES和ACCOUNTING的員工
select *
from emp
where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING');
any 和集合中任意一個值比較
查詢工資比30號部門任意一個員工高的員工信息
select *
from emp
* where sal > any (select sal from emp where deptno=30)
===
select *
from emp
* where sal > (select min(sal) from emp where deptno=30)
all: 和集合中的所有值比較
查詢工資比30號部門所有員工高的員工信息
select *
from emp
where sal > all (select sal from emp where deptno=30);
===
select *
from emp
* where sal > (select max(sal) from emp where deptno=30)
集合運算
union 并集:兩個集合取并集,自動排序,去掉重復(fù)行
select ename,sal,deptno from emp where sal > 1000
union
select ename,sal,deptno from emp where deptno = 30;
union all 并集:兩個結(jié)合取并集,不排序,不去掉重復(fù)行
select ename,sal,deptno from emp where sal > 1000
union all
select ename,sal,deptno from emp where deptno = 30;
intersect 交集:第一個集合減第二個集合
select ename,sal,deptno from emp where sal > 1000
intersect
select ename,sal,deptno from emp where deptno = 30;
minus 差集:第一個集合減第二個集合
select ename,sal,deptno from emp where sal > 1000
minus
select ename,sal,deptno from emp where deptno = 30;
SQL> 注意的問題:
SQL> 1. 參與運算的各個集合必須列數(shù)相同 且類型一致
SQL> 2. 采用第一個集合表頭作為最后表頭
SQL> 3. order by 永遠在最后
SQL> 4. 括號
SQL> select deptno,job,sum(sal) from emp group by deptno,job
2 union
3 select deptno,sum(sal) from emp group by deptno
4 union
5 select sum(sal) from emp;
select deptno,sum(sal) from emp group by deptno
*
第 3 行出現(xiàn)錯誤:
ORA-01789: 查詢塊具有不正確的結(jié)果列數(shù)
SQL> select deptno,job,sum(sal) from emp group by deptno,job
2 union
3 select deptno,to_char(null),sum(sal) from emp group by deptno
4 union
5 select to_number(null),to_char(null),sum(sal) from emp;
order by 后面 + 列,表達式,別名,序號
select empno,ename,sal,sal*12
from emp
order by sal*12 desc;
select empno,ename,sal,sal*12 年薪
from emp
* order by 年薪 desc
select empno,ename,sal,sal*12 年薪
from emp
* order by 4 desc
select empno,ename,sal,sal*12 年薪
from emp
* order by 5 desc
SQL> /
order by 5 desc
*
第 3 行出現(xiàn)錯誤:
ORA-01785: ORDER BY 項必須是 SELECT-list 表達式的數(shù)目
多個列的排序
order by 作用于后面所有的列,先按照第一個列排序,如果相同,再按照第二列排序;以此類推
select *
from emp
order by deptno,sal;
desc 只作用于離他最近的一列
select *
from emp
* order by deptno desc,sal desc
用desc的時候
如果有null會被排在上面,因為null最大
select *
from emp
order by comm desc
* nulls last
表的高級管理
create table t_student(t_id integer,t_sex char(2),t_age integer);
create table t_teacher(tc_id integer primary key,tc_name varchar2(10));
--給學(xué)生表添加外鍵列
alter table t_student add tc_id integer;
--主鍵約束
alter table t_student add constraint pk_t_student_t_id primary key(t_id);
--唯一性約束
alter table t_student add constraint unique_stu_name unique(t_name);
--非空約束
alter table t_student modify t_name not null;
--外鍵約束
alter table t_student add constraint fk_stu_tc_id_tea foreign key(tc_id) references t_teacher(tc_id);
--檢查約束
alter table t_student add constraint ck_age check(t_age between 1 and 200);
alter table t_student add constraint ck_sex check(t_sex in ('男','女'));
SQL優(yōu)化原則
- 理論上,盡量使用多表查詢
- 盡量不要使用集合運算
- 盡量使用列名代替*
- where順序: 右--》 左
SQL中的null
- 包含null的表達式都為null
- SQL> 2. null永遠!=null
- 如果集合中,含有null,不能使用not in;但是可以使用in
- 如果要查詢的話用exists函數(shù)代替in
- select * from dept where exists(select 1 from emp where emp.deptno=dept.deptno)
表的三大范式
- 所有的列都是不可分割的最小單元
- 所有的非主鍵列都完全依賴主鍵列
- 非主鍵列之間不存在傳遞依賴
數(shù)據(jù)庫設(shè)計原則
- 分析系統(tǒng)中所有的數(shù)據(jù)(對象,表)
- 確定數(shù)據(jù)與數(shù)據(jù)之間的關(guān)系(一對一,一對多,多對多)