第一章:基礎知識
sys : 超級用戶,必須以sysdba身份登陸
system : 必須以normal身份登陸.
scott
tiger
練習:配置一個服務命名,連接鄰近同學的數據庫;
第二章 簡單的select語句
1. 分類
1> DQL (DATA Quary LANGUAGE)
- SELECT
5> TCL
HR HR
2. SELECT 語句
練習:查詢emp表中所有列的信息
SELECT *
FROM emp;
練習:查詢emp表員工的名字和工資
SELECT ename, sal
FROM emp;
3. 表達式
1> 算術表達式
練習:查詢emp表中員工的姓名和年薪
SELECT ename, sal * 12
FROM emp;
2> 字符串連接表達式(用 || 進行連接)
-- 注意:在Oracle中字符串常量要寫在單引號中
-- 在字符串中,用兩個單引號來顯示單引號(即用單引號來轉義單引號)
練習:查詢emp表中員工的名字和工資,-- XXX's salary is XXX
SELECT ename || '''s salary is ' || sal
FROM emp;
4. NULL
-- null在Oracle SQL中是一個比較特殊的值,它既不代表空字符串,也不代表0
-- 任何數據類型都支持null
-- 1〉如果null在算術表達式中出現,其結果一定是null;
-- 2〉如果null在字符串連接表達式中出現,當字符串連接一個null的話,其結果還是原來的字符串;
練習:查詢emp表中員工的姓名和年薪(考慮comm列)
-- 空值轉化的方法,以後再說
SELECT ename, (sal + comm) * 12
FROM emp;
練習:查詢emp表中員工的名字和工資,-- XXX's salary is XXX
SELECT ename || '''s salary is ' || sal || null
FROM emp;
5. 列別名
-- 列別名中不能包含空格等特殊字符,如果包含,別名一定要寫在雙引號中
SELECT ename, (sal + comm) * 12 AS "Annual salary"
FROM emp;
6. DISTINCT -- 重複記錄只顯示一次
練習:查詢emp表中員工在哪些部門中工作,列出部門編號
SELECT DISTINCT deptno
FROM emp;
第三章 限制數據和對數據排序
練習:查詢emp表中10部門員工姓名和工資
SELECT ename, sal
FROM emp
WHERE deptno = 10;
1. 比較運算符
= 等於
>, <, >=, <=,
<> 不等於
-- 比較運算符兩端類型要一致
練習:查詢emp表中工資高於3000的員工的名字和工資
SELECT ename, sal
FROM emp
WHERE sal > 3000;
-- 關鍵字和對象(表,或列名等)的名字不區分大小寫
-- 表中存儲的字符型的數據是嚴格區分大小寫的
-- 如果不知道表中數據如何存儲,怎樣進行字符串的匹配? 以後再說
練習:查詢emp表中姓名是scott的員工的信息
SELECT *
FROM emp
WHERE ename = 'SCOTT';
-- 在oracle SQL中,日期類型的常量也要寫在單引號中
-- 日期的默認格式 'DD-MON-YYYY',月份在中文環境下,要寫成 4月
-- 有語言區域的限制,不建議使用,有更好的替代方法,以後再說。
練習:查詢emp表中入職時間是1987-4-19號的員工的信息
SELECT *
FROM emp
WHERE hiredate = '19-4月-1987'; -- 漢字 月 不能忘
ALTER SESSION SET nls_language = 'AMERICAN'; -- 修改當前會話的語言環境
SELECT *
FROM emp
WHERE hiredate = '19-APR-1987'; -- 英文環境下應該寫月份英文的縮寫
ALTER SESSION SET nls_language = 'SIMPLIFIED CHINESE';
練習:查詢emp表中20部門工資小於2000的員工的姓名,工資以及部門編號
SELECT ename, sal, deptno
FROM emp
WHERE deptno = 20 AND sal < 2000;
練習:查詢emp表中10和30部門員工的信息
SELECT *
FROM emp
WHERE deptno = 10 OR deptno = 30;
練習:查詢emp表中工資在1250到3000之間的員工的信息(包括端點)
SELECT *
FROM emp
WHERE sal >= 1250 AND sal <= 3000;
2. 幾種特殊的比較運算符
1> BETWEEN AND -- 包括端點的,小的寫前面,大的端點寫後面
練習:查詢emp表中工資在1250到3000之間的員工的信息(包括端點)
SELECT *
FROM emp
WHERE sal BETWEEN 1250 AND 3000;
SELECT *
FROM emp
WHERE sal NOT BETWEEN 1250 AND 3000; -- 加了not,不包括端點
2> IN
練習:查詢emp表中10和30,20,50部門員工的信息
SELECT *
FROM emp
WHERE deptno IN (10, 20, 30, 50);
SELECT *
FROM emp
WHERE deptno not IN (10, 20);
3> LIKE -- 字符串的模糊匹配
-通配符
- i. _ 代表一個字符,不包括零字符
- ii. % 代表任意長度的字符串,包括零字符
練習:查詢emp表中姓名以 S開頭的員工的信息
SELECT *
FROM emp
WHERE ename LIKE 'S%';
SELECT *
FROM emp
WHERE ename NOT LIKE 'S%';
練習:查詢emp表中姓名的第二個字符是O的員工的信息
SELECT *
FROM emp
WHERE ename LIKE '_O%';
練習:查詢emp表中姓名至少含有一個E的員工的信息
SELECT *
FROM emp
WHERE ename LIKE '%E%';
練習:查詢emp表中姓名的第二個字符是O,且長度是4個字符的員工的信息
SELECT *
FROM emp
WHERE ename LIKE '_O__';
練習:查詢emp表中姓名是5個字符的員工的信息
SELECT *
FROM emp
WHERE ename LIKE '_____';
CREATE TABLE emp1 AS SELECT * FROM emp;
UPDATE emp1 SET job = 'M_' || job WHERE job = 'CLERK';
-- escape子句定義轉義字符,對匹配字符串中的符號進行轉義
練習:查詢emp1表中職位以M_開頭的員工的信息
SELECT *
FROM emp1
WHERE job LIKE 'M+_%' ESCAPE '+';
4> IS NULL
-- Oracle中,null只有用is null或is not null來判斷的時候,纔會返回true或false,否則都是null
練習:查詢emp表中沒有補助的員工的信息
SELECT *
FROM emp
WHERE comm is NULL;
SELECT *
FROM emp
WHERE comm IS NOT NULL;
3. 排序 -- order by是最後一個子句
練習:查詢emp表中20部門所有員工的姓名和工資,按工資升序排序
SELECT ename, sal
FROM emp
WHERE deptno = 20
ORDER BY sal;
練習:查詢emp表中所有員工的姓名和年薪,按照年薪進行降序排序
SELECT ename, sal * 12
FROM emp
ORDER BY sal * 12 DESC;
SELECT ename, sal * 12 annsal
FROM emp
ORDER BY annsal DESC;
-- 多列排序
-- ASC或DESC只修飾前面的一列
SELECT ename, deptno, sal
FROM emp
ORDER BY deptno, sal DESC;
第四章 單行函數
-- 在oracle中,函數如果沒有參數,調用的時候不要寫括號
-- 單行函數:不同於分組函數,會對結果集中每一條記錄執行一次,每一條記錄返回一個結果。
一. 字符型
1. 大小寫轉換
-- dual: 是sys用戶下的一個表,本身沒有任何意義,它的作用就是用來補全SQL語句
練習:將'I love SQL'分別以全小寫,全大寫和首字符大寫的形式輸出
SELECT LOWER('I love SQL'), UPPER('I love SQL'), INITCAP('I love SQL')
FROM dual;
練習:查詢emp表中姓名是scott的員工的信息
SELECT *
FROM emp
WHERE UPPER(ename) = 'SCOTT';
2. CONCAT -- 字符串的連接
練習:將 'I love '和'SQL'連接
SELECT CONCAT('I love ', 'SQL') FROM dual;
-- 函數是可以嵌套的,單行函數理論上是可以無限嵌套;
-- 函數有內向外依次執行;
練習:將 'I', ' love '和'SQL'連接
SELECT CONCAT(CONCAT('I', ' love '), 'SQL') FROM dual;
3. SUBSTR(源字符串, m [, n]) -- 從源字符串的第m個字符開始,截取n個字符(如果省略n,默認是提取到字符串的末尾)
SELECT SUBSTR('I love SQL', 3, 4) FROM dual; -- 在Oracle中,所有的計數都是從1開始
練習:將'Hi, my name is Mike, i am from american, I love SQL'中的'SQL'提取出來
SELECT SUBSTR('I love SQL', 8, 3) FROM dual;
SELECT SUBSTR('I love SQL', 8) FROM dual;
-- 如果m爲負數,那麼是從右往左進行計數
SELECT SUBSTR('Hi, my name is Mike, i am from american, I love SQL', -3, 3) FROM dual;
SELECT SUBSTR('Hi, my name is Mike, i am from american, I love SQL', -3) FROM dual;
4. LENGTH(字符串) -- 返回長度
SELECT LENGTH('I love SQL') FROM dual;
5. INSTR(源字符串, 子串[, m [, n]]) -- 返回一個整數,是子串在源字符串中從第m個字符開始,第n次出現的位置,m,n默認都是1
SELECT INSTR('I Love SQL', 'L') FROM dual;
SELECT INSTR('I Love SQL', 'L', 1, 2) FROM dual;
SELECT INSTR('I Love SQL', 'L', 5, 1) FROM dual;
SELECT INSTR('I Love SQL', 'L', 5, 2) FROM dual; -- 如果沒有找到,會返回0
練習:加密IP地址的SQL語句
-- 加密前
'192.168.181.75'
'10.10.23.35'
-- 加密後
'192.168.181.*'
'10.10.23.*'
SELECT CONCAT(SUBSTR('10.10.23.35',
1,
INSTR('10.10.23.35', '.', 1, 3)),
'*')
FROM DUAL;
6. LPAD(源字符串, n, 子串), RPAD(源字符串, n, 子串)
-- 將源字符串用子串在左邊(右邊)填充至n個長度
SELECT LPAD('SQL', 10, '*') FROM dual;
7. TRIM([BOTH|LEADING|TRAILING] 字符 FROM 源字符串) -- 截去源字符串頭尾的給定字符
SELECT TRIM(BOTH 'l' FROM 'level') FROM dual; -- 頭尾都去
SELECT TRIM(LEADING 'l' FROM 'level') FROM dual; -- 只去頭的,不去尾的
SELECT TRIM(TRAILING 'l' FROM 'level') FROM dual; -- 只去尾的,不去頭的
-- 第二種用法,去除字符串頭尾的空格
-- trim(字符串)
SELECT ' mike ', TRIM(' mike ') FROM dual;
8. REPLACE
練習:將'I Love SQL'中的'SQL'替換成'Oracle'
SELECT REPLACE('I Love SQL', 'SQL', 'Oracle') FROM dual;
二. 數字函數
1. round(數字, n) -- 將給定的數字四捨五入到小數點後n位
SELECT ROUND(654.38, 1) FROM dual;
SELECT ROUND(654.38, 0) FROM dual;
SELECT ROUND(654.38, -1) FROM dual;
SELECT ROUND(654.38, -2) FROM dual;
SELECT ROUND(654.38, -3) FROM dual;
2. TRUNC(數字, n) -- 將給定的數字截斷到小數點後n位
SELECT TRUNC(654.38, 1) FROM dual;
SELECT TRUNC(654.38, 0) FROM dual;
SELECT TRUNC(654.38, -3) FROM dual;
3. MOD(m, n) -- 取m/n後的餘數
SELECT MOD(10, 5) FROM dual;
三. 日期函數
1. SYSDATE -- 返回oracle服務器的系統時間
SELECT SYSDATE FROM dual;
SELECT SYSDATE + 1/24/60/60/1000 FROM dual;
2. months_between -- 返回兩個日期之間間隔的月數
練習:計算emp表中員工工作的月數。
SELECT ename, hiredate, months_between(SYSDATE, hiredate)
FROM emp;
練習:計算同學自己的年齡,結果四捨五入到小數點後三位
SELECT round(months_between(SYSDATE, '1-4月-1980')/12, 3) FROM dual;
3. add_months
SELECT add_months(SYSDATE, 2) FROM dual;
SELECT add_months('29-2月-2012', 1) from dual; -- 如果給定的日期是某個月的最後一天,那麼返回的也是對應月的最後一天
練習:查詢emp表中所有的員工的轉正日期(試用期3個月)
SELECT ename, add_months(hiredate, 3)
FROM emp;
4. next_day(日期, '星期×'|n) -- 返回給定日期後一週內下一個星期×的日期
SELECT next_day(SYSDATE, '星期二') FROM dual;
SELECT next_day(SYSDATE, '星期一') FROM dual;
SELECT next_day(SYSDATE, '星期日') FROM dual;
-- 注意,n=1,代表星期日
SELECT next_day(SYSDATE, 1) FROM dual;
5. last_day -- 返回給定日期當月的最後一天
SELECT last_day(SYSDATE) FROM dual;
6. ROUND(日期, '特徵字符串') -- YY - 年, MM - 月, DD- 日
練習:emp表 月末發工資,上半月來的,領全月工資,下半月來的,從下個月1號開始計算工資
查詢emp表中所有員工,計算工資的起始日期是那一天。
SELECT ename ,hiredate ,ROUND(hiredate, 'MM')
FROM emp;
7. TRUNC(日期, '特徵字符串') -- YY - 年, MM - 月, DD- 日
練習:emp表 月末發工資,不管上半月還是下半月,都發全月工資,查詢emp表中所有員工,計算工資的起始日期是那一天。
SELECT ename ,hiredate ,TRUNC(hiredate, 'MM')
FROM emp;
四. 類型轉換
- 隱式類型轉換
SELECT * FROM emp WHERE deptno = '10';
- oracle是支持隱式類型轉換
- 隱式類型轉換是有規則的
-- 不建議大家使用隱式類型轉換
-- 1. 代碼可讀性很差;
-- 2. 執行效率會很低;
-- 3. oracle官方並沒有承諾在下一個版本不改變規則。
- 顯式類型轉換
1. to_char(日期|數字, 'fmt') -- 特徵(格式)字符串
-- 日期 --> 字符
練習:輸出當前系統的日期, 2012/3/5
SELECT to_char(SYSDATE, 'fmYYYY/MM/DD') FROM dual;
-- fm 去掉前導零
練習:提取當前日期中的年
SELECT to_char(SYSDATE, 'DY') FROM dual;
練習:輸出當前系統的時間, 16:31:22
SELECT to_char(SYSDATE, 'HH24:MI:SS') FROM dual;
練習:輸出當前系統的日期和時間 2012/3/5 16:31:22
SELECT to_char(SYSDATE, 'fmYYYY/MM/DD HH24:MI:SS DY') FROM dual;
SELECT to_char(SYSDATE, 'DDSP') FROM dual;
練習:輸出當前系統的日期和時間 '今天是2012年3月5日'
SELECT to_char(SYSDATE, 'fm"今天是"YYYY"年"MM"月"DD"日"') FROM dual;
-- 數字 --> 字符
練習:查詢emp表中King工資數,並以 '$5,000.00'
SELECT ename, to_char(sal, '$9,999.00')
FROM emp WHERE ename = 'KING';
-- 注意,轉換過程中,整數位一定要足夠寬,否則結果就是 #########
練習:查詢emp表中King工資數,換算成人民幣,並以 ¥5,000.00
SELECT ename, to_char(sal*6, 'L999,999.00')
FROM emp WHERE ename = 'KING';
練習:查詢emp表中入職時間是1987-4-19號的員工的信息
SELECT *
FROM emp
WHERE hiredate = to_date('19-4-1987', 'DD-MM-YYYY');
五. 其他函數
1. NVL
練習:查詢emp表中員工的姓名和年薪(考慮comm列)
SELECT ename, (sal + NVL(comm, 0)) * 12
FROM emp;
2. NVL2
練習:查詢emp表中員工的姓名和年薪(考慮comm列)
SELECT ename, NVL2(comm, sal + comm, sal) * 12
FROM emp;
3. COALESCE
練習:查詢emp表中員工的姓名和年薪(考慮comm列)
SELECT ename, COALESCE(sal+comm, sal, 0) * 12
FROM emp;
4. case表達式
CASE 列|表達式
WHEN 值1 THEN 返回值1
WHEN 值2 THEN 返回值2
...
WHEN 值N THEN 返回值N
ELSE 默認返回值
END
練習:查詢emp表中員工的姓名和部門(部門用漢字 10 --部門1 20 -- 部門2 30 -- 部門3)
SELECT ename,
CASE deptno
WHEN 10 THEN '部門1'
WHEN 20 THEN '部門2'
ELSE '部門3'
END
FROM emp;
5. DECODE -- 就是case表達式的簡便寫法
- DECODE(列|表達式, 值1, 返回值1, 值2, 返回值2, ...值N, 返回值N, 默認返回值)
練習:查詢emp表中員工的姓名和部門(部門用漢字 10 --部門1 20 -- 部門2 30 -- 部門3)
SELECT ENAME, DECODE(DEPTNO, 10, '部門1', 20, '部門2', '部門3') FROM EMP;
-- a代表整數
DECODE(a, 0, 1, 0) -- 邏輯取反