《SQL必知必會》閱讀筆記
【自言自語】對於資料庫sql語言,之前都是用的時候再查,沒有系統的瞭解,用了一天半把這個書看完了,所以需要總結一下,不過,我沒有寫遊標、儲存過程這些,因為我覺得書中講的過淺了。等下一本書看完,或許有更好的理解。到時候,再寫關於那幾個方面的我覺得是不錯的。這段時間抓緊時間啃書啊,書越借越多。
SQL和Java、C不一樣,他只有很少的詞。他不是某個特定資料庫提供商專有的語言。幾乎所有重要的DBMS都支援SQL,但是有些細節地方還是要去看該DBMS的詳細文件。
資料庫增刪改查操作
一、建立資料庫
CREATE DATABASE test;
二、檢視資料庫
SHOW DATABASES;
- 檢視當前資料庫
SELECT DATABASE();
SHOW TABLES;
檢視所有表操作也可以顯示出資料庫名稱
三、切換指定資料庫
USE test;
四、建立表
CREATE TABLE client( id INT, age INT, name VARCHAR(20), gender VARCHAR(1) );
五、查看錶資料
DESC client;
六、增刪改查
1. 增
INSERT INTO client VALUES(1,20,'zhangsan','female');
插入所有欄位INSERT INTO client(id,name) VALUES(2,'zhansgan');
插入部分欄位- 省略的列需要被定義為允許
NULL
- 在表中給出預設值。表示如果不給出值,將使用預設值。
- 省略的列需要被定義為允許
INSERT INTO client(id,name) SELECT id,name from oldClient;
- 插入檢索出的語句,它可以用一條INSERT插入多行,不管SELECT返回多少行,都將被INSERT插入。
Create TABLE CustCopy AS SELECT * from Customers;
- 建立一個新表,將Customers表的整體內容複製到新表中。
2. 改
UPDATE client SET gender='female';
修改所有資料(使用較少),修改範圍較大。UPDATE client SET gender='mael' WHERE id=1;
UPDATE client SET gender='male' , age=30 WHERE id=2;
修改多個欄位,中間用英文逗號分隔。
3. 刪
DELETE FROM client;
刪除該表的所有資料,可以帶條件刪除。- 若執行該指令,只會刪除table的所有資料,但是不能刪除表的約束。例如自增長的繼續增長。
- 使用該指令,刪除的資料可以回滾。
DELETE FROM client WHERE id=2;
刪除帶條件的資料。TRUNCATE TABLE client;
全表刪除,不能帶條件刪除。
4. 查詢資料(基於一張表)
查詢出來的順序未必是按照 存放的順序。
4.1 查詢所有列
SELECT * FROM client
查詢所有列 *代表所有
``
4.2 查詢制定列
SELECT id,name,FROM client;
SELECT id, AS '編號',name AS '姓名' FROM client AS 's';
查詢時指定別名(as),再多表查詢時,經常使用!
4.3 查詢時新增常量列
SELECT id,name ,'常量列' AS ‘常數列的表頭’ FROM cilent;
4.4 查詢是合併列
SELECT id,name (a2+a3) AS '新專案' FROM client;
只能合併數值型別
4.5 查詢時去除重複記錄
SELECT DISTINCT gender FROM client;
SELECT DISTINCT(gender) FROM client;
**PS:**不能部分使用DISTINCT
:
- 該關鍵字作用於所有的列,不僅僅是跟在其後的那一列。
- 例如你指定
select distinct id,name
,除非指定的兩列完全相同,否則所有的行都會被檢索出來。
4.6 條件查詢
-
邏輯條件 and or
SELECT * FROM client WHERE id=2 AND name='zhangsan';
兩個欄位以上的之間一定會有邏輯關係! -
比較條件 > 、<、 >=、 <=、 ==、 <>或!=(不等於) between and
SELECT * FROM client WHERE 指定項>=70 AND 指定項2<=90;
SELECT * FROM client WHERE 制定項 BETWEEN 70 AND 95
SELECT * FROM client WHERE gender <> 'male';
尋找性別不為男的資料。SELECT * FROM client WHERE age in (16,18)
IN
:Where子句中用來指定要匹配值的清單的關鍵字,功能和OR相當。- IN操作符一般比一組OR操作符執行的更快。
-
判空(null / 空字串) is null /is not null NULL :沒有值 空字串 :有值。
SELECT * FROM client WHERE address IS NULL ;
判斷NULLSELECT * FROM client WHERE address='';
判斷空字串SELECT * FROM client WHERE address IS NULL OR address='';
包括NULL和空字串。SELECT * FROM client WHERE address IS NOT NULL AND address<>'';
-
模糊查詢
只適用於字串型別。
通常使用以下替換標記
%
:表示任意字元出現任意次數(可以是0次)_
:(下劃線)表示一個字元。[]
:指定一個字符集,SELECT * FROM client WHERE name LIKE 'zhang%';
SELECT * FROM client WHERE name LIKE 'zhang_' ;
4.7 聚集函式
常用的聚集函式:sum()
avg()
max()
min()
count()
。
這些函式都很高效,它們返回的結果一般比你在自己的客戶端應用程式中計算要快得多。
AVG()
返回某列的平均值select avg(prod_price) AS avg_price from products;
- 該函式忽略列值為
NULL
的行。
COUNT()
返回某列的行數- 使用
count(*)
對錶中的行數目進行計數。(不忽略NULL
值) - 使用
count(列名)
同樣也是對錶中該列的行數目進行計數。(忽略NULL
值)
- 使用
MAX()
返回某列的最大值- 用於文字資料時,MAX()返回該列排序後的最後一行。
- 忽略值為NULL的行
MIN()
返回某列的最小值- 用於文字資料時,MAX()返回該列排序後的最前面的行。
- 忽略值為NULL的行
SUM()
返回某列值之和- 忽略值為NULL的行
select sum(item_price*quantity) AS total_price from OrderItems where order_num = 20005;
4.8 分頁查詢 (limit 起始行,查詢幾行)
起始行從0開始
select * from client limit 0,2;
4.9 查詢排序(order by
)
4.9.1 按多個列排序
select prod_id,prod_price,prod_name from products order by prod_price,prod_name;
先按照 prod_price
進行排序,然後按照prod_name
進行排序。
4.9.2 按列位置排序
select prod_id,prod_price,prod_name from products order by 2,3;
select清單中指定的是列的相對位置而不是列名。
order by 2.3
表示先按prod_price
排序,再按照prod_name
進行排序。
4.9.3 指定排序方向
**PS:**如果想在多個列上進行降序排序,必須對每一列指定DESC
關鍵字。
asc
:順序,反序。數值:遞增,字母:自然順序。
desc
:反序。
4.11分組查詢(group by)
分組篩選後查詢
七. 資料處理
1. 建立計算欄位
- 拼接欄位(例如:拼接兩個字串)
select province + '('+county+')' AS userAddress from address order by county;
- 執行算術計算
select id,count,price,count*price AS money from OrderItems;
- 算術操作符有四種。
+
、-
、*
、/
。
2. 使用函式處理資料
由於每個DBMS都有自己的特性,所以這裡就不列出每個DBMS的函式。只舉例說明如何運用。
2.1 文字處理函式
UPPER()
將文字轉換成大寫。select vend_name,UPPER(vend_name) AS vend_name_upcase from vendors order by vend_name
RTRIM()
去掉字串右邊的空格。LTRIM()
去掉字串左邊的空格。TRIM()
去掉字串中的空格。
2.2數值處理函式
abs()
返回一個數的絕對值cos()
返回一個角度的餘弦exp()
返回一個數的指數值PI()
返回圓周率
2.3 日期處理函式
Year()
返回日期的年份。(Mysql)
3 分組資料
3.1 建立分組
select vend_id,count(*) as num_prods from products group by vend_id;
Group By
子句可以包含任意數目的列,因而可以對分組進行巢狀。Group By
子句必須出現在Where子句之後,Order By
子句之前。1
3.2 過濾分組
select vend_id,count(*) AS orders from Orders Group By cust_id HAVING count(*) >=2
用Having
來過濾分組,上一句SQL語句的意思是 對小於兩個訂單的分組進行過濾。
where
與having
的區別:
- 前者是在資料分組前進行過濾,後者實在資料分組後進行過濾。
- where排除的行不在這些分組中。
- 使用
HAVING
時應該結合GROUP BY
子句,而WHERE
子句用於標準的行級過濾。
3.3 分組和排序
Group by
和ORDER BY
經常完成相同的工作,但他們非常不同。
- 前者對行進行分組,但輸出可能不是分組的順序;後者對產生的輸出排序。
- 一般在使用
GROUP BY
子句時,應該也給出ORDER BY
子句,這是保證資料正確排序的唯一方法。
select order_num , count(*) AS items from orderItems group by oredr_num having count(*) >=3 order by items,oredr_num;
3.4 SELECT 子句的順序
select(必) .....from.....where ....group by .... having .....order by
4. 子查詢
sql中允許子查詢,即巢狀在其他查詢中的查詢。
在SELECT語句中,子查詢總是從內向外處理。
select cust_id from orders where order_num IN (
select order_num from orderItems where prod_id = 'RGAN01');
在實際的DBMS中,實際上執行了兩個操作。
再比如:
select cust_name,cust_contact from customers where cust_id IN(
select cust_id from Orders where order_num IN(
select order_num from OrderItems where prod_id = '45274'
)
);
上述sql程式碼執行了三個 select子語句。
對於能巢狀的子查詢的數目沒有限制,不過在實際使用時由於效能的限制,不能巢狀太多的子查詢。
PS:
- 作為子查詢的select語句只能查詢單個列。
- 使用子查詢並不總是執行這類資料檢索的最有效的方法。
select cust_name,cust_state,(
select count(*) from orders where orders.cust_id = Customers.cust_id) As orderNUM
) from customers order by cust_name;
order
是一個計算欄位,她是由圓括號中的子查詢建立的。該子查詢對檢索出的每個顧客執行一次。
cuwstomers.cust_id
加.
是全限定列名。
5. 聯結表
關於什麼 是聯結,請上百度搜索,百度比我講的清楚。我只簡單的點一下。
資料儲存在多個表中,有些業務需要將他們聯絡起來,檢索出來。
聯結是一種機制,用來在一條SELECT語句中關聯表,因此稱為聯結。
使用特殊的語法,可以聯結多個表返回一組輸出。
5.1 建立聯結
簡單寫法:
select vend_name,prod_name,prod_price from vendors,Products where
vendors.vend_id = Products.vend_id;
**PS:**在引用的列名會產生歧義時,必須使用完全限定列名。
上邊使用的聯結方式稱為等值聯結,它基於兩個表之間的相等測試,這種聯結也成為內聯結。
另外一種標準寫法:
select vend_name,prod_name,prod_price from vendors INNER JOIN Products
on vendors.vend_id = Products.vend_id;
兩個表之間的關係是以INNER JOIN
指定的部分FROM
子句。在使用這種語法時,聯結條件用特定的ON
子句而不是WHERE
。
至於選用哪種方法就需要看具體的DBMS文件。
5.2 聯結多個表
select prod_name,vend_name,prod_price,quantity from OrderItems,Products,Vendors Where
Products.vend_id = Vendors.vend_id
And OrderItems.prod_id = Products.prod_id
And order_num = 20007;
不要聯結不必要的表,聯結的表越多,效能下降的越厲害。
6 建立高階聯結
6.1 使用表別名
-
使用表別名
from 表名 AS 別名
表別名只在查詢執行中使用,與列別名不一樣,表別名不返回到客戶端。
6.2 使用不同型別的聯結
-
自聯結
通常作為外部語句喲個來替代從相同表中檢索資料的子查詢語句。雖然結果相同,但是使用聯結要比使用子查詢效率高很多。
- 使用子查詢:
select id, name,address from user where address = (select address from user where age = 15);
- 使用自聯結:
select c1.name from user as c1,user as c2 where c1.address = c2.address and c2.age = 15;
- 使用子查詢:
-
自然聯結
- 實際上,我們建立的每個內聯結都是自然聯結。
-
外聯結
有兩種外聯結形式,它們之間的唯一差別是所關聯的表的順序。
- 左外聯結
LEFT OUTER JOIN
包含其所有行的表在左邊 - 右外聯結
RIGHT OUTER JOIN
包含其所有行的表在右邊
- 左外聯結
八、使用檢視
1. 檢視是什麼?
檢視是虛擬的表。與包含資料的表不一樣,檢視只包含使用時動態檢索資料的查詢。
他不包含任何列和資料,包含的只是一個查詢。
2. 檢視有什麼作用?
- 簡化複雜的SQL操作。在編寫查詢業務時,直接重用,不需要知道實現的細節。
- 保護資料(可以授權使用者訪問表的特定部分的許可權,而不是整個表的訪問許可權)
- 更改資料格式和表示。
3. 如何建立檢視?
那先說一下 檢視的規則和限制。(詳細的還是要根據所使用的DBMS來決定)
- 與表一樣,檢視必須唯一命名。
- 建立檢視,必須有足夠的訪問許可權
建立檢視:
CREATE VIEW ProductCustomers AS Select cust_name,cust_contact,prod_id from customers,Orders,OrderItems where customers.cust_id = Orders.cust_id and OrderItems.order_num = Orders.order_num;
這個 叫ProductCustomers
的檢視,他聯結了三個表,返回已訂購了任意產品的所有顧客的列表。
比如,我們檢索訂購了產品id為0001
的紀梵希
的顧客。
select cust_name,cust_contact from ProductCustomers where prod_id = '0001';
實際執行上邊的sql語句,檢視中的select會先執行。
用檢視重更新格式化檢索出的資料
create view viewTest AS select RTRIM(province) + '('+RTRIM(county)+')' AS address from User;
該試圖將使用者的省份和國籍進行格式化輸出。
End
SQL基本的會用之後,學習原理就相對來說簡單,更有針對性。