Oracle 數據庫(七)—— Oracle SQL語言之多表聯查、子查詢和數據庫增刪改操作

一、SQL 查詢語言

1.1 多表關聯查詢

1.1.1 多表關聯查詢介紹
在實際的應用系統開發中會設計多個數據表,每個表的信息不是獨立存在的,而是若干個表之間的信息存在一定的關係,當用戶查詢某一個表的信息時,很可能需要查詢關聯數據表的信息,這就是多表關聯查詢。

SELECT語句自身是支持多表關聯查詢的,多表關聯查詢要比單表查詢複雜得多。多表關聯查詢有內連接、外連接、自然連接和交叉連接等。

1.1.2 表的別名
在多表關聯查詢時,如果多個表之間存在同名的列,則必須使用表名來限定列的引用。但是,隨着查詢變得越來越複雜,語句就會因爲每次限定列必須輸入表名而變得冗長。

對於這種情況,SQL語言提供了設定表別名的機制,使用簡短的表別名就可以替代原有較長的表名稱,這樣就可以大大縮減語句的長度。

select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a, users as b
 where a.id = b.id

另外,還需要注意一點,一旦在FROM子句中爲表指定了別名,則必須在剩餘的子句中都使用表的別名,而不允許再使用原來的表名稱

  • 表的別名在FROM子句中定義,別名放在表名之後,它們之間用空格隔開。
  • 別名一經定義,在整個查詢語句中就只能使用表的別名而不能再使用表名。
  • 表的別名只在所定義的查詢語句中有效。
  • 應該選擇有意義的別名,表的別名最長爲30個字符,但越短越好。

1.1.3 內連接
內連接是一種常用的多表關聯查詢方式,一般使用關鍵字INNER JOIN來實現。其中,INNER關鍵字可以省略,當只使用JOIN關鍵字時,語句只表示內連接操作。

在使用內連接查詢多個表時,必須在FROM子句之後定義一個ON子句,ON子句指定內連接操作列出與連接條件匹配的數據行,使用比較運算符比較被連接列的值。

簡單地說,內連接就是使用JOIN指定用於連接的兩個表,使用ON指定連接表的連接條件。若進一步限制查詢範圍,則可以直接在後面添加WHERE子句。

內連接的語法格式如下:

SELECT columns_list
  FROM table_name1 [INNER] JOIN table_name2
    ON join_condition;
  • columns_list:字段列表。
  • table_name1和table_name2:兩個要實現內連接的表。
  • join_condition:實現內連接的條件表達式。
select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a inner join users as b
    on a.id = b.id

1.1.4 外連接
使用內連接進行多表查詢時,返回的查詢結果中只包含符合查詢條件和連接條件的行。內連接消除了與另一個表中的任何行不匹配的行,而外連接擴展了內連接的結果集,除了返回所有匹配的行外,還會返回一部分或全部不匹配的行,這主要取決於外連接的種類。

外連接通常有以下3種。

  • 左外連接:關鍵字爲LEFT OUTER JOINLEFT JOIN
  • 右外連接:關鍵字爲RIGHT OUTER JOINRIGHT JOIN
  • 完全外連接:關鍵字爲FULL OUTER JOINFULL JOIN
    與內連接不同的是,外連接不只列出與連接條件匹配的行,還能夠列出左表(左外連接時)、右表(右外連接時)或兩個表(全部外連接時)中所有符合搜索條件的數據行。

(1)左外連接
左外連接的查詢結果中不僅包含了滿足連接條件的數據行,而且還包含左表中不滿足連接條件的數據行。

select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a left join users as b
    on a.id = b.id

(2)右外連接
右外連接的查詢結果中不僅包含了滿足連接條件的數據行,而且還包含右表中不滿足連接條件的數據行。

select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a right join users as b
    on a.id = b.id

在外連接中也可以使用外連接的連接運算符,外連接的連接運算符爲“(+)”,該連接運算符可以放在等號的左邊,也可以放在等號的右邊,但一定要放在缺少相應信息的那一邊。

//左外連接
select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a, users as b
 where a.id = b.id(+)

//右外連接
select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a, users as b
 where a.id(+) = b.id

使用“(+)”操作符時應注意:

  • 當使用“(+)”操作符執行外連接時,如果在WHERE子句中包含多個條件,則必須在所有條件中都包含“(+)”操作符。
  • “(+)”操作符只適用於列,而不能用在表達式上。
  • “(+)”操作符不能與ON和IN操作符一起使用。

(3)完全外連接
在執行完全外連接時,Oracle會執行一個完整的左外連接和右外連接查詢,然後將查詢結果合併,並消除重複的記錄行。

select a.id ida, a.name namea, a.sal, b.id idb, b.name nameb, b.age 
  from emp as a full join users as b
    on a.id = b.id

1.1.5 自然連接
自然連接和內連接的功能相似,自然連接是指在檢索多個表時,Oracle會將第一個表中的列與第二個表中具有相同名稱的列進行自動連接。

在自然連接中,用戶不需要明確指定進行連接的列,這個任務由Oracle系統自動完成,自然連接使用NATURAL JOIN關鍵字。

select id, name, sal, age 
  from emp natural join users

由於自然連接強制要求表之間必須具有相同的列名稱,這樣容易在設計表時出現不可預知的錯誤,所以在實際應用系統開發中很少用到自然連接。

需要注意的是,在使用自然連接時,不能爲列指定限定詞(即表名或表的別名),否則Oracle系統會彈出“ORA-25155: NATURAL連接中使用的列不能有限定詞”的錯誤提示。

1.1.6 自連接
在應用系統開發中,用戶可能會擁有“自引用式”的外鍵,“自引用式”外鍵是指表中的一個列可以是該表主鍵的一個外鍵。

自連接主要用在自參考表上顯示上下級關係或者層次關係,自參照表是指在同一張表的不同列之間具有參照關係或主從關係的表。

select id1, id2, name, sal, age 
  from emp a left join emp b
    on a.id1 = b.id2

因爲自連接是在同一張表之間的連接查詢,所以必須定義表別名。

1.1.7 交叉連接
交叉連接實際上就是不需要任何連接條件的連接,它使用CROSS JOIN關鍵字來實現,其語法格式如下:

select colums_list
  From table_name1 cross join table_name2
  • colums_list:字段列表。
  • table_name1和table_name2:兩個實現交叉連接的表名。

交叉連接的執行結果是一個笛卡爾積,這種查詢結果是非常冗餘的,但可以通過WHERE子句來過濾出有用的記錄信息

1.2 子查詢

1.2.1 子查詢介紹
在執行數據操作(包括查詢、添加、修改和刪除等)的過程中,如果某個操作需要依賴於另外一個SELECT語句的查詢結果,那麼就可以把SELECT語句嵌入到該操作語句中,這樣就形成了一個子查詢。實際上,在關係型數據庫中,各表之間的數據關係非常密切,它們相互關聯,相互依存,這樣就可以根據數據之間的關係使用相應的子查詢,從而實現複雜的查詢。

子查詢是在SQL語句內的另外一條SELECT語句,也被稱爲內查詢或是內SELECT語句。在SELECT、INSERT、UPDATE或DELETE命令中允許是一個表達式的地方都可以包含子查詢,子查詢甚至可以包含在另外一個子查詢中。

select id, uname, age from users where uname in (select ename from emp where ename = 'jack')
//等價於
select id, uname, age from users a, emp b where a.uname = b.ename and b.ename = 'jack';

相比多表關聯查詢,子查詢的使用更加靈活、功能更強大,而且更容易理解。但是多表關聯查詢也有它自身的優點,比如,它的查詢效率要高於子查詢。

在執行子查詢操作的語句中,子查詢也稱爲內查詢,包含子查詢的查詢語句也被稱爲外查詢或主查詢。

在一般情況下,外查詢語句檢索一行,子查詢語句需要檢索一遍數據,然後判斷外查詢語句的條件是否滿足。如果條件滿足,則外查詢語句將檢索到的數據行添加到結果集中,如果條件不滿足,則外查詢語句繼續檢索下一行數據,所以子查詢相對多表關聯查詢要慢一些。

另外,在使用子查詢時,還應注意以下規則:

  • 子查詢必須用括號“()”括起來。
  • 子查詢中不能包括ORDER BY子句。
  • 子查詢允許嵌套多層,但不能超過255層。

在Oracle 11g中,通常把子查詢再細化爲單行子查詢、多行子查詢和關聯子查詢3種

1.2.2 單行子查詢
單行子查詢是指返回一行數據的子查詢語句。當在WHERE子句中引用單行子查詢時,可以使用單行比較運算符(=、>、<、>=、<=和< >)。

select id, uname, age from users where age = (select max(age) from emp)

在上面的語句中,如果內層子查詢語句的執行結果爲空值,那麼外層的WHERE子句就始終不會滿足條件,這樣該查詢的結果就必然爲空值,因爲空值無法參與比較運算。

在執行單行子查詢時,要注意子查詢的返回結果必須是一行數據,否則Oracle系統會提示無法執行。另外,子查詢中也不能包含ORDER BY子句,如果非要對數據進行排序的話,那麼只能在外查詢語句中使用ORDER BY子句。

1.2.3 多行子查詢
多行子查詢是指返回多行數據的子查詢語句。當在WHERE子句中使用多行子查詢時,必須使用多行比較符(IN、ANY、ALL)。

(1)使用IN運算符
當在多行子查詢中使用IN運算符時,外查詢會嘗試與子查詢結果中的任何一個結果進行匹配,只要有一個匹配成功,則外查詢返回當前檢索的記錄。

(2)使用ANY運算符
ANY運算符必須與單行操作符結合使用,並且返回行只要匹配子查詢的任何一個結果即可。

(3)使用ALL運算符
ALL運算符必須與單行運算符結合使用,並且返回行必須匹配所有子查詢結果。

select id, uname, age from users where age in (select age from emp);
select id, uname, age from users where age > any(select age from emp);
select id, uname, age from users where age > all(select age from emp);

1.2.4 關聯子查詢
在單行子查詢和多行子查詢中,內查詢和外查詢是分開執行的,也就是說,內查詢的執行與外查詢的執行是沒有關係的,外查詢僅僅是使用內查詢的最終結果。

在一些特殊需求的子查詢中,內查詢的執行需要藉助於外查詢,而外查詢的執行又離不開內查詢的執行,這時,內查詢和外查詢是相互關聯的,這種子查詢就被稱爲關聯子查詢。

select id, uname, age from users a where age > (
	select avg(age) from emp b where a.uname = b.ename)

在執行關聯子查詢的過程中,必須遍歷數據表中的每條記錄,因此如果被遍歷的數據表中有大量數據記錄,則關聯子查詢的執行速度會比較緩慢。

需要補充一點的是,關聯子查詢不但可以作爲SELECT語句的子查詢,也可以作爲INSERT、UPDATE或DELETE語句的關聯子查詢。

二、數據庫操作

2.1 數據庫操作介紹

使用SQL語句操作數據庫,除了查詢操作之外,還包括完成插入、更新和刪除等數據操作。後3種數據操作使用的SQL語言也稱爲數據操縱語言(Data Manipulation Language,DML),它們分別對應INSERT、DELETE和UPDATE三條語句。

在Oracle 11G中,DML除了包括上面提到的3種語句之外,還包括TRUNCATE、CALL、LOCKTABLE和MERGE等語句。

2.2 插入數據(INSERT語句)

2.2.1 插入數據介紹
插入數據就是將數據記錄添加到已經存在的數據表中,Oracle數據庫通過INSERT語句來實現插入數據記錄。該語句既可以實現向數據表中一次插入一條記錄,也可以使用SELECT子句將查詢結果集批量插入數據表。

使用INSERT語句有以下注意事項:

  • 當爲數字列增加數據時,可以直接提供數字值,或者用單引號引住。
  • 當爲字符列或日期列增加數據時,必須用單引號引住。
  • 當增加數據時,數據必須要滿足約束規則,並且必須爲主鍵列和NOT NULL列提供數據。
  • 當增加數據時,數據必須與列的個數和順序保持一致。

2.2.2 單條插入數據
單條插入數據是INSERT語句最基本的用法,其用法格式如下:

INSERT INTO table_name [(column_name1[,column_name2])]
    VALUES(express1[,express2])
  • table_name:表示要插入的表名。
  • column_name1和column_name2:指定表的完全或部分列名稱。如果指定多個列,那麼列之間用逗號分開。
  • express1和express2:表示要插入的值列表。

當使用INSERT語句插入數據時,既可以指定列列表,也可以不指定列列表。如果不指定列列表,那麼在VALUES子句中必須爲每個列提供數據,並且數據順序必須與表列順序完全一致。如果指定列列表,則只需要爲相應列提供數據。

(1)使用列列表增加數據
在INSERT語句的幾種使用方式中,最常用的形式是在INSERT INTO子句中指定添加數據的列,並在VALUES子句中爲各個列提供一個值。

insert into users(id, name, age) values(1, 'Jack', 18);

INSERT INTO子句中指定添加數據的列,既可以是數據表的全部列,也可以是部分列。在指定部分列時,需要注意不許爲空(NOT NULL)的列必須被指定出來,並且在VALUES子句中的對應賦值也不許爲NULL,否則系統顯示“無法將NULL插入”的錯誤信息提示。

在使用INSERT INTO子句指定爲表的部分列添加數據時,爲了避免產生不許爲空值的錯誤,可以使用DESC命令查看數據表中的哪些列不許爲空。對於可以爲空的列,用戶可以不指定其值。
在這裏插入圖片描述

(2)不使用列列表增加數據
在向表的所有列添加數據時,也可以省略INSERT INTO子句後面的列表清單,使用這種方法時,必須根據表中定義的列的順序,爲所有的列提供數據。用戶可以使用DESC命令來查看錶中定義列的順序。

insert into users values(1, 'JACK', 18, '男');

(3)使用特定格式插入日期值
當增加日期數據時,默認情況下日期值必須匹配於日期格式和日期語言;否則在插入數據時會增加錯誤信息。如果希望使用習慣方式插入日期數據,那麼必須使用TO_DATE函數進行轉換。

insert into users(id, name, age, birth) values(1, 'JACK', 18, to_date('2019-12-01','yyyy-mm-dd'));

(4)使用DEFAULT提供數據
從Oracle Database 9i開始,當增加數據時,可以使用DEFAULT提供數值。當指定DEFAULT時,如果列存在默認值,則會使用其默認值,如果列不存在默認值,則自動使用NULL。

insert into users(id, name, age, birth) values(1, 'JACK', 18, default);

(5)使用替代變量插入數據
如果經常需要給某表插入數據,那麼爲了避免輸入錯誤,可以將INSERT語句放到SQL腳本,並使用替代變量爲表插入數據。如果經常需要爲emp表插入數據,那麼爲了避免輸入錯誤,可以使用SQL腳本插入數據。

2.2.3 批量插入數據
INSERT語句還有一種強大的用法,就是可以一次向表中添加一組數據,也就是批量插入數據。用戶可以使用SELECT語句替換掉原來的VALUES子句,這樣由SELECT語句提供添加的數值。

其語法格式如下:

INSERT INTO table_name [(column_name1[,column_name2])] selectSubquery
  • table_name:表示要插入的表名稱。
  • column_name1和column_name2:表示指定的列名。
  • selectSubquery:任何合法的SELECT語句,其所選列的個數和類型要與語句中的column對應。
insert into users1 
	select * from user2
 	where users2.age > 19;

需要注意的是,在使用這種組合語句實現批量插入數據時,INSERT INTO子句指定的列名可以與SELECT子句指定的列名不同,但它們之間的數據類型必須是兼容的,即SELECT語句返回的數據必須滿足INSERT INTO表中列的約束。

2.3 更新數據(UPDATE語句)

2.3.1 更新數據介紹
如果表中的數據不正確或不符合需求,那麼就需要對其進行修改。Oracle數據庫通過UPDATE語句來實現修改現有的數據記錄。 在更新數據時,更新的列數可以由用戶自己指定,列與列之間用逗號(,)分隔;更新的條數可以通過WHERE子句來加以限制,使用WHERE子句時,系統只更新符合WHERE條件的記錄信息。

UPDATE語句的語法格式如下:

UPDATE table_name
   SET {(column_name1 = express1),(column_name2 = express2...)} 
 [WHERE condition]
或者
UPDATE table_name
   SET (column_name1, column_name2…) = (selectSubquery)
 [WHERE condition]
  • table_name:表示要修改的表名。
  • column_name1和column_name2:表示指定要更新的列名。
  • selectSubquery:任何合法的SELECT語句,其所選列的個數和類型要與語句中的column對應。
  • condition:篩選條件表達式,只有符合篩選條件的記錄才被更新。

使用UPDATE語句有以下注意事項:

  • 當更新數字列時,可以直接提供數字值,或者用單引號引住。
  • 當更新字符列或日期列時,必須用單引號引住。
  • 當更新數據時,數據必須要滿足約束規則。
  • 當更新數據時,數據必須與列的數據類型匹配。

2.3.2 更新單列數據
當更新單列數據時,set子句後只需要提供一個列。

update users set age = 18 where name = 'jack';

2.3.3 更新多列數據
當使用update語句修改錶行數據時,既可以修改一列,也可以修改多列。當修改多列時,列之間用逗號分開。

update users set age = 18 where age = '20';

2.3.4 更新日期列數據
當更新日期列數據時,數據格式要與日期格式和日期語言匹配;否則會顯示錯誤信息。如果希望使用習慣方式指定日期值,那麼可以使用TO_DATE函數進行轉換。

update users set birth = to_date('2019-12-01','yyyy/mm/dd') where age = '20';

2.3.5 使用DEFAULT選項更新數據
當更新數據時,可以使用DEFAULT選項提供數據。使用此方式時,如果列存在默認值,則會使用默認值更新數據;如果列不存在默認值,則使用NULL。

update users set birth = default where age = '20';

2.3.6 使用子查詢更新數據
另外,同INSERT語句一樣,UPDATE語句也可以與SELECT語句組合使用來達到更新數據的目的。

update users set age = (select avg(age) from user2) where age = '20';

需要注意的是,在將UPDATE語句與SELECT語句組合使用時,必須保證SELECT語句返回單一的值,否則會出現錯誤提示,導致更新數據失敗。

2.4 刪除數據(DELETE語句和TRUNCATE語句)

2.4.1 刪除數據介紹
Oracle系統提供了向數據庫添加記錄的功能,同時也提供了從數據庫刪除記錄的功能。從數據庫中刪除記錄可以使用DELETE語句和TRUNCATE語句,但這兩種語句還是有很大區別的

2.4.2 DELETE語句
DELETE語句用來刪除數據庫中的所有記錄和指定範圍的記錄,若要刪除指定範圍的記錄,同UPDATE語句一樣,要通過WHERE子句進行限制.

其語法格式如下:

DELETE FROM table_name [WHERE condition]
  • table_name:表示要刪除記錄的表名。
  • condition:篩選條件表達式,是個可選項,當該篩選條件存在時,只有符合篩選條件的記錄才被刪除掉。

刪除滿足條件的數據:當使用DELETE語句刪除數據時,通過指定WHERE子句可以刪除滿足條件的數據。
刪除表的所有數據:當使用DELETE刪除表的數據時,如果不指定WHERE子句,那麼會刪除表的所有數據。

delete from users where age > 18

2.4.3 TRUNCATE語句
如果用戶確定要刪除表中的所有記錄,那麼除了可以使用DELETE語句之外,還可以使用TRUNCATE語句,而且Oracle本身也建議使用TRUNCATE語句。

使用TRUNCATE語句刪除表中的所有記錄要比DELETE語句快得多。這是因爲使用TRUNCATE語句刪除數據時,它不會產生回滾記錄。當然,執行了TRUNCATE語句的操作也就無法使用ROLLBACK語句撤銷。

truncate table users;

在TRUNCATE語句中還可以使用REUSE STORAGE關鍵字或DROP STORAGE關鍵字,前者表示刪除記錄後仍然保存記錄所佔用的空間,後者表示刪除記錄後立即回收記錄佔用的空間。默認情況下TRUNCATE語句使用DROP STORAGE關鍵字。

參考文獻:

  1. Oracle 11g從入門到精通 第二版,明日科技 著,清華大學出版社有限公司
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章