最近復習了一下SQL語句,用把SQL各種基本的用法小小地總結了下
一、表的創建
1、創建表
格式:
1 CREATE TABLE 表名 2 (列名 數據類型(寬度)[DEFAULT 表達式][COLUMN CONSTRAINT], 3 ... 4 [TABLE CONSTRAINT]
5 [TABLE_PARTITION_CLAUSE]
6 );
例子:
1 CREATE TABLE book( 2 book_number VARCHAR2(5), 3 book_name VARCHAR2(30), 4 pub_com_number VARCHAR2(2), 5 author VARCHAR2(10), 6 publishing_date DATE, 7 volume INT(3), 8 price FLOAT9 );
通過上面的SQL語句,我們就在數據庫中創建了一個簡單的數據表,這里我們使用mysql來進行演示
2、通過現有的表創建表
CREATE TABLE tablename(column_name1,column_name2) AS SQL 查詢語句
Eg:
(1)完全復制表結構和數據
create table book1 as select * from book;
PS.關於查看數據表結構,有兩種方式:
a.DESCRIBE(簡寫DESC)`table_name`;
b.SHOW FULL COLUMNS FROM `table_name`;
可以看出,兩者的區別使用SHOW FULL COLUMNS還會顯示數據表的一些鍵還有字段注釋。
說到這里,順帶說說在win下面如何使用mysql的dos終端:
a.進入mysql.exe所在目錄
b.執行mysql.exe -u用戶名 -p密碼
c.選擇你要進行操作的數據庫,語法為:use 數據庫名 ,如果你不知道都有哪些數據庫,可以使用show databases;來查看
d.查看數據庫中的數據表,使用show tables;
(2)只復制數據表中的某些字段建表
create table copy_table_name as select `column_name1`,`column_name2`,..., from table;
如果你想在復制的時候對這些字段進行重命名,可以這樣做
create table copy_table_name(`new_column_name1`,`new_column_name2`,..) as select `column_name1`,`column_name2`,... From table;
不過這種語法在MySQL里不支持,在Oracle中支持
(2)刪除已創建的數據表
DROP TABLE table_name;
二、表的結構修改
1、為數據表增加新列,即增加一個字段
ALTER TABLE `table_name`
ADD `column_name` dataType(maxLength) [DEFAULT `默認值`][字段約束];
(中括號意為可選)
2、對數據表某一列即某個字段進行修改
語法跟增加差不多只是把ADD關鍵字改成MODIFY
ALTER TABLE `table_name`
MODIFY `column_name` dataType(maxLength) [DEFAULT `默認值`][字段約束];
注意:字段名無法被修改!!!如果要改變列名,只能先刪除該列,然后重新增加。其他部分 都可以進行修改,如果沒有給出新的定義,表示該部分屬性不變。
修改列定義還有以下一些特點:
(1) 列的寬度可以增加或減小,在表的列沒有數據或數據為NULL時才能減小寬度。
(2) 在表的列沒有數據或數據為NULL時才能改變數據類型,CHAR和VARCHAR2之間可以隨意轉換。
(3) 只有當列的值非空時,才能增加約束條件NOT NULL。
(4) 修改列的默認值,只影響以后插入的數據。
3、刪除數據表的一列即一個字段
ALTER TABLE `table_name` DROP COLUMN `column_name`;
三、表的數據更新
1、插入
INSERT INTO `table_name`(`column_name1`,`column_name2`,..) VALUES (val1,val2,..);
遇到字段很多的表,如果要插入全部字段的值,一個一個字段名聲明很麻煩,可以直接省去這一步
INSERT INTO `table_name` values (val1,val2,...)
有的時候我們想從一個表中復制數據數據過來,可以嗎?沒問題
INSERT INTO `table_name` (`column_name1`,`column_name2`,..) SELECT
(`column_name1`,`column_name2`,..) FROM `other_table_name`;
2、修改數據
使用UPDATE關鍵字對數據進行修改,不過往往需要用WHERE子句加限制條件,不然會修改所有的行。
UPDATE `table_name` SET `column1` = val1,`column2` = val2,... WHERE condition;
特殊用法:通過其他查詢結果更新數據
UPDATE 表名 SET(字段名1, 字段名2, ...)=SELECT (字段名1, 字段名2, ...) FROM 另外的表名WHERE條件;
3、刪除數據
刪除數據一樣非常敏感,在執行之前一定要檢查是否有where條件,否則會刪除數據表中的全部數據。
DELETE FROM `table_name` WHERE condition;
如果我們想清空數據表中的所有數據,可以用:
DRUNCATE `table_name`
這里你可能會自然而然想到,我用delete from `table_name`不也可以達到相同的效果么?確實,但其實兩者還是有一些區別的:
兩者均是刪除數據表中全部數據,但是使用truncate的速度更快,且使用的系統和事務日志資源少,delete語句每刪除一行,都要在事務日志中為所刪除的每行記錄一項;而truncate通過釋放存儲表數據所用的數據頁來刪除數據,並只在事務日志中記錄頁的釋放。Truncate刪除內容釋放空間,delete刪除內容不釋放空間。
4、查詢數據
(1)指定索引字段
SELECT 字段名列表 FROM 表名 WHRER 條件
(2)顯示計算列
查詢語句中可以有算術表達式,包括+、-、*
(3)使用別名
(4)字符串拼接
在oracle中使用“||”,在MySQL中則使用concat()函數
要達到相同的效果上圖sql語句在oracle中的用法應該為:
select ‘書名為:’||`book_name`||’ 價格為:’||`price` as `descript` from book2;
(5)消除重復
如果在顯示結果中存在重復行,可以使用關鍵字DISTINCT消除重復顯示
SELECT DISTINCE 字段名 FROM 表名
加入我們對多個字段去重,那么顯示的結果是多個字段的組合不重復結果
(6)排序
使用ORDER BY關鍵字,有升序降序之分,ASC表示升序,DESC表示降序
升序:
SELECT * FROM表名 ORDER BY `字段名` ASC;
降序:
SELECT * FROM表名 ORDER BY `字段名` DESC;
多列排序:
SELECT * FROM表名 ORDER BY `字段名1`,`字段名2`,... ;
多列排序中,前面字段名的排序優先級高,即后面字段的排序是在前面字段排序的結果的基礎上再進行排序的。
PS.多列排序中的字段名包括對字段的重命名和自定義字段
5、條件查詢
(1)簡單條件查詢
要對顯示的行進行限定,可在FROM從句后使用WHERE從句,在WHERE從句中給出限定的條件,因為限定條件是一個表達式,所以稱為條件表達式。條件表達式中可以包含比較運算,表達式的值為真的記錄將被顯示。
PS.只有數值和日期型的字段才能進行大小的比較,字符型字段只能比較是否相等
(2)符合條件查詢
可以用邏輯運算符構成復合的條件查詢,即把兩個或多個條件,用邏輯運算符連接成一個條件。有3個邏輯運算符,如下圖所示:
運算的優先順序是NOT,AND,OR。如果要改變優先順序,可以使用括號。
(3)特殊運算表示法
A.between
對於數值型或日期型數據,表示范圍時可用以下運算表示方法
[NOT] BETWEEN ... AND ...
B.in
顯示值滿足特定集合的結果
[NOT] IN ...
C.like
使用like操作符可完成按通配符查找字符串,適用於模糊查詢
[NOT] LIKE 匹配模式
匹配模式中除了可以包含固定的字符之外,還可以包含以下的通配符:
%:代表0個或多個任意字符。
_ :代表一個任意字符。
Eg:
查找開頭為“我”的書籍信息
如果想查找書名第二個字符為“+”的書籍
D.判斷某字段是否為空值
[NOT] NULL
四、表的高級查詢
1、多表聯合查詢
通過連接可以建立多表查詢,多表查詢的數據可以來自多個表,但是表之間必須有適當的連接條件。為了從多張表中查詢,必須識別連接多張表的公共列。一般是在WHERE子句中用比較運算符指明連接的條件。
忘記說明表的連接條件是常見的一種錯誤,這時查詢將會產生表連接的笛卡爾積(即一個表中的每條記錄與另一個表中的每條記錄作連接產生的結果)。一般N個表進行連接,需要至少N-1個連接條件,才能夠正確連接。兩個表連接是最常見的情況,只需要說明一個連接條件。
兩個以上的表也可以進行連接,在這里不做專門介紹。
兩個表的連接有四種連接方式:
- 相等連接。
- 不等連接。
- 外連接。
- 自連接。
(1)相等連接
通過兩個表具有相同意義的列,可以建立相等連接條件。使用相等連接進行兩個表的查詢時,只有連接列上在兩個表中都出現且值相等的行才會出現在查詢結果中。
舉個例子:
我們假設有一個學生表student和一個老師表teacher。student表里面有學生的信息,其中一個關鍵字段是老師的t_id,對應teacher表的id,這里我們簡化一下老師和學生的關系是一對一的,即一個老師只能執教一個學生,一個學生只能被一個老師執教
我們要求查詢學生和老師的對應關系和學生id,這時可以聯表相等查詢:select s.id,s.name,t.name from student s,teacher t where s.t_id = t.id;
(2)不等連接
跟上面類似
(3)外連接
使用上面的相等或不等連接會產生一個問題,就是我們只能看到有上老師的課的學生的信息而不能看到沒有選老師的課的學生的信息,如果我們想在和老師的表進行連接時還想顯示全部學生的信息怎么辦?外連接可以達到這個目的!
外連接不僅顯示滿足相等連接條件的記錄,還顯示不滿足條件連接的行。
外連接的種類有三種,分別為:
左外連接:左邊的表不加限制
右外連接:右邊的表不加限制
全外連接:左右兩表都不加限制
這里我們用老師和學生的關系來說明這三種外連接:
如下圖所示,學生表里有個t_id表示被執教的老師id,老師表里有個s_id表示老師執教的學生id,老師和學生是一對一的關系。
我們初始化數據,學生表里陳六沒有被任何一名老師執教,老師kalay也沒有執教任何一名學生。
當我們想查詢被執教的學生和對應老師信息時,使用如下查詢:
那假如同時我們還想顯示其他沒有被執教的學生的信息呢?使用左連接left join
如果我們想顯示的是全部老師執教情況的信息呢?使用右連接right join
如果我們想顯示出了正常執教的老師和正常被執教的學生之外,還想顯示沒有被執教的學生和沒有執教的老師呢?用全連接full join,但是在mysql中是不支持full join的,那怎么達到full join的效果呢?仔細觀察上面左右連接,我們發現左右連接的合集就是全連接的集合了,這里我們可以使用union去重達到全連接full join的效果了。
(4)自連接
自連接就是一個表,同本身進行連接。對於自連接可以想像存在兩個相同的表(表和表的副本),可以通過不同的別名區別兩個相同的表
Eg:
經理和雇員都在雇員表中,每個雇員有一個對應管理的經理,要查詢雇員和對應經理的名稱。這種查詢在無限分類表中也很常見。
假設雇員表的主鍵是id,雇員名稱是name,經理id是man_id,則上述查詢要求對應sql應該為
SELECT work.name,manager.name FROM `employ` worker,`employee` manager WHERE work.man_id = manager.id;
2、統計查詢
通常需要對數據進行統計,匯總出數據庫的統計信息。比如,可能想了解公司的總人數和總工資額,或各個部門的人數和工資額,這個功能可以由統計查詢完成。
數據庫中提供了一些函數來完成統計工作,這些函數稱為組函數,組函數不同於前面介紹和使用的函數(單行函數)。組函數可以對分組的數據進行求和、求平均值等運算。組函數只能應用於SELECT子句、HAVING子句或ORDER BY子句中。組函數也可以稱為統計函數。
3、子查詢
很多情況下,我們需要做這樣的操作,把一個查詢的結果作為另一個查詢的一部分,第一個查詢可以作為第二個查詢的一部分出現在第二個查詢的條件中,這樣的查詢叫做子查詢。
子查詢一般出現在SELECT語句的WHERE子句中,Oracle也支持在FROM或HAVING子句中出現子查詢。子查詢比主查詢先執行,結果作為主查詢的條件,在書寫上要用圓括號擴起來,並放在比較運算符的右側。子查詢可以嵌套使用,最里面的查詢最先執行。子查詢可以在SELECT、INSERT、UPDATE、DELETE等語句中使用。
這里已雇員和工資的關系為例,假設有一個雇員表emp,每一行代表一名雇員的信息,有ename、sal、empno、job、deptno字段分別代表雇員名、雇員工資、雇員號、工作崗位和部門。
(1)單行子查詢
如果子查詢只返回一行結果,我們稱之為單行子查詢
例子: 查詢一個比SCOTT工資高的雇員名字和工資
分析:對SCOTT工資的查詢為子查詢,只有先查出這個,才能差距SCOTT的工資查到我們想要查詢的結果
SQL語句:SELECT ename,sal FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename == 'SCOTT');
(2)多行子查詢
如果子查詢返回多行結果,稱之為多行子查詢。多行子查詢經常使用不用的比較運算符,它們是IN、ANY和ALL
例子:查詢工資低於任何一個“CLERK”的工資的雇員信息
分析:有任何的關鍵字,故使用ANY比較運算符
SQL語句:SELECT * FROM emp WHERE sal < ANY(SELECT sal FROM emp WHERE job = 'CLERK') AND job != 'CLERK';
例子:查詢工資比所有的“SALESMAN”都高的雇員的編號、名字和工資
分析:有所有關鍵字,使用ALL比較運算符
SQL語句:SELECT empno,ename,sal FROM emp WHERE sal > ALL(SELECT sal FROM emp WHERE job = 'SALESMAN');
例子:查詢部門20中職務同部門10的雇員一樣的雇員信息
分析:有在什么中的范圍關鍵字,用IN比較運算符
SQL語句:SELECT * FROM emp WHERE job in (SELECT job FROM emp WHERE deptno = 10) AND deptno = 20;
(3)多列子查詢
如果子查詢返回多列,則對應的比較條件中也應該出現多列,這種查詢成為多列子查詢。
例子:查詢職務和部門與SCOTT相同的雇員的信息
SQL語句:SELECT * FROM emp WHERE (job,deptno) = (SELECT job,deptno FROM emp WHERE ename = 'SCOTT');
4、集合運算
多個查詢語句的結果可以做集合運算,結果集的字段類型、數量和順序應該一樣。
並集
差集
MySQL不支持MINUS
要達到類似的效果,可使用IN、NOT IN,也可以配合使用UNION ALL來實現,不過只建議數據量比較小的時候使用,否則效率比較低
使用union all實現差集
使用not in實現交集
交集
使用union all實現交集
使用in實現交集