官术网_书友最值得收藏!

4.2 使用SELECT語句

用戶對表或視圖的操作是通過SQL語句來實現的,SQL語句是一種標準的結構化查詢語言。在眾多的SQL語句中,使用頻率最高的是SELECT語句,該語句主要用于檢索數據。雖然在前面已經使用了一些SELECT語句,但是這些使用是零散的、不完整的。因此,在這里將對SELECT語句進行系統的、完整的介紹。

4.2.1 檢索單表數據

檢索單表數據是指從單個表中檢索數據,檢索的結果都來源于同一個表中,檢索單表數據是檢索數據最基礎的操作。

在檢索數據的過程中,既可以檢索所有的列,也可以檢索部分列。在檢索數據時,數據將按照SELECT子句后面指定列的順序顯示。如果使用星號“*”,則表示檢索所有的列,這時數據將按照定義表時指定列的順序顯示數據。

在下面的示例,將檢索EMP表中的所有列和指定列。

① 以SCOTT/TIGER身份連接數據庫。

      SQL> sconnect scott/tiger
      已連接。

提示:

Oracle 12c中,如果在安裝過程中安裝了PDB選項,在創建或使用已創建的用戶名或角色時,需要在用戶名和角色前面添加C##符號。

② 使用SELECT語句檢索EMP表中的所有數據。在該檢索中,使用星號代表所有的列名稱。

③ 使用SELECT語句檢索ENAME列名。注意,在該檢索中,檢索列的順序與列的定義順序是不同的。

在Oracle系統中,有一個標識行中唯一數據的行標識符,行標識符的名稱為ROWID。行標識符ROWID是Oracle數據庫內部使用的數據,其長度為18個數字,包含了該行數據在Oracle數據庫中的物理地址。雖然使用DESCRIBE命令無法查看到ROWID的存在,但是可以在SELECT語句中檢索該列。由于該列并不是在表中定義的列,所以該列也稱為“偽列”。

例如,下面的語句檢索EMP表中的ROWID、EMPNO和ENAME列等數據。

在使用SELECT語句檢索表中的數據時,還可以執行加、減、乘和除運算。另外,在SELECT語句中不僅可以執行單獨的數學運算,還可以執行單獨的日期運算,以及執行與列名關聯的運算。

在執行運算時,經常使用系統提供的DUAL表,DUAL表的結構和數據如下:

DUAL表只包含了一列一行數據,列名為DUMMY(中文含義為啞巴、樣品等),數據類型為VARCHAR2(1)。一行數據為X。該表本身的結構和數據并不重要,但是基于該表可以執行一些基于表的運算。

實際上,為了使結果更好理解,用戶經常會為這些列指定別名。另外,在定義表時,為了簡單起見,列名經常是一些縮寫形式,閱讀這樣的列名感覺上有些困難。因此,為列名指定一個描述性的別名,可以使閱讀檢索結果更加方便。

例如,下面的示例分別為EMP表的各個列指定了中文別名。

在為列指定別名時,關鍵字AS是可選的。例如,下面的語句就省略了關鍵字AS。

    SQL> select ename  "姓名",job  "職位",hiredate  "工作日期",sal  "薪金"
      2  from emp;

在檢索數據時,有時會需要將檢索出來的數據合并起來,以滿足實際需求。例如,在HR用戶模式中,職工的姓名是分別存儲在FIRST_NAME和LAST_NAME列中的。如果希望以“姓名”的完整方式顯示這些數據,就可以使用連接運算符“||”將兩個列連接在一起。通常為提高這種連接運算的可讀性,在連接兩個列后為其指定一個別名。

例如,下面以HR身份連接數據庫,并查詢其中的職工信息表。

在執行字符連接運算時,應該根據需要在兩個字符表達式之間插入一個分隔符,以防止將這兩個字符表達式完全連接在一起,影響檢索結果的可讀性。

在檢索數據時,還有一個點需要注意,表中的空值既不表示空字符串,也不表示數字0,而是表示沒有值,是一個未知值。只有在允許為空的列中才會出現空值。在Oracle中,可以使用NVL( )函數為空值提供一個指定的顯示值,NVL( )函數的使用方法如下:

     nvl(column_name,displayed_message)

其中,如果COLUMN_NAME列為空值,那么就在空值相應的位置上顯示DISPLAYED_ MESSAGE指定的字符。例如:

在SELECT語句中,還可以使用關鍵字DISTINCT,限制在檢索結果中顯示那些不重復的數據。該關鍵字用在SELECT子句中列的列表前面。例如,下面的語句使用DISTINCT關鍵字檢索EMP表中所有職工的職務種類。

    SQL> select distinct job
      2  from emp;

4.2.2 過濾數據

在SELECT語句中可以使用WHERE子句過濾數據,只檢索那些滿足過濾條件的數據。當表中的數據非常多時,這種過濾操作是非常有意義的。通過過濾數據,可以從大量的數據中獲取自己所需要的數據。

1. 比較運算符

在WHERE子句中可以使用比較運算符實現過濾數據,這樣只有滿足比較條件的數據行才會被檢索出來,不滿足比較條件的數據行則不會被檢索出來。可以在WHERE子句中使用的比較運算符如下表所示。

當使用字符串和日期數據進行比較時,應注意要符合下面的規則。

※ 字符串和日期必須使用單引號標識。

※ 字符串數據是區分大小寫的。

※ 日期數據的格式是敏感的,默認的日期格式是DD-MON-YY。

在下面的示例,將練習如何使用比較運算符過濾數據。

① 以SCOTT身份連接數據庫。

② 使用SELECT語句檢索EMP表,要求工作編號為7521。

③ 使用SELECT語句檢索EMP表,要求職位為CLERK、ANALYST中的任何一個,這時可以使用ANY比較運算符。

2. SQL運算符

使用SQL運算符可以基于字符串的模式匹配、值的列表、值的范圍和是否空值等情況來過濾數據。在Oracle中,可以使用的SQL運算符如下表所示。

在上表中的SQL運算符也可以與NOT運算符取反處理。例如,NO LIKE、NOT LIKE、NOT BETWEEN和IS NOT NULL等。如果LIKE為真,則NOT LIKE為假。

可以在WHERE子句中使用LIKE運算符指定將要匹配的字符串模式。在這種模式中,下畫線“_”代表任意一個字符,百分號“%”代表任意數量字符。例如,‘A%’表示以字母A開頭的任意長度的字符串,‘DB_’表示3個字符長且兩個字符是DB的字符串。

例如,下面的示例使用LIKE運算符過濾數據,要求顯示職工姓名中第一個字符是S的職工信息。

如果在模式中包含了實際的下畫線或斜杠,則可以使用ESCAPE關鍵字來指定該字符是實際數據,而不是匹配標記。


例如,下面的示例添加了一行包含下畫線“_”的數據,為了顯示新添加的數據,使用EXCAPE關鍵字指定了一個轉義字符“\”,這樣轉義字符后的下畫線就不再表示匹配標記了。

使用IN運算符可以檢索在指定列表中的數據,例如,過濾條件EMPNO IN(7369,7521,7789)表示檢索工作編號是7369、7521或者7789的職工信息。NOT IN正好與IN相反,例如,EMPNO NOT IN(7369,7521,7789)表示檢索工作編號除7369、7521或者7789之外的職工信息。但是,如果在NOT IN條件中包括了NULL值,那么NOT IN總是返回一個空值。

使用BETWEEN運算符可以在指定范圍內搜索數據。例如,如果希望檢索薪金為1000到2000之間的職工信息,那么可以使用BETWEEN運算符。需要注意的是,BETWEEN運算符僅適用于那些可以指定范圍的數字數據。

例如,使用BETWEEN運算符檢索指定薪金范圍內的職工信息。

    SQL> select empno,ename,job,sal
      2  from emp
      3  where sal between 1500 and 2000;

3. 邏輯運算符

前面介紹的過濾條件都是單一的條件,如果希望寫出復雜的過濾條件,那么,必須使用邏輯運算符,以便把簡單的條件組合起來。在Oracle系統中,可以使用的邏輯運算符如下表所示。

實際上,BETWEEN運算符的條件可以寫成使用AND邏輯運算符連接起來的兩個簡單條件。例如,條件SAL BETWEEN 1500 AND 2000等價于SAL>=1500 AND SAL<=2000。

在使用邏輯運算符連接多個簡單條件時,還需要注意運算符的優先級問題。對于邏輯運算符,優先級由高到低的順序為NOT、AND和OR。即先進行NOT取反運算,然后再進行AND與運算,最后再進行OR或運算符。

在復合條件中,優先級越高的運算符將優先執行。如果優先級相同,則按照條件的先后順序執行。如果復合條件中包括了括號,那么括號內的優先級高于括號外的。例如,在下面的示例,將檢索職工所屬部門編號為20,并且職位為MANAGER或SALESMAN的職工信息。

4.2.3 排序數據

在前面介紹的數據檢索技術中,只是把數據庫中的數據直接取出來。這時,結果集中數據的排列順序是由數據的物理存儲順序所決定的。這種存儲順序比較混亂,并且可以不符合用戶的各種業務需求,因此需要對檢索到的結果集進行排序。在SELECT語句中,可以使用ORDER BY子句對檢索的結果集進行排序。

添加ORDER BY子句后SELECT語句的語法規則如下。

      select  column _list
      from  table_name
      where  condition
      order by order_expression [ASC︱DESC],order_expression [ASC︱DESC],…

其中,ORDER_EXPRESSION表示將要排序的列名或由列組成的表達式;關鍵字ASC指定按照升序排列,這也是默認的排列順序,關鍵字DESC指定按照降序排列。

在排序過程中,可以同時對多個列進行排序。如果是按照多個列進行排序,那么列之間的順序非常重要。在這種情況下,系統首先按照第一個列進行排序,如果第一個列相同,則按照第二個列進行排序,以此類推。

在下面的示例,將使用ORDER BY子句對檢索到的數據進行排序。

① 以SCOTT身份連接系統。

② 使用SELECT語句檢索EMP表中的信息,并且按照職工的薪金SAL列和姓名ENAME列進行升序排序。

③ 在ORDER BY子句通過指定列的位置,指定進行排序的列。

提示:

這里使用的位置是根據SELECT子句后面出現的列表達式的順序確定的。

4.2.4 多表檢索

在實際應用中,經常會碰到需要檢索的數據存在于兩個或兩個以上的表中。這時就需要使用SELECT語句執行多表檢索。多表檢索操作比單表檢索復雜得多。為了更好地理解多表檢索操作,需要理解表的別名、笛卡爾積、內連接、外連接、自然連接和交叉連接等概念。

1. 表的別名

在多表查詢時,如果多個表之間存在同名的列,則必須使用表名來限定列引用。例如,在SCOTT模式中,EMP和DEPT表中都存在DEPTNO列,在進行多表檢索時就是根據該列連接兩個表。

然而,隨著查詢變得越來越復雜,語句會由于每次限定列時輸入表名而變得冗長乏味。因此,SQL語言提供了另一種機制—表別名。表的別名是在SELECT語句中為表定義的臨時性名稱,以簡化對表的引用。

下面的示例將使用表別名來實現多表的檢索。

① 以SCOTT身份連接系統。

② 使用SELECT語句檢索EMP和DEPT表,查詢屬于某一個部門的職工信息。在該檢索中,沒有使用表的別名,因此在WHERE子句中需要使用表的全名對列進行限定。

③ 使用SELECT語句查詢EMP和DEPT表,同樣查詢屬于某一個部門的職工信息。只是在該SELECT語句中為每個表指定了別名,并通過不同的列別名引用表。EMP表的別名為E,而DEPT表的別名為D。為表定義別名后,在SELECT語句的任何地方都可以使用E和D引用相應的表。

為更好地理解表別名的工作過程,在這里有必要介紹一下SELECT語句中各子句執行的順序。在SELECT語句的執行順序中,FROM子句是最先執行的,而SELECT子語是最后執行的。這樣一旦在FROM子句中指定了表別名,當限定引用列時,其他所有子句都可以使用表的別名。需要注意的是,一旦為表指定了別名,則必須在整個剩余語句中使用表的別名,并且不再允許使用表原來的名稱,否則,將出現ORA-00904錯誤。

提示:

在多表檢索中,由于需要頻繁地使用表名稱限定指定的列名稱,因此表的別名應該盡可能簡單。大多數表的別名是由一個或兩個字母組成的,但是,表的別名也應該具有描述性,為求與其他表的別名明顯區分。

2. 內連接

內連接是指滿足連接條件的連接操作,也是通常所說的連接操作。也就是說,在內連接的檢索結果中,都是滿足連接條件的數據。因此,內連接的檢索結果就是笛卡爾積中滿足連接條件的子集。

內連接的語法形式如下:

      select column_list
      from table_name1 [inner] join table_name2
      on join_condition;

其中,COLUMN_LIST表示將要檢索的列名列表,通常情況下,這些列名來自兩個不同的表中。TABLE_NAME1和TABLE_NAME2表示將要連接的表名稱。INNER JOIN關鍵字表示內連接,其中INNER關鍵字是可選的。ON JOIN_CONDITION用于指定連接的條件。

例如,下面的示例將通過內連接檢索EMP和DEPT表。

① 以SCOTT身份連接系統。

② 使用SELECT語句檢索EMP和DEPT表。這兩個表之間的連接是內連接,其連接條件是兩個表中的DEPTNO列。

③ 使用SELECT語句檢索EMP和DEPT表。但是,不使用INNER JOIN表示內連接,也不通過ON指定連接條件,而是通過WHERE子句指定連接條件。

    SQL> select e.ename,e.job,e.sal,d.deptno,d.dname
      2  from emp e,dept d
      3  where e.deptno=d.deptno;

3. 外連接

在外連接中,如果某個表中的數據不滿足條件,而又希望出現在檢索結果中,那么,可以使用外連接。外連接的特點是某些不滿足連接條件的數據也可以出現在連接結果中。

根據外連接檢索結果中包含的數據,外連接可以分為左外連接、右外連接和全外連接。左外連接表示在結果中不僅包含了滿足條件的數據,而且還包含了連接左邊的左表;在右邊接中,結果包含了不滿足條件的右表中的數據;如果左表和右表中不滿足連接條件的數據都出現在結果中,那么這種連接是全外連接。

提示:

在連接語句中,JOIN關鍵字左邊的表稱為“左表”,而右邊的表稱為“右表”。

外連接的語法和內連接的語法規則相似,區別在于外連接中用LEFT OUTER JOIN、RIGHT OUTER JOIN或FULL OUTER JOIN關鍵字,而不使用INNER JOIN關鍵字。其中OUTER是可選的。例如,左邊接可以使用LEFT JOIN代替LEFT OUTER JOIN。

理解不同類型外連接之間的區別的最好方法是看各自的查詢結果。在下面的示例,將分別演示內邊接以及各種外連接之間的區別。

① 以SCOTT身份連接系統。

② 使用SELECT語句檢索EMP和DEPT表,在這兩個表之間執行左外連接。由于EMP表位于LEFT JOIN關鍵字的左邊,所以EMP表中的所有數據都將顯示出來。

從查詢結果中可以看出,左邊接的查詢結果中不僅包括內連接的檢索結果,還包括了新添加數據,盡管該行在DEPT表中沒有匹配的行。由于新添加行在DEPT表中沒有匹配的行,所以EMP表中的DEPTNO和DNAME列以NULL值表示。

③ 使用SELECT語句檢索EMP和DEPT表,在這兩個表之間執行右外連接。由于DEPT表位于RIGHT JOIN關鍵字的右邊,所以DEPT表中所有的數據都將顯示出來。

④ 使用SELECT語句檢索EMP和DEPT表,在這兩個表之間執行全外連接。

提示:

在外連接中,用戶需要特別注意兩個表的位置。

4. 自然連接

與內連接的功能相似,在使用自然連接檢索多個表時,Oracle會將第一個表中的那些列與第二個表中具有相同名稱的列進行連接。在自然連接中,用戶不需要明確指定進行連接的列,系統會自動完成這一任務。

下面的SELECT語句將使用自然連接連接EMP和DEPT表。

自然連接的實際應用性較差,因為它需要連接的各個表之間必須具有相同名稱的列。這將會強制設計者將要連接的表設計為具有相同名稱的列,并且不能夠讓表中的其他列具有相同的名稱。假如EMP和DEPT表中都有一個表示地址的ADDRESS列,則在進行自然連接時,Oracle會嘗試使用DEPTNO和ADDRESS列進行連接。

5. 交叉連接

交叉連接實際上就是指沒有連接條件的連接。實際上,這種連接的結果就是笛卡爾積的結果。

交叉連接的語法形式如下。

      select column_list
      from table_name1 cross join table_name2;

在上面的語法中,CROSS JOIN關鍵字表示執行交叉連接。使用交叉連接檢索表時,雖然會得到一個無實際用處的笛卡爾積。但是,可以通過在其中使用WHERE子句,從笛卡爾積中過濾需要的數據。

在下面的示例,將使用交叉連接檢索EMP和DEPT表,并使用WHERE子句從中過濾所需要的數據。

① 以SCOTT身份連接系統。

② 使用SELECT語句檢索EMP和DEPT表。由于這兩個表之間的檢索是交叉連接的,并且沒有限定條件,所以查詢結果是一個笛卡爾積。

③ 使用WHERE子句在笛卡爾積中過濾不必要的數據。

從檢索結果中可以看出,WHERE子句的作用是從笛卡爾積中篩選適合條件的數據。實際上,各種連接方式也是從笛卡爾積中篩選數據。

主站蜘蛛池模板: 屏山县| 永安市| 南郑县| 大荔县| 庆元县| 衡阳县| 福清市| 南开区| 资溪县| 临清市| 察雅县| 榆中县| 隆尧县| 崇明县| 沂南县| 庐江县| 广水市| 萍乡市| 吴江市| 通海县| 临夏市| 盐津县| 邛崃市| 济宁市| 韶关市| 五莲县| 莱阳市| 阿克苏市| 彭州市| 奉贤区| 彭州市| 普洱| 施秉县| 湖州市| 德州市| 台中市| 织金县| 乌拉特后旗| 海南省| 韩城市| 中牟县|