Oracle_SQL 資料操作和查詢
1、SQL簡介
SQL 是結構化查詢語言(Structured Query Language),專門用於資料存取、資料更新及資料庫管理等操作。
在 Oracle 開發中,客戶端把 SQL 語句傳送給伺服器,伺服器對 SQL 語句進行編譯、執行,把執行的結果返回給客戶端。Oracle SQL 語句由如下命令組成:
- 資料定義語言(DDL),包括 CREATE(建立)命令、ALTER(修改)命令、DROP(刪除)命令等。
- 資料操縱語言(DML),包括 INSERT(插入)命令、UPDATE(更新)命令、DELETE(刪除)命令、SELECT … FOR UPDATE(查詢)等。
- 資料查詢語言(DQL),包括基本查詢語句、Order By 子句、Group By 子句等。
- 事務控制語言(TCL),包括 COMMIT(提交)命令、SAVEPOINT(儲存點)命令、ROLLBACK(回滾)命令。
- 資料控制語言(DCL),GRANT(授權)命令、REVOKE(撤銷)命令。
目前主流的資料庫產品(比如:SQL Server、Oracle)都支援標準的 SQL 語句。資料定義語言,表的增刪改操作,資料的簡單查詢,事務的提交和回滾,許可權的授權和撤銷等,Oracle與 SQL Server 在操作上基本一致。
2、Oracle資料型別
Oracle 資料庫的核心是表,表中的列使用到的常見資料型別如下:
型別 | 含義 |
CHAR(length) | 儲存固定長度的字串。引數 length 指定了長度,如果儲存的字串長度小於 length,用空格填充。預設長度是 1,最長不超過 2000 位元組。 |
VARCHAR2(length) | 儲存可變長度的字串。length 指定了該字串的最大長度。預設長度是 1,最長不超過 4000 字元。 |
NUMBER(p,s) | 既可以儲存浮點數,也可以儲存整數,p 表示數字的最大位數(如果是小數包括整數部分和小數部分和小數點,p 預設是 38 為),s 是指小數位數。 |
DATE | 儲存日期和時間,儲存紀元、4 位年、月、日、時、分、秒,儲存時間從公元前 4712 年 1 月 1 日到公元后 4712 年 12 月 31 日。 |
TIMESTAMP | 不但儲存日期的年月日,時分秒,以及秒後 6 位,同時包含時區。 |
CLOB | 儲存大的文字,比如儲存非結構化的 XML 文件 |
BLOB | 儲存二進位制物件,如圖形、視訊、聲音等。 |
對應的NUMBER型別的例項:
格式 | 輸入的數字 | 實際的儲存 |
NUMBER | 1234.567 | 1234.567 |
NUMBER(6,2) | 123.4567 | 123.46 |
NUMBER(4,2) | 12345.67 | 輸入的數字超過了所指定的精度,資料庫不能儲存 |
對於日期型別,可以使用 sysdate 內建函式可以獲取當前的系統日期和時間,返回 DATE型別,用 systimestamp 函式可以返回當前日期、時間和時區。
Oracle 的查詢中,必須使用“select 列… from 表”的完整語法,當查詢單行函式的時候,from 後面使用 DUAL 表,dual 表在系統中只有一行一列,該表在輸出單行函式時為了select…from 的語法完整性而使用。
3、建立表和約束
Oracle 建立表使用 CREATE TABLE 命令來完成。建立約束則使用如下命令:
ALTER TABLE 表名 ADD CONSTRAINT 約束名 約束內容
案例1:建立一個學生資訊(INFOS)表和約束:
CREATE TABLE INFOS
(
STUID VARCHAR2(7) NOT NULL, --學號 學號=‘S’+班號+2位序號
STUNAME VARCHAR2(10) NOT NULL, --姓名
GENDER VARCHAR2(4) NOT NULL, --性別
AGE NUMBER(2) NOT NULL, --年齡
SEAT NUMBER(2) NOT NULL, --座號
ENROLLDATE DATE, --入學時間
STUADDRESS VARCHAR2(50) DEFAULT '地址不詳', --住址
CLASSNO VARCHAR2(4) NOT NULL --班號 班號=學期序號+班級序號
) -- 1
ALTER TABLE INFOS ADD CONSTRAINT PK_INFOS PRIMARY KEY(STUID); --2
ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_GENDER CHECK(GENDER = '男' OR GENDER = '女'); --3
ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_SEAT CHECK(SEAT >=0 AND SEAT <=50); --4
ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_AGE CHECK(AGE >=0 AND AGE<=100); --5
ALTER TABLE INFOS ADD CONSTRAINT CK_INFOS_CLASSNO
CHECK((CLASSNO >='1001' AND CLASSNO<='1999') OR
(CLASSNO >='2001' AND CLASSNO<='2999')); --6
ALTER TABLE INFOS ADD CONSTRAINTS UN_STUNAME UNIQUE(STUNAME); --7
程式碼解析:
- 1 在 Oracle 程式碼中,“/”執行快取區中的語句,由於緩衝區中只儲存一條剛剛儲存過語句,由於每條語句沒有用分號結尾,只是儲存在緩衝區,因此每條語句後面都有單獨一行“/”。
- 2 建立一個主鍵約束。
- 3 與 4 5 6 7一起建立各種 check 約束。其中⑦是唯一約束,表示該列值是唯一的,列中的值不能重複。
案例2:建立一個成績表(SCORES)表和約束:
CREATE TABLE SCORES
(
ID NUMBER , --ID 1
TERM VARCHAR2(2), --學期 S1或S2
STUID VARCHAR2(7) NOT NULL, --學號
EXAMNO VARCHAR2(7) NOT NULL, --考號 E+班號+序號
WRITTENSCORE NUMBER(4,1) NOT NULL, --筆試成績
LABSCORE NUMBER(4,1) NOT NULL --機試成績
)
ALTER TABLE SCORES ADD CONSTRAINT CK_SCORES_TERM CHECK(TERM = 'S1' OR TERM ='S2');
ALTER TABLE SCORES ADD CONSTRAINT FK_SCORES_INFOS_STUID FOREIGN KEY(STUID) REFERENCES INFOS(STUID); --2
程式碼解析:
- 1 SQL Server 中可以使用 identify 建立自動增長列,但是 Oracle 中的自動增長需要藉助序列(Sequence)完成,在後面章節中講解。
- 2 Oracle 中的外來鍵約束定義。
4、資料操縱語言(DML)
據操縱語言(DML)用於對資料庫的表中資料進行新增、修改、刪除和 SELECT…For UPDATE(後面專門學習該查詢)操作。
(1)簡單查詢
資料查詢是用 SELECT 命令從資料庫的表中提取資訊。SELECT 語句的語法是:
SELECT *|列名|表示式 FROM 表名 WHERE 條件 ORDER BY 列名
語法解析:
- *表示表中的所有列。
- 列名可以選擇若干個表中的列名,各個列表中間用逗號分隔。
- 表示式可以是列名、函式、常數等組成的表示式。
- WHERE 子句是查詢的條件。
- ORDER BY 要求在查詢的結果中排序,預設是升序。
Oracle 中可以把查詢的結果根據結果集中的表結構和資料形成一張新表。
語法結構:根據結果集建立表
CREATE TABLE 表名 AS SELECT 語句
程式碼演示:根據結果集建立表
CREATE TABLE INFOS1 AS SELECT * FROM INFOS;
使用上面命令建立的新表中,不存在任何約束,並且把查詢的資料一起插入到新表中。如果只複製表結構,只需使查詢的條件不成立(比如 where 1=2),就不會查詢從出任何資料,從而複製一個表結構。
程式碼演示:複製表結構
CREATE TABLE INFOS2 AS SELECT * FROM INFOS WHERE 1=2;
(2)資料插入
語法結構:根據結果集建立表
INSERT INTO 表名(列名 1,列名 2……) VALUES (值 1,值 2……)
語法解析:
- 列名可以省略。當省略列名時,預設是表中的所有列名,列名順序為表定義中列的先後順序。
- 值的數量和順序要與列名的數量和順序一致。值的型別與列名的型別一致。
INSERT INTO INFOS VALUES ('s100102','林沖','男',22,2,TO_DATE('2009-8-9 06:30:10','YYYY-MM-DD HH24:MI:SS'),'西安','1001');
INSERT INTO INFOS VALUES ('s100104','阮小二','男',26,3,SYSDATE,default,'1001');
INSERT INTO INFOS VALUES ('s100105','盧俊義','男',24,3,SYSDATE,'青龍寺','1001');
INSERT INTO INFOS VALUES ('s100106','宋江','男',30,3,SYSDATE,DEFAULT,'1001');
alter table INFOS modify (GENDER varchar2(4));
commit;
程式碼解析:
- 表名後面缺省了列名,預設是表 Infos 中的所有列名,values 中的值要與表中列一一對應,包括順序和資料型別的對應。在 SQL*Plus 中一條語句可以寫在多行,那麼從第二行開始,sqlplus 會為每一行前面給出行號。
- 在 Oracle 中,日期是國際化的,不同的區域安裝的資料庫,預設的日期格式不同,因此為了程式便於移植,日期的輸入要使用 TO_DATE 函式對日期格式化後輸入,採用格式化字串對日期進行格式化時,格式化字串中字元不區分大小寫,常見的格式化字元如下:
- yyyy 表示四位年份
- mm 表示兩位月份,比如 3 月表示為 03
- dd 表示兩位日期
- hh24 表示小時從 0-23,hh12 也表示小時從 0-11。
- mi 表示分鐘
- ss 表示秒
- 在遇到存在預設值的列時,可以使用 default 值代替。
- commit 是把使用者操作(新增、刪除、修改操作)提交,只有提交操作後,資料才能真正更新到表中,否則其他使用者無法查詢到當前使用者操作的結果。
在 Oracle 中,一個 INSERT 命令可以把一個結果集一次性插入到一張表中。使用的語句是:INSERT INTO 表 SELECT 子句,如下示例:
程式碼演示:INSERT 向表中插入一個結果集
INSERT INTO INFOS2 SELECT * FROM INFOS;
在這種語法下,要求結果集中每一列的資料型別必須與表中的每一列的資料型別一致,結果集中的列的數量與表中的列的數量一致。比如表 INFOS2,該表的結構與 INFO 表一樣,那麼可以把 INFO 表中的所有記錄一次性插入到 INFOS2 表中。
程式碼演示:INSERT 向表中插入一個常量結果集
INSERT INTO INFOS
SELECT 's100103','李逵','男',24,3,TO_DATE('2009-8-9 08:00:10','YYYY-MM-DD HH24:MI:SS'),
'青龍寺','1001'
FROM DUAL;
(3)更新資料
語法結構:UPDATE 操作
UPDATE 表名 SET 列名 1=值,列名 2=值…… WHERE 條件
程式碼演示:UPDATE 操作
UPDATE INFOS SET CLASSNO='1002',STUADDRESS='山東萊蕪' WHERE STUNAME='阮小二';
(4)刪除資料
語法結構:DELETE 操作
DELETE FROM 表名 WHERE 條件
程式碼演示:DELETE 操作
DELETE FROM INFOS WHERE STUID='s100103';
(5)TRUNCATE
在資料庫操作中, TRUNCATE 命令(是一個 DDL 命令)可以把表中的所有資料一次性全部刪除,語法是:
TRUNCATE TABLE 表名
TRUNCATE 和 DELETE 都能把表中的資料全部刪除,他們的區別是:
- TRUNCATE 是 DDL 命令,刪除的資料不能恢復;DELETE 命令是 DML 命令,刪除後的資料可以通過日誌檔案恢復。
- 如果一個表中資料記錄很多,TRUNCATE 相對 DELETE 速度快。由於 TRUNCATE 命令比較危險,因此在實際開發中,TRUNCATE 命令慎用。
PS:Oracle 預設安裝中,已經建立了一個 SCOTT 使用者,預設密碼是:tiger,該使用者下有四張表分別是:僱員表(EMP),部門表(DEPT),工資登記表和獎金錶,請參考本章後面的附表。接下來很多操作都是在該使用者下完成的。
5、操作符
(1)算術運算
Oracle 中的算術運算子,沒有 C#中的算術運算子豐富,只有+、-、*、/四個,其中除號(/)的結果是浮點數。求餘運算只能藉助函式:MOD(x,y):返回 x 除以 y 的餘數。
案例3:每名員工年終獎是 2000 元,請顯示基本工資在 2000 元以上的員工的月工資,年總工資。
程式碼演示:查詢中的算術運算
(2) 關係運算和邏輯運算
Oracle 中 Where 子句經中經常見到關係運算和邏輯運算,常見的關係運算有:
運算子 | 說明 | 運算子 | 說明 |
= | 等於 | > | 大於 |
<>或!= | 不等於 | <= | 小於或者等於 |
< | 小於 | >= | 大於或者等於 |
邏輯運算子有三個:AND、OR、NOT
(3)字串連線操作符(||)
在 Oracle 中,字串的連線用雙豎線(||)表示。比如,在 EMP 表中,查詢工資在 2000元以上的姓名以及工作。
程式碼解析:
- Oracle 中字串可以用單引號,也可以用雙引號,在別名中存在空格時,必須用雙引號。在表名、列名時用雙引號。
6、高階查詢
(1)消除重複行
在 Oracle 查詢中結果中,可能出現若干行相同的情況,那麼可以使用 DISTINCT 消除重複行。具體的用法如示例:
(2)NULL操作
如果某條記錄中有缺少的資料值,就是空值(NULL 值)。空值不等於 0 或者空格,空值是指未賦值、未知或不可用的值。任何資料型別的列都可以包括 NULL 值,除非該列被定義為非空或者主鍵。
程式碼演示:EMP 中的 NULL 值
在查詢條件中 NULL 值用 IS NULL 作條件,非 NULL 值用 NOT IS NULL 做條件。
案例 4:查詢 EMP 表中沒有發獎金的員工。
程式碼演示:NULL 值查詢
(3)IN操作
在 Where 子句中可以使用 IN 操作符來查詢其列值在指定的列表中的行。比如:查詢出工作職責是 SALESMAN、PRESIDENT 或者 ANALYST 的員工。條件有兩種表示方法:
- WHERE job = 'SALESMAN ' OR job = 'PRESIDENT ' OR job = 'ANALYST '
- WHERE job IN ('SALESMAN', 'PRESIDENT', 'ANALYST')
程式碼演示:IN 操作
對應 IN 操作的還有 NOT IN,用法一樣,結果相反。
(4) BETWEEN...AND...
在 WHERE 子句中,可以使用 BETWEEN 操作符來查詢列值包含在指定區間內的行。比如,查詢工資從 1000 到 2000 之間的員工。可以使用傳統方法:WHERE SAL>=1000 AND SAL<=2000;也可以使用:WHERE SAL BETWEEN 1000 AND 2000
BWTWEEN 操作所指定的範圍也包括邊界。
程式碼演示:BETWEEN 操作
(5)LIKE 模糊查詢
在一些查詢時,可能把握不準需要查詢的確切值,比如百度搜索時輸入關鍵字即可查詢出相關的結果,這種查詢稱為模糊查詢。模糊查詢使用 LIKE 關鍵字通過字元匹配檢索出所需要的資料行。字元匹配操作可以使用萬用字元“%”和“_ ”:
- %:表示零個或者多個任意字元。
- :代表一個任意字元。
語法是:LIKE '字串'[ESCAPE '字元']。匹配的字串中,ESCAPE 後面的“字元”作為轉義字元。與一期 SQLServer 中 ESCAPE 用法相同。
萬用字元表示式 | 說明 |
'S%' | 以 S 開頭的字串。 |
'_S%' | 第二個字元時 S 的字串。 |
'%30\%%' escape '\' | 包含“30%”的字串,“\”指轉義字元,“\%”在字串中表示一個字元“%”。 |
案例 5:顯示員工名稱以 J 開頭以 S 結尾的員工的姓名、工資和工資。
程式碼演示:LIKE 操作
(6)集合運算
集合運算就是將兩個或者多個結果集組合成為一個結果集。集合運算包括:
- INTERSECT(交集),返回兩個查詢共有的記錄。
- UNION ALL(並集),返回各個查詢的所有記錄,包括重複記錄。
- UNION(並集),返回各個查詢的所有記錄,不包括重複記錄。
- MINUS(補集),返回第一個查詢檢索出的記錄減去第二個查詢檢索出的記錄之後剩餘的記錄。
當使用集合操作的時候,要注意:查詢所返回的列數以及列的型別必須匹配,列名可以不同。
案例 6:查詢出 dept 表中哪個部門下沒有員工。只需求出 dept 表中的部門號和 emp表中的部門號的補集即可。
前面學習過可以通過 insert into …select 把一個結果集插入到另一張結構相同的表中,因此可以使用 union 把若干條記錄一次性插入到一張表中。
(7)連線查詢
Oracle 中對兩個表或者若干表之間的外聯接用(+)表示。
案例 7:請查詢出工資大於 2000 元的,員工姓名,部門,工作,工資。
由於部門名稱在 dept 中,其他的資訊在 emp 表中,需要內聯接才能完成。
程式碼演示:內聯接
也可以使用 SQL/92 標準中的內聯接:
程式碼演示:內聯接
這裡 INNER JOIN 中,關鍵字 INNER 可以省略。
案例 8:請查詢出每個部門下的員工姓名,工資。
案例分析:Emp 表用外來鍵 deptno 引用 Dept 表中的 deptno,在 Dept 表中如果有某些部門沒有員工,那麼用內聯接,沒有員工的部門將無法顯示,因此必須以 Dept 表為基準的外聯接。
程式碼演示:外聯接
程式碼解析:
- (+):Oracle 專用的聯接符,在條件中出現在左邊指右外聯接,出現在右邊指左外聯接。
- 也可以使用 SQL/92 標準的寫法:
程式碼演示:外聯接