sqlplus /as sysdba登陸
spool c:\基本查詢.txt--清屏 host clear(linux)
host cls
showuser查看當前用戶
select *from tab 數據字典,管理員給我們提供的表
exit 退出命令行
desc emp 查詢表結構信息
setlinesize 120表示每一行顯示120個字符
col namefor a8 表示8個字符 a字符
cols salfor 9999
/ 表示執行上一條sql語句
Sql優化:
儘量使用列名代替*,因爲使用*,需要解析所有的列名
但是在oracle 9i之後,他們兩個是一樣的,
修改錯誤的sql語句
-c命令 change
2*form emp
c/form/from
ed會把sql語句存入一個文件並打開
3種別名的方式(別名之間如果有空格、sql關鍵字就必須要添加雙引號)
selectsal,sal*12,name as “姓名”,age “年齡”,sex 性別, from emp
selectsal,sal*12 年薪,comm 獎金,sal*12+comm 年收入 from emp
如果獎金沒有年收入就爲0了,
Sql語句中的null值
包含null的表達式都爲null
Sql中null != null。
控制是無效的,未指定的,未知的或不可預知的值
Sal * 12 +nu1(comm,0)//如果comm爲null,就返回0
查詢獎金爲null的員工
Select * from emp where comm=null這是不對的
Select * from emp where comm Is null(is not null)
Select distinct name from emp;
Select distinct deptno,job from emp;
Distinct作用於後面所有的列
Sql語言大小寫不敏感
連接符:
concat鏈接字符串 selectconcat(‘hello’,’world’) from emp
如果emp有14條記錄,就會顯示14條語句
select concat(‘hello’,’world’) from dual
dual表:僞表,是管理員提供的,不是我們創建的
sql 99 ANSI發佈的標準所以oracle中select後面必須有from,而mysql可以沒有
select‘hello’| | ‘world’from dual;//helloworld
selectename | |’的薪水是’ | | sal fromemp
sql語句與sql*plus命令:
SQL:一種語言
是ANSI的標準
關鍵字不能縮寫
使用語句控制數據庫中的表的定義信息和表中的數據
SQL*PLUS:一種環境
oracle的特性之一
關鍵字可以縮寫
命令不能改變數據庫中的數據的值
集中運行
Select、update、insert、delete
Desc、Col 、set、ed、change是sql plus語句
使用isql*plus可以:(就是sql plus的web版,11g之後就沒有)
描述表結構
Savec:\a.sql
@c:\a.sql加載並且執行
Loadc:\a.sql加載不執行
Spooloff //剛纔操作的所有步驟將被記錄,也就是錄屏命令
過濾:
Select * from emp where empno=10;
Oracle中字符串大小寫和日期格式敏感
1981-11-17不叫日期,17-11月-81符合格式,oracle數據庫中默認
DD-MON-RR格式的日期,是oracle9i之後的格式,9i之前DD-MON-YY(1998-20982098-98)
千年蟲問題,DD-MON-RR解決了這個問題,
查詢當前時間
selectnow()//mysql
selectsysdate from dual;//oracle
--查詢系統參數
Setlinesize 150
Col parameter for a20
select *from v$nls_parameters; // v$nls_parameters數據字典
--修改日期格式
Altersession | globle(全局)setNLS_DATA_FORMAT =’yyyy-mm-dd’
<<=>between and(含邊界,小的在前,大的在後面)inlikeis null
Select *from emp where depot in(10,20); not in(10,20)
那麼in(set)這個集合裏面能不能有null值呢?如果集合中含有null,不能使用not in操作符,但是可以使用in操作符
Like表示的是模糊查詢 %任意長度的任意字符串_ 任意的字符串
查詢名字是四個字的員工 select * from emp where enamelike ‘_ _ _ _’.
查詢名字中含有下劃線的員工
select * from emp where ename like ‘% \ _%’escape ‘\’;
select * from emp where ename like ‘% a_%’escape ‘a’;
rollback;// 回退,可以做這一步的原因就是前面做的事在一個事務中,mysql中通過start Transaction 開啓事務,oracle自動開啓的事務。
And 邏輯並 or 邏輯或not 邏輯否
Sql優化第二點:
Where condition1 and condition2
Where condition2 and condition1
這兩句執行的結果是一樣的嗎,但是性能不一樣。
Oracle解析where條件的時候是從右至左,對於and條件把有可能爲false的條件放在右邊,因爲右邊第一個爲false,其他的就不會執行
可以使用括號改變優先級
Order by字句 ascend (升序)descend(降序)默認是升序--
--a命令 append
adesc//a後面至少加上兩個空格,因爲如果一個的話就默認在sql後面加上desc
order by 後面+列名、表達式、別名、序號
order bysal * 12 + ny1(comm.,0)
selectcomm. As ‘年收入’fromemporder by “年收入”
order by4//第四列列數不能超過表中的總列數
order by後面可以有多列嗎?
Order bydeptno,sal ;這樣排序作用於所有的列,如果第一列相同,則按照第二列排序
Order bydeptno,sal desc // 這樣desc是作用於離他最近的一列,如果都要降序
Order bydeptno desc ,sal desc
按照獎金排序(獎金有可能爲null)
Setpagesize 20//每一頁顯示的條數
Order bycomm.;// 升序是沒有問題的
Order bycomm. desc;這樣的話 comm.爲null的都會在前面,而有數據的在後面進行排序
Order bycomm. desc nulls last ;// 這樣就可以解決null在後面,oracle有,這個不符合sql 99
函數;
單行函數:一個輸入、一個輸出,只對一行進行變換。
多行函數:多個輸入、一個輸出
單行函數:字符、數值、日期、通用、轉換等
字符函數:
大小寫控制函數:lower、upper、initcap(首字母大寫)
字符控制函數
concat、
substr(a,b從a中,第b位開始取)(a,b,c取c位)、
length(字符數)|lengthb(字節數)、instr(a,b在一個串中查找字串,返回下標,從1開始,否則返回0)、lpad|rpad(a,10,‘*’10位多餘的*填充,左填充、又填充)、trim(去掉前後指定的字符)、replace
trim(‘H’ from ‘Hello’)
replace (‘hello’,’l’,’L’)
數字函數:
Round 四捨五入
Round (45.926,2)--45.93 小數點後兩位
Round (45.926,-1)-- 50
Round (45.926,-2)--0
Trunc 截斷
trunk(45.926,2)--45.92
trunk(45.926,0)--45.92
trunk(45.926,-1)--40
trunk(45.926,-2)--0
Mod 求餘mod(1600,300)--100
日期:
Oracle中的日期類型數據實際含有兩個值:日期和時間
默認的日期格式DD-MON-RR
Select to_char(sysdate,’yyyy-mm-ddhh24:mi:ss’) from dual;
selectto_char(systimestamp,’yyyy-mm-dd hh24:mi:ss*ff’)from dual
日期的數學運算:
在日期上加上或減去一個數字結果爲日期(但是不允許日期+日期,因爲今天加上明天沒有任何意義)
Select (sysdate-1),sysdate,sysdate+1from dual;
在兩個日期相減返回日期之間相差的天數
Selectename,hiredate,(sysdate-hiredate)天,(sysdate-hiredate)/7星期,(sysdate-hiredate)/30月,(sysdate-hiredate)/365年.
可以用數子除24來向日期中加上或減去小時
日期函數;
Months_between兩個日期相差的天數
Add_month指定日期上加上若干月數
Next_day指定日期的下一個日期select next_day(sysdate,7)下個禮拜的今天
Last_day本月的最後一天
Round日期四捨五入
Trunk日期截斷
Selectmonths_between(sysdate,hiredate)(相減) 算準工齡
快照 snapshot 給數據庫拍個照片,數據庫出問題後可以恢復
Now date----- 25-7-95
round(sysdate,’MONTH’)--à01-8-95
round(sysdate,’YEAR’)---à 01-1-96
trunk(sysdate,’MONTH’)--à01-7-95
trunk(sysdate,’YEAR’)--à01-1-95
日期格式的元素:
YYYY 2011
YEAR
MM 04
MONTH4月
DY|DAY 星期一
DD02
轉換函數:
隱性:’123’à123(有一個前提:被轉換對象是可以轉換的)
Varchar2 --à number
Varchar2 --à date
Char--ànumber
Char--àdate
To_char(123) 、to_number(‘123’)、to_date
顯性:
Select to_char(sysdate,’yyyy-mm-ddhh24:mi:ss “今天是” day’)
To_char(number,’fomat’)
9數字0零$美元L本地貨幣.小數點,千位符
查詢員工的薪水,貨幣符號,兩位小數
Selectsal,to_char(sal,’L9,999.99’)-à2598¥2,598.00
???to_number
通用函數;
Nvl(a,b)慮空函數當a爲null時返回b
Nvl2(a,b,c)當a爲null時返回c否則返回b
Nullif(a,b) a==b時返回null,否則返回a
Coalesce(a,b,c...)從左至右找到第一個不爲null的值返回
條件表達式;
在 SQL語句中使用if-then-else邏輯
使用兩種方法:
Case表達式:sql99的語法類似Basic,比較繁瑣
Decode函數:oracle自己的語法,類似java
Case expr when expr1 then return_expr1
[whenexpr1 then return_expr1
Else else_expr
]
End
Decode(col|expred,search1,result[search1,result][default])
根據職位漲薪水(總裁1000、經理400、其他100)
Select ename,job,sal,case job when‘president’ then sal+100
When‘manager’ then sal+400
Elsesal+100
End ‘漲後薪水’
Selectename,job,sal,decode(job,’president’,sal+1000,
‘manager’,sal+400,
Sal+100) ‘漲後薪水’
使用decode函數:根據80號部門員工的工資,顯示稅率
Selectlast_name,sal,decode(trunk(sal/2000,0),
0,0.00,
1,0.09,
2,0.20,
3,0.30,
0.45) tax_rate
From employees
Where depart_id = 80
分組函數:作用於一組數據,並對一組數據返回一個數據
Avg
Count:
Max
Min
Sum
組函數會自動慮空,只會統計非空的數據
Count(*) count(nvl(comm,0))
Count(distinct dept_id)
Group by
在select列表中所有沒有包含在組函數中的列都應該包含在groupby後面
包含在group by中的列不必包含在select列表中
求各個部門的平均工資
Select depno,avg(sal) from emp group bydepno
Select depno,depname,avg(sal) from empgroup by depno(mysql)
Select depno,depname,avg(sal)
from emp
group by depno,depname(oracle)
如果group by後面有多列怎麼分組呢?
先按照第一列分,如果第一列相同,再按照第二列、、、、
上述語句的效果是按照部門中的每個職位分組
不能再where字句中使用組函數
Having:把滿足條件的結果選出來,前提條件是必須要分組(過濾分組)
求出部門平均工資大於2000的部門
Selectdeptno,avg(sal)
Fromemp
Groupby deptno
Havingave(sal)>2000;
SQL優化三:
Having 和 where 的區別
求10號部門的平均工資
Select deptno,avg(sal)
From emp
Group deptno
Having deptno = 10;
Selectdeptno,avg(sal)
From emp
wheredeptno = 10;
如果having和where在業務中都可以儘量使用where,效率高於having
Where是先過濾再分組(先選出10號,再求)
Having是先分組再過濾(先對全部的分組,再過濾10號)
有一種情況例外只能使用having:如果條件中含有組函數只能使用having
嵌套組函數max(avg(sal))
Group by 語句增強
按照部門統計個部門不同工種的工資情況,要求如下:
Deptnojobsum(sal)
10clerk1300
Manager2450
3750
20clerk1900
Manager2692
7592
11342
Group by deptno,job
+
Group by deptno
+
Group by null
=
Group by rollup(deptno,job)
同理:
Group by rollup(deptno,job)
=
Group by deptno,job
+
Group by deptno
+
Group by null
Break on deptno skip 2// 以depto分段,跳躍空2行
Select depot,job,sum(sal)
From emp
Group by rollup(deptno,job)
多表的查詢:
笛卡爾積:
Table120行5列table2 8行2列
笛卡爾積 20 * 8 = 160行5 + 2 = 7 列
多表查詢就是從這個笛卡爾積中選出所符合條件的結果
Oracle鏈接;
Equijoin :等值鏈接whereemp.deptno = dep.deptno;
Non-equijion:不等值鏈接where emp.deptno between 10and 20
Outer join:外連接
Self join:自連接
外連接:
按部門統計員工人數-à部門號、部門名稱、人數
Selectd.deptno,d.dname,count(e.empno)
From dept d,emp e
Where d.deptno = e.deptno(1)
Group by d.deptno,d.dname(如果某個部門沒有員工,這樣查不正確的)
外連接解決的問題:當條件不成立時候,仍然希望在結果中包含不成立的記錄
左外連接:== 左邊代表的表信息仍然包含在結果中
左外連接的表是在 == 的右邊
寫法把(1)改爲 -à where e.deptno = d.deptno(+);
右外連接:與左外連接相反
自連接:核心是利用表的別名,將同一張表視爲多張表
查詢XX的老闆是YY
Selecte.ename||’的老闆是’||b.ename
Fromemp e,emp b
Wheree.mgr = b.empno;
層次查詢:
自連接查找大表的時候(1億行),笛卡爾積會很大,會嚴重影響性能,因此自連接不適合大表
層次查詢可以解決這個問題(就是樹操作,對樹進行遍歷)
層次查詢後面from只能有一張表,因爲不能有笛卡爾積
在層次查詢中不再是表和表做連接操作,而是對同一張表的前後兩次操作進行連接
上一層的員工就是下一層員工的老闆,要遍歷一棵樹就必須知道根root
Connect by prior empno = mgr start withmgr is null(總boss)
或者 start with empno = 7566(從某一個管理人員開始)
Select level(僞列,層次1,2,3) ,empno,ename,mgr
From emp
Connect by prior empno = mgr
Start with mgr is null;
應用場景:中國-à江西à九江à都昌à街道