SQL必知必會第4版讀書筆記
SQL必知必會_4
前言
@author 魯偉林
在讀電子版<<SQL必知必會>> 第4版時,做了下筆記。供以後自己或者其他學習者參考。
電子版<<SQL必知必會>>和書中使用的資料庫和表的原始碼,
請參看地址:https://github.com/thinkingfioa/Notes/tree/master/sql/SQL%E5%BF%85%E7%9F%A5%E5%BF%85%E4%BC%9A4
第2課 檢索資料
2.3 檢索多個列
select column1, column2, column3 from tableName;
2.4 檢索所有的列
select * from products;
注:
1. 缺點:使用萬用字元(*),除非確實需要查詢表的每一列,否則可能會降低檢索和應用的效能.
2. 優點:能檢索出表的不明確的列。
2.5 檢索不同的值
select distinct vend_id from products;
注:
1. distinct關鍵字作用於作用於其後的所有的列,不僅僅是其後的一列。
2. 如:select distinct vend_id,prod_price from products;那麼這兩列vend_id, prod_price都同,才會合併。
2.6 限制結果
- select prod_name from products limit 5; 返回結果只有5行。
- select prod_name from products limit 5 offset 5; 返6,7,8,9,10這5行資料。
注:
1. 第一個被檢索的行是第0行,而不是第1行。因此,LIMIT 1 OFFSET 1會檢索第2行,而不是第1行.
2. MySQL和MariaDB支援簡化版的LIMIT 4 OFFSET 3語句,即LIMIT 3,4。
2.7 使用註釋
- 單行註釋: #
- 多行註釋: /*. ... */
第3課 排序檢索資料
使用Select子句的Order by子句,根據需要檢索排序出的資料
3.1 排序資料
使用Order by語句排序Select檢索出來的語句, Order by子句取一個或多個列的名字。
select prodname, prodprice from products order by prod_price;注:Order by子句, 必須是select的最後一條語句。
3.2 按多個列排序
select prodname, prodprice, prodid from products order by prodprice, prod_name;
3.3 按列位置排序
select prodname, prodprice, prod_id from products order by 2, 3;注: 1. order by 後面可以接數字,比如:2代表的是prod_price, 3代表的是prod_id。不推薦使用這種方式。
3.4 指定排序方向
ASC 升序(預設),DESC 降序。
- select prodname, prodprice, prodid from products order by prodprice DESC, prod_name;
- 如果DESC降序,必須對所有需要降序的列都要加上。
第4課 過濾資料
4.2.3 範圍值檢查
- select prodname, prodprice, prodid from products where prodprice between 4 and 10;
4.2.4 空值檢查
- select * from customers where cust_email is NULL; 空判斷過濾資料
- select * from customers where cust_email is not NULL; 非空判斷過濾資料
第5課 高階資料過濾
5.1.3 組合where子句
- OR操作符和AND操作符。
select prod_name, prod_price, vend_id from products where vend_id = '1001' OR vend_id = '1005' and prod_price >= 10;
結果:
prod_name | prod_price | vend_id |
---|---|---|
.5 ton anvil | 5.99 | 1001 |
1 ton anvil | 9.99 | 1001 |
2 ton anvil | 14.99 | 1001 |
JetPack 1000 | 35.00 | 1005 |
JetPack 2000 | 55.00 | 1005 |
分析:
OR操作符和AND操作符優先順序不同。AND操作符的優先順序 > OR操作符的優先順序。所以上面的sql變成了:
select prod_name, prod_price, vend_id from products where vend_id = '1001' OR (vend_id = '1005' and prod_price >= 10 );
5.2 IN操作符
- select prodname, prodprice, vendid from products where vendid in ('1001', '1003') order by prod_price DESC;
IN操作符的優點
- IN操作符一般比一組OR操作符更快
- IN最大的優點是:可以包含其他SELECT語句,能夠動態的建立WHERE子句。
5.3 NOT操作符
Not操作符用作否定其後所跟的任何條件。
- select * from products where Not vendid = 1001 and prodname = 'Safe';
prod_id | vend_id | prod_name | prod_price | prod_desc |
---|---|---|---|---|
SAFE | 1003 | Safe | 50.00 | Safe with combination lock |
注:Not在這裡只能作用與vend_id.
第6課 使用萬用字元進行過濾
6.1.1 百分號(%)萬用字元
在搜尋串中,%表示任何字元出現任意次數。代表搜尋模式中給定位置0個,1個,多個字元。排除匹配NULL的行。
- select prodid, prodname from products where prod_name like 'Jet%';
6.1.2 下劃線(_)萬用字元
在搜尋串中,下劃線(_)只匹配單個字元,而不是多個字元。只能是一個字元。
- select prodid, prodname from products where prod_name like 'JetPack _000';
6.1.3 方括號([])萬用字元
只有微軟的Access和SQL server支援。
6.2 使用萬用字元的技巧
- 要知道,使用萬用字元可能比其他的搜尋耗費更長的時間,對資料庫的壓力更大。
- 不要過度使用萬用字元,在其他操作符能達到效果的情況下,儘量不要使用萬用字元。
- 儘量不要把萬用字元放在搜尋模式的開始處,把萬用字元置於開始處,搜尋起來最慢的。
第7課 建立計算欄位
7.1 計算欄位
計算欄位是執行時在SELECT語句內建立的。不同於資料庫中表的列
7.2 拼接欄位
將表中的列資料,拼接到一起。將值聯結在一起(將一個值附加到另一個值), 構成單個值。如:prodname(prodprice).
拼接的操作符:
1. Access和SQL Server使用+號
2. DB2、Oracle、PostgreSQL、SQLite和Open Office Base使用||
3. MySQL和MariaDB中,必須使用特殊的函式。eg: concat(prod_name, '(', prod_price, ')')
Trim函式
1. RTRIM(String)函式去掉字串右邊的空格。
2. LTRIM(String)函式去掉字串左邊的空格。
3. TRIM(String)函式去掉字串左邊和右邊空格。
As別名。重新為列起一個新的名字。
1. select concat(prod_name, '(', vend_id, ')') as price_info from products;
7.3 執行算術計算
算術運算子:加,減,乘,除
計算商品共賣出多少錢
1. select prod_id, quantity, item_price, quantity * item_price as expanded_price from orderitems where order_num = 20005;
第8課 使用資料處理函式
8.1 函式
SQL中函式,各個DBMS所支援的都不同,如果使用過多的函式,可能會帶來可移植問題。
8.2 使用函式
大部分SQL實現支援以下型別的函式
1. 用於處理文字字串(如刪除,填充值,轉換大小寫等)的文字函式。
2. 用於在數值資料上進行的算術操作(如返回絕對值,進行代數運算)的數值函式。
3. 用於處理日期和時間值,並從這些值中提取特定成分(如返回兩個日期之差,檢查日期有效性)的日期和時間函式。
4. 返回DBMS正使用的特殊資訊(如返回使用者登入資訊)的系統函式。
8.2.1 文字處理函式
常見的文字處理函式
函式 | 說明 |
---|---|
LEFT()(或使用子字串函式) | 返回字串左邊的字元 |
RIGHT()(或使用子字串函式) | 返回字串右邊的字元 |
LOWER()(Access使用LCASE()) | 將字串轉換為小寫 |
UPPER()(Access使用UCASE()) | 將字串轉換為大寫 |
LTRIM() | 去掉字串左邊的空格 |
RTRIM() | 去掉字串右邊的空格 |
TRIM()、去掉字串左邊和右邊的空格 | |
SOUNDEX() | 返回字串的SOUNDEX值(讀音相同) |
LENGTH()(也使用DATALENGTH()或LEN()) | 返回字串長度 |
解釋文字處理函式:SOUNDEX()
SOUNDEX()函式是一種和根據讀音相同來比較的
1. SELECT cust_name, cust_contact FROM Customers WHERE SOUNDEX(cust_contact) = SOUNDEX('Michael Green');
8.2.2 日期和時間處理函式
非常遺憾的是:日期和時間處理函式在SQL實現中差別很大,可移植性非常差。所以,關於具體DBMS支援的日期-時間處理函式,請參閱相應的文件。
8.2.3 數值處理函式
數值處理函式僅處理數值資料,這些函式一般主要用於代數、三角或幾何運算。數值處理函式在SQL差別不大。
函式 | 說明 |
---|---|
ABS() | 返回一個數的絕對值 |
COS() | 返回一個角度的餘弦 |
EXP() | 返回一個數的指數值 |
PI() | 返回圓周率 |
SIN() | 返回一個角度的正弦 |
SQRT() | 返回一個數的平方根 |
TAN() | 返回一個角度的正切 |
第9課 彙總資料
9.1 聚集函式
函式 | 說明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
9.1.1 AVG()函式
AVG函式計算表中列的平均值。AVG()只能用來確定特定數值列的平均值.AVG函式忽略列值為NULL的行。
- select avg(prodprice) as avgprice from products;
9.1.2 COUNT()函式
COUNT函式有兩種實現方式:
1. 使用count(*),對錶中行的數目進行計數。無論是空值(NULL)或非空值。
2. 使用count(columnName)對錶特定列具有值進行計數,忽略NULL值。
3. select count(vend_state) from vendors;語句忽略NULL值。
9.1.3 MAX()函式
MAX()返回指定列中的最大值。
- select max(prodprice) as maxprice from products;
9.1.4 MIN()函式
MIN()的功能正好與MAX()功能相反,它返回指定列的最小值。
9.1.5 SUM()函式
SUM()用來返回指定列值的和(總計)。
- select sum(itemprice) as sumprice from orderitems where order_num = 20005;
- select sum(itemprice*quantity) as totalprice from orderitems where order_num = 20005;
注: 利用標準的算術運算子,所有的聚集函式都可以執行多個列上的計算。
9.2 聚集不同的值
使用關鍵字: DISTINCT關鍵字,過濾相同的值。
- select avg(distinct prodprice) as avgprice from products where vend_id = 'DLL01';
9.3 組合聚集函式
select 語句可以根據需要包含多個聚集函式。
- select count(*) as numitems, min(prodprice) as minprice, max(prodprice) as maxprice, sum(prodprice) as sum_price from products;
第10課 分組資料
將資料分組,使用Group by子句和Having子句。
10.1 資料分組
目前為止的所有計算都是在表的所有資料或匹配特定的WHERE子句的資料上進行的。沒有對應的分組概念。
- select count(*) as numprods from products where vendid = 'DLL01';
如果查詢每個供應商提供的商品數,怎麼查?答:需要使用分組,Group by子句和Having子句
10.2 建立分組
分組是使用select語句的Group by實現的。
- select vendid, count(*) numprods from products group by vend_id;
使用group by子句分組資料,然後對每個組而不是整個結果集進行聚集。
使用GROUP BY子句前,需要了解一些重要的規定:
1. GROUP BY子句可以包含任意數目的列,因而可以對分組進行巢狀,更細緻的進行分組。
2. GROUP BY子句嵌套了分組,資料將在最後指定的分組上進行彙總。
3. GROUP BY子句中列出的每一列必須是檢索列或有效的表示式。如果在SELECT中使用表示式,則必須在GROUP BY子句中指定相同的表示式。不能使用別名。
4. 大多數SQL實現不允許GROUP BY列帶有長度可變的資料型別。
5. 除聚集計算語句外,SELECT語句中的每一列都必須在GROUP BY子句中給出。
6. 如果分組列中包含具有NULL值的行,則NULL將作為一個分組返回。如果列中有多行NULL值,它們將分為一組。
7. GROUP BY子句必須出現在WHERE子句之後,Order by子句之前。
10.3 過濾分組
Group by新建分組,使用Having子句過濾分組。如:查詢至少有兩個訂單的顧客。
Where 子句和Having 子句的區別:
1. Where子句過濾的是行,而Having子句過濾的是分組。
2. Having子句可以替代Where子句,但是不建議這樣做。
- select vendid, count(*) as numprods from products where prodprice >= 4 group by vendid having count(*) > 2;
分析:首先,where語句先選出價格大於4的商品,然後按照vend_id來進行分組,再對分組進行過濾。
10.4 分組和排序
Order by | Group by |
---|---|
對產生的輸出排序 | 對行分組,但輸出可能不是分組的順序 |
任意列都可以使用 | 只可能使用選擇列或表示式列,而且必須使用每個選擇列表達式 |
不一定需要 | 如果與聚集函式一起使用列(或表示式),則必須使用 |
一般使用GROUP BY子句後,也應該使用ORDER BY子句。
10.5 Select子句的順序
子句 | 說明 | 是否必須使用 |
---|---|---|
SELECT | 要返回的列或表示式 | 是 |
FROM | 從中檢索資料的表 | 僅在從表選擇資料時使用 |
WHERE | 行級過濾 | 否 |
GROUP BY | 分組說明 | 僅在按組計算聚集時使用 |
HAVING | 組級過濾 | 否 |
ORDER BY | 輸出排序順序 | 否 |
第11課 使用子查詢
11.2 利用子查詢進行過濾
假如需要列出訂購物品RGAN01的所有顧客,應該怎樣檢索?
1. 從訂單詳情表(OrderItems)中查詢訂購物品GRANO1的所有訂單編號。
2. 根據訂單編號,從表(Orders)中查詢顧客ID
3. 根據顧客ID,從表(Customers)查詢顧客資訊。
select cust_name, cust_contact from customers
where cust_id IN (select cust_id from Order
where order_num IN (select order_num from OrderItems
where prod_id = 'GRANO1'));
作為子查詢的Select語句只能查詢單個列。企圖查詢多個列,是錯誤的。
11.3 作為計算欄位使用子查詢
假如需要顯示Customers表中每個顧客的訂單總數,應該怎樣寫?
1. 從Customers表中檢索顧客列表。
2. 對於檢索的每個顧客,統計在Orders表中的數目。
select cust_name, cust_state,
(select count(*) from Orders
where Orders.cust_id = Customers.cust_id) AS orders
from Customers order by cust_name;
該子查詢檢索到每個顧客執行一次。
第12課 聯結表
12.1.1 關係表
關係表的設計就是把資訊分成多個表,一類資料一個表。各個表通過共同的值進行關聯。
12.2 建立聯結
當from子句後接多個表時候,表示聯結產生了。select子句後面所接的欄位,分別來自於兩個表中。
1. select vend_name, prod_name, vend_city, vendors.vend_id from vendors, products where vendors.vend_id = products.vend_id;
如果沒有Where子句,那麼返回結果就是笛卡爾積。
12.2.3 聯結多個表
select prodname, vendname, prodprice, quantity from OrderItems, Products, Vendors where Products.vendid = Vendors.vendid And OrderItems.prodid = Products.prodid And ordernum = 20007;
第13課 建立高階聯結
13.1 使用表別名
使用表別名優點:
1. 縮短SQL語句
2. 允許在一條select語句中多次使用相同的表
select cust_name, cust_contact from Customers AS C, Orders AS O, OrderItems AS OI
where C.cust_id = O.cust_id and OI.order_num = O.order_num and prod_id = 'RGAN01'
13.2 使用不同型別的聯結
四種聯結: 1. 內聯結或等值聯結, 2. 自聯結(self-join), 3. 自然聯結(natural join), 4. 外聯結(outer join)。
13.2.1 自聯結
問:查詢與Y Lee同一公司的所有顧客。
1. 使用子查詢
select cust_name, cust_address from customers where cust_name = (select cust_name from customers where cust_contact = 'Y Lee')
2. 使用自聯結
select C1.cust_name, C2.cust_address from customers as C1, customers as C2 where C1.cust_name = C2.cust_name and C1.cust_contact = 'Y Lee'
用自聯結而不用子查詢:
1. 許多DBMS處理聯結遠比處理子查詢快得多。
13.2.2 自然聯結
13.2.3 外聯結
許多聯結將一個表中的行和另一個表中的行相關聯,但有時候需要包含沒有關聯行的那些行。如,以下工作:
1. 對每個顧客訂單進行計數,包括至今尚未下訂單的顧客。
2. 列出所有產品以及訂購數量,包括沒人訂購的產品。
上述舉例,包括了那些相關表中沒有關聯的行。這種聯結稱為外聯結。
檢索所有顧客及其訂單
1. 內聯結(inner join):
select Customers.cust_id, Orders.order_num from Customers inner join Orders on Customers.cust_id = Orders.cust_id;
2. 外聯結(left outer join):
select Customers.cust_id, Orders.order_num from Customers left outer join Orders
on Customers.cust_id = Orders.cust_id;
外聯結的使用的是left outer join是從左邊的表(Customers)中選擇行,所以如果右表沒有對應的id則補充。要注意on後面的表Customers和Orders順序。
3. 外聯結(right outer join)
select Customers.cust_id, Orders.order_num from Customers right outer join Orders on Orders.cust_id = Customers.cust_id;
4. 全外聯結(full outer join)
select Customers.cust_id, Orders.order_num from Orders full out join Customers
on Orders.cust_id = Customers.cust_id;
兩個表的行的最大集合。
13.3 使用帶聚集函式的聯結
檢索所有顧客及每個顧客所下的訂單數
1. select Customers.cust_id, count(Orders.order_num) AS num_ord
from Customers inner join Orders on Customers.cust_id = Orders.cust_id
group by Customers.cust_id;
13.4 使用聯結和聯結條件
聯結和聯結的使用要點:
1. 注意使用的聯結型別。有內聯結,外聯結等
2. 聯結語法每個DBMS可能不一樣。
3. 保證使用正確的聯結條件,否則返回不正確的資料。
4. 應該總是使用聯結條件,否則會得到笛卡爾積。
5. 在一個聯結中可以包含多個表,甚至可以對每個聯結采用不同的聯結型別。雖然這樣做是合法的,一般也很有用,但應該在一起測試它們 前分別測試每個聯結。這會使故障排除更為簡單。
第14課 組合查詢
利用UNION操作符將多條Select語句合成一個結果集。
14.1 組合查詢
SQL 允許執行多條查詢語句(多條Select語句),並將結果作為一個查詢結果集返回。
主要有兩種情況需要使用組合查詢:
1. 在一個查詢中,從不同的表返回結構資料。
2. 對一個表執行多個查詢,按一個查詢返回資料。
注:一般多個Where子句的Select語句都可以作為一個組合查詢。也就是說將Where子句拆分開來。
14.2 建立組合查詢
用操作符UNION操作符組合多條Select語句,將他們的結果組合成一個結果集。
14.2.1 使用UNION操作符
查詢Illinois、Indiana和Michigan等美國幾個州的所有顧客的報表,和不管位於哪個州的所有的Fun4All
1. 使用UNION操作符查詢。
select cust_name, cust_contact, cust_email from Customers
where cust_state in ('Illinois','Indiana','Michigan')
UNION
select cust_name, cust_contact, cust_email from Customers
where cust_name = 'Fun4All';
2. 使用Where子句
select cust_name, cust_contact, cust_email from Customers
where cust_state in ('Illinois','Indiana','Michigan') or cust_name = 'Fun4All'
Union和Where子句比較:
1. 對於較複雜的過濾條件,或者從多個表(而不是一個表)中檢索資料的情形,使用UNION可能會使處理更簡單。
2. 多數DBMS使用內部查詢優化程式,使用Union關鍵字會在內部組合它們,所以效能幾乎無差別。但使用Union操作符也請注意下效能問題。
14.2.2 UNION規則
Union非常好用,但使用組合前請注意下以下規則:
1. UNION必須由兩條或兩條以上的SELECT語句組成,語句之間用關鍵字UNION分隔。
2. UNION每次查詢必須包含相同的列,表示式,聚集函式。(各個列不需要以相同的次序列出)。
3. 列資料型別必須相容:型別不必完全相同,但必須是DBMS可以隱含轉換的型別。
14.2.3 包含或取消重複的行
UNION從查詢結果集中自動去除了重複的行。
使用關鍵字:Union All的會返回所有的匹配行(不進行去除重複的行)。
Union All操作符是Where不能替代的。
14.2.4 對組合查詢結果排序
用Union組合查詢時,只能使用一條Order by子句,它必須位於最後一條Select語句。
- select custname, custcontact, custid from customers where custstate in ('MI', 'OH') union select custname, custcontact, custid from customers where custcontact = 'E Fudd' order by cust_id;
注意:union組合查詢中order by子句的列必須在select後面有。且order by必須在語句最後,對整個結果集進行排序。
第15課 插入資料
利用SQL的INSERT語句將資料插入表中。
15.1.1 插入完整的行
使用insert語句時,請在表名括號內明確給定列名。
1. insert into Customers(cust_id,cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES
('1000000006','Toy Land','123 Any Street','New York','NY','11111','USA',NULL, NULL);
15.1.3 插入檢索出的資料
將Select語句的查詢結果插入到表中。顧名思義,它是由一條INSERT語句和一條SELECT語句組成的。
insert into
Customers(cust_id, cust_contact,cust_email,cust_name,cust_address,cust_city,cust_state,cust_zip,cust_country)
select
cust_id,cust_contact,cust_email,cust_name,cust_address,cust_city,cust_state,cust_zip,cust_country
from CustNew;
說明:將select語句查詢出來的結果,插入到表Customers中.
注意:
1. insert 和select不一定要求列名匹配。它使用的是列的位置,因此SELECT中的第一列(不管其列名)將用來填充表列中指定的第一列,第二列將用來填充表列中指定的第二列。
2. insert 通常只插入一行。但insert select是個例外,它可以用一條insert插入多行,不管select語句返回對少條語句,都會被插入到表中。
15.2 從一個表複製到另一個表
select into將資料複製到一個新表中。
insert select與select into區別:
1. insert select是匯出資料,先select出結果,然後插入到表中。select into是匯入資料。
select * into CustCopy from customers;
建立一個名為CustCopy的新表。然後將整個customers表內容複製到表CustCopy中。
Mysql中語法是:
create table CustCopy AS select * from Customers;
使用select into注意點:
1. 任何select選項和子句都可以使用,包括where和order by。
2. 可利用聯結從多個表插入資料(Mysql中未測試通過).
3. 不管從多少個表中檢索資料,資料都只能插入到一個表中。
第16課 更新和刪除資料
16.1 更新資料
update語句更新表中的資料。
- update Customers set custcontact = 'Sam Roberts',custemail = '[email protected]' where cust_id = '10000006';
注意:update語句可能更新多個值。
16.2 刪除資料
delete語句刪除表中的資料。
- delete from Customers where cust_id = '10000006'
刪除時外來鍵考慮:
1. 使用delete語句刪除資料時,可能會有外來鍵的影響。比如:我要刪除Products表中某個商品,但是該商品cust_id在訂單表中有記錄,作為訂單表的外來鍵。那麼刪除會失敗。
16.3 更新和刪除的指導原則
- 除非確實刪除所有行或更新所有行,否則絕不能不使用where語句。
- 保證每個表都要有主鍵,儘可能像where子句那樣使用它。
- 在update和delete語句使用where子句前,應該先用select進行測試,保證過濾條件是正確無誤的。
- 使用強制實施引用完整性的資料庫,這樣DBMS將不允許刪除其資料與其他表相關聯的行。
第17課 建立和操縱表
該課主要講解:建立,更改和刪除表的基本知識。
17.1.1 表建立基礎
利用create table建立表,必須給出下列資訊:
1. 新表的名字,在關鍵字create table後給出.
2. 表列的名字和定義,用逗號隔開。
3. 有的DBMS還要指定表的位置。
create table Products
(
prod_id char(10) Not null,
vend_id char(10) Not null,
prod_name char(254) Not null,
prod_price DECIMAL(8,2),
prod_desc text(1000), NULL
);
17.1.2 使用Null
建立表的時候,指定表的列為Not null,則表示,以後執行insert語句,該列必須有值,不接受null。
17.1.3 指定預設值
建立表的時候,可以為表的列提供預設值。
- create table OrderItems
(
order_num INTEGER Not null,
order_item INTEGER Not null,
prod_id CHAR(10) Not null,
quantity INTEGER Not null default 1,
item_price DECIMAL(8,2) not null
);
17.2 更新表
使用alter table時,請考慮下列的事:
1. 理想情況下,不要再表包含資料時對其進行更新。應該在表的設計過程中充分烤爐未來可能。
2. 所有的DBMS都允許給現有的表增加列,不過對所增加列的資料型別(以及NULL和Default的使用)有所限制.
3. 許多DBMS不允許刪除或更改表中的列.
- alter table Vendors add vend_phone CHAR(20);
複雜的表結構更改一般需要手動刪除過程,它涉及以下步驟:
1. 用新的列布局建立一個新表;
2. 使用INSERT SELECT語句從舊錶複製資料到新表。有必要的話,可以使用轉換函式和計算欄位;
3. 檢驗包含所需資料的新表;
4. 重新命名舊錶(如果確定,可以刪除它);
5. 用舊錶原來的名字重新命名新表;
6. 根據需要,重新建立觸發器、儲存過程、索引和外來鍵
17.3 刪除表
- drop table Customers;
注意:刪除表不可撤銷。請慎重
17.4 重命名錶
每個DBMS對錶重新命名的支援有所不同,具體要參考具體的DBMS文件.
第18課 使用檢視
18.1 檢視
檢視是虛擬的表。與包含資料的表不一樣,檢視只包含使用時動態檢索資料的查詢。
理解檢視的最好方法是看例子.
select cust_name, cust_contact from Customers, Orders, OrderItems
where Customers.cust_id = Orders.cust_id
and OrderItems.order_num = Orders.order_num
and prod_id = 'RGAN01';
該句sql檢索訂購了某種商品的顧客。任何需要這個資料的人必須理解這些表與表之間的關係。
假如將整個查詢包裝成一個名為ProductsCustomers的虛擬表。那麼sql可以簡化為:
select cust_name, cust_contact from ProductCustomers where prod_id = 'RGANO1';
總結:檢視不包含任何的列或資料,包含的是一個查詢。
18.1.1 為什麼使用檢視
檢視的常見使用場景:
1. 重用SQL語句。
2. 簡化複製的SQL操作。在編寫查詢後,可以方便的使用它,而不必知道具體的細節。
3. 使用表的一部分,而不是整個表。
4. 保護資料。可以授予使用者訪問表的特定部分,而不是表的全部許可權。
5. 更改資料格式和表示。檢視可返回與底層表的表示和格式不同的資料。
建立檢視後,可以用表相同的方式去使用它們。可以對檢視執行select操作,過濾和排序資料,將檢視聯結到其他檢視或表等。
再次強調:檢視只是包含了動態檢索資料的查詢。
18.1.2 檢視的規則與限制
不同的DBMS中檢視的限制和規則可能不同,具體請參考文件。
檢視的建立和使用的一些最常見的規則和限制:
1. 與表一樣,檢視必須唯一命名,名字不能有衝突。
2. 對於可以建立的檢視數目沒有限制。
3. 建立檢視,必須具有足夠的訪問許可權。
4. 檢視可以巢狀,即可以利用從其他檢視中檢索資料的查詢來構造檢視。所允許的巢狀層數在不同的DBMS中有所不同(巢狀檢視可能會嚴 重降低查詢的效能,因此在產品環境中使用之前,應該對其進行全面測試)。
5. 許多DBMS禁止在檢視查詢中使用ORDER BY子句。
6. 有些DBMS要求對返回的所有列進行命名,如果列是計算欄位,則需要使用別名。
7. 檢視不能索引,也不能有關聯的觸發器或預設值。
8. 有些DBMS把檢視作為只讀的查詢,這表示可以從檢視檢索資料,但不能將資料寫回底層表。
18.2 建立檢視
Create view語句來建立檢視。
18.2.1 利用檢視簡化複雜的聯結
檢視最常見的應用:隱藏複雜的SQL
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;
然後呼叫sql查詢:
select cust_name, cust_contact from ProductCustomers where prod_id = 'RGANO1';
18.2.2 用檢視重新下格式化檢索的資料
檢視另一個常見的應用: 重新格式化檢索出的資料
create view VendorLocations AS
select RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')'
AS vend_title from Vendors;
在單個組合計算列中返回供應商名和位置
18.2.3 用檢視過濾不想要的資料
可以定義一個檢視:過濾沒有電子郵件地址的顧客
create view CustomerEMailList AS
select cust_id, cust_name, cust_email
from Customers where cust_email is not Null;
18.2.4 使用檢視與計算欄位
在簡化計算欄位的使用上,檢視也特別有用。create view OrderItemsExpanded AS select order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price from OrderItems
第19課 使用儲存過程
19.1 儲存過程
1. 通俗的講,儲存過程就是類似於C的一個方法。
2. 簡單的說,儲存過程就是為以後使用而儲存一條或多條SQL語句。可以將其視為批檔案,但它的作用不僅限於批處理。
19.2 為什麼使用儲存過程
- 儲存過程有3個優點:簡單,安全和高效能。
- 多數DBMS的儲存過程可能不同,而且儲存過程也比較複雜,難於編寫。
19.3 執行儲存過程
使用關鍵字execute來執行儲存過程
EXECUTE AddNewProduct( 'JTS01', 'Stuffed Eiffel Tower', 6.49,'Plush stuffed toy with the text");
AddNewProduct是一個儲存過程,將一個新的商品新增到Product表中。但我們發現,最重要的欄位prod_id列沒有,應為我們想統一化規格化生成對應的prod_id.
所以,該儲存過程需要做以下3件事:
1. 驗證傳遞的資料,保證所有4個引數都有值;
2. 生成用作主鍵的唯一ID;
3. 將新產品插入Products表,在合適的列中儲存生成的主鍵和傳遞的資料。
19.4 建立儲存過程
建立儲存過程,每個DBMS差別很大,具體需要參考DBMS文件。
第20課 管理事務處理
- 使用事務處理,確保成批的SQL操作要麼完全執行,要麼完全不執行,來保證資料庫的完整性。
- 事務處理是一種機制,用來管理必須成批執行的SQL操作,保證資料庫不可能包括不完整的操作結果。
- 事務都應該具備ACID特徵。所謂ACID是Atomic(原子性),Consistent(一致性),Isolated(隔離性),Durable(永續性)四個詞的首字母所寫,
在使用事務時,需要理解幾個關鍵字:
1. 事務(transaction)指一組SQL語句.
2. 回退(rollback)指撤銷指定SQL語句的過程。
3. 提交(commit)指將未儲存的SQL語句結果寫入資料庫表。
4. 保留點(savepoint)指事務處理中設定的臨時佔位符(placeholder),可以對它釋出回退。
哪些sql語句可以回退?
答:Insert, Delete和Update語句可以回退。Select, Drop和Create語句不能回退。
20.2 控制事務處理
管理事務的關鍵在於將SQL語句組合成邏輯塊,並規定資料何時回退,何時不應該回退。
不同的DBMS實現事務處理的語法不同:
1. SQL Server
Begin Transaction
...
Commit Transaction
在這裡Begin Transaction和Commit Transaction之間的SQL必須完全執行,或完全不執行。
2. Mysql
Start Transaction
...
Commit
3. Oracle
Set Transaction
...
Commit
20.2.1 使用Rollback
SQL 使用Rollback來回退(撤銷)SQL命令
命令:delete from Orders; Rollback;
使用Delete語句,然後使用Rollback語句撤銷。該句能充分說明:在事務處理塊中,delete操作(insert操作和update操作)並不是最終的結果。
20.2.2 使用Commit
在事務處理塊中,提交必須時顯示提交。
刪除訂單12345,所以需要同時更新兩個資料庫表Orders表和OrderItems表。
1. Mysql中
Begin Transaction
delete OrderItems where order_num = 12345;
delete Orders where order_num = 12345;
Commit Transaction
2. Oracle中
Set Transaction
delete OrderItems where order_num = 12345;
delete Orders where order_num = 12345;
Commit;
上面的事務處理塊中同時更新兩個表中的記錄,事務保證了操作的一致性,不可能出現部分刪除。
20.2.3 使用保留點
保留點(savepoint)作用是:支援回退部分事務。
例如新增一個訂單,需要插入顧客資訊,插入訂單資訊,訂單詳情資訊,但當插入訂單詳情時發生錯誤,只需要回退到插入訂單資訊,不需要回退到插入顧客資訊。這是就需要回退部分事務。
保留點使用:在編寫事務過程中,需要在事務處理塊中的合適位置放置佔位符。用於後面的回退。
不同的DBMS的保留點設定不同
1. Mysql
Savepoint delete1;
2. SQL Server
Save Transaction delete1;
不同的DBMS的回退保留點的方式不同
1. Mysql
Rollback to delete1;
2. SQL Server
Rollback transaction delete1;
20.3 SQL Server事務舉例
不同的DBMS可能不同,但是總體概念和流程都是相同的。
Begin Transaction
insert into Customers(cust_id, cust_name) values('1000000010', 'Toys Emporium');
save transaction StartOrder;
insert into Orders(order_num, order_date, cust_id) values(20100,'2001/12/1','1000000010');
IF @@ERROR <> 0 Rollback Transaction StartOrder;
insert into OrderItems(order_num, order_item, prod_id, quantity, item_price)
values(20100, 1, 'BR01', 100, 5.49);
IF @@ERROR <> 0 Rollback Transaction StartOrder;
insert into OrderItems(order_num, order_item, prod_id, quantity, item_price)
values(20100, 2, 'BR03', 100, 10.99);
IF @@ERROR <> 0 Rollback Transaction StartOrder;
Commit Transaction;
第21課 使用遊標
21.1 遊標
SQL檢索結果是返回一組稱為結果集的行。但是無法從結果集中得到第一行,下一行或前10行的資料。但是大多數Web應用開發人員不使用遊標,而是根據自己的需要開發相應的功能。如:利用limit1, 10來實現分頁查詢, 或使用foreach來實現遍歷。
遊標的用途:
有時,需要在檢索出來的行中前進或後退一行或多行,就需要使用遊標。
遊標(cursor)是一個儲存在DBMS伺服器上的資料庫查詢,它不是一條SELECT語句。在儲存了遊標之後,應用程式可以根據需要滾動或瀏覽資料集中的資料。
遊標在不同的DBMS中的一些共性:
1. 能夠標記遊標為只讀,使資料能讀取,但不能更新和刪除。
2. 能控制可以執行的定向操作(向前、向後、第一、最後、絕對位置、相對位置等)。
3. 能標記某些列為可編輯的,某些列為不可編輯的。
4. 規定訪問範圍,使遊標對建立它的特定請求(如儲存過程)或對所有請求可訪問。
5. 指示DBMS對檢索出的資料(而不是指出表中活動資料)進行復制,使資料在遊標開啟和訪問期間不變化。
21.2 使用遊標
使用遊標的幾個明確的步驟:
1. 在使用遊標前,必須定義它。這個過程實際上沒有檢索資料,它只是定義要使用的SELECT語句和遊標。
2. 一旦定義,就必須開啟遊標以供使用。這個過程用前面定義的SELECT語句把資料實際檢索出來。
3. 對於填有資料的遊標,根據需要取檢索各行。
4. 在結束遊標使用時,必須關閉遊標,可能的話,釋放遊標(有賴於具體的DBMS)。
21.2.1 建立遊標
使用Declare語句建立遊標。
建立一個遊標來檢索沒有電子郵件地址的所有顧客.
1. Mysql + SQL Server
Declare CustCursor Cursor for
Select * from Customers where cust_email is null;
2. Oracle
Declare Cursor CustCursor is
Select * From Customers where cust_email is null;
21.2.2 使用遊標
遊標的使用場景並不多,該節筆記比較粗糙。
使用OPEN CURSOR語句開啟遊標
1. Open Cursor CustCursor;
使用Fetch語句訪問遊標資料。
Fetch需要指出檢索哪些行,從何處檢索他們以及將他們存放於何處。
Declare Type CustCursor IS ref Cursor
Return Customers%ROWTYPE;
Declare CustRecord Customers%ROWTYPE
Begin
Open CustCursor;
Fetch CustCursor INTO CustRecord;
Close CustCursor;
End;
21.2.3 關閉遊標
1. Oracle
Close CustCursor;
2. SQL Server
Close CustCursor
Deallocate Cursor CustCursor;
第22課 高階SQL特性
22.1 約束
- 約束: 管理如何插入或處理資料庫資料的規則。
- 引用完整性(referential integrity): 利用鍵來建立從一個表到另一個表的引用
關係型資料庫,需要保證插入資料庫的資料和合法性。
例如:如果Orders表儲存訂單資訊,OrderItems表儲存訂單詳細內容,應該保證OrderItems中引用的任何訂單ID都存在於Orders中。類似地,在Orders表中引用的任意顧客必須存在於Customers表中。
DBMS通過在資料庫表上施加約束來實施引用完整性.
22.1.1 主鍵
主鍵是一種特殊的約束,用來某一行的資料是唯一的,而且主鍵永不改動。
表中的列只要滿足以下條件,可用於主鍵:
1. 任意兩行的主鍵值都不相同。
2. 每行都具有一個主鍵值(即列中不允許NULL值)。
3. 包含主鍵值的列從不修改或更新。
4. 主鍵值不能重用。如果從表中刪除某一行,其主鍵值不分配給新行。
主鍵的建立:
1. Create Table
Create Table Vendors
(
vend_id CHAR(10) NOT NULL Primary Key,
vend_name CHAR(50) NOT NULL,
vend_address CHAR(50) NULL,
vend_city CHAR(50) NULL,
vend_state CHAR(5) NULL,
vend_zip CHAR(10) NULL,
vend_country CHAR(50) NULL
);
Primary Key宣告表的主鍵列
2. Alter Table
Alter Table Vendors
Add Constraint Primary Key(vend_id);
22.1.2 外來鍵
外來鍵是表中的一列,其值必須在另一表的主鍵列中。
外來鍵是關係資料庫描述表和表之間依賴關係
1. Create Table
Create Table Orders
(
order_num Integer not null primary key,
order_date DateTime not null,
cust_id char(10) not null references Customers(cust_id)
);
2 Alter Table
Alter Table Orders
Add Constraint Foreign key (cust_id) references Customers(cust_id);
外來鍵的作用:
1. 能夠幫組保證引用完整性。
2. 防止意外刪除記錄
由於顧客表Customers表中主見: cust_id,作為訂單表Orders中的外來鍵。所以如果想直接刪除顧客表中的記錄,必須保證其值已經不被訂單表中依賴。
3. 級聯刪除
Mysql支援級聯刪除特性。解釋:如果從顧客表Customers表中刪除某個顧客,那麼由於顧客表Customers表中的主見cust_id作為了Orders表中的外來鍵依賴,所以訂單表Orders中的該顧客的訂單也一併刪除。
22.1.3 唯一約束
唯一約束用來保證某一列中的資料是唯一的。它和主鍵有以下區別:
1. 表可包含多個唯一約束,但每個表只允許一個主鍵。
2. 唯一約束列可包含NULL值。
3. 唯一約束列可修改或更新。
4. 唯一約束列的值可重複使用。
5. 與主鍵不一樣,唯一約束不能用來定義外來鍵。
22.1.4 檢查約束
檢查約束用來保證一列中的資料滿足一組指定的條件。檢查約束的常見用途:
1. 檢查最小或最大值。例如,防止0個物品的訂單(即使0是合法的數)。
2. 指定範圍。例如,保證發貨日期大於等於今天的日期,但不超過今天起一年後的日期。
3. 只允許特定的值。例如,在性別欄位中只允許M或F。
對OrderItems表施加了檢查約束,保證所有物品的數量大於0:
CREATE TABLE OrderItems
(
order_num INTEGER NOT NULL,
order_item INTEGER not null,
prod_id CHAR(10) not null,
quantity INTEGER not null check (quantity > 0),
item_price MONEY not null
);
檢查名為gender的列只包含M或F
Alter Table OrderItems
Add Constraint Check (gender LIKE '[MF]')
22.2 索引
索引是利用B+等索引機制,加快查詢和排序的速度。
使用索引需要記住以下內容:
1. 索引提高檢索操作的效能,但降低了資料插入、修改和刪除的效能。因為資料變更需要更新索引。
2. 索引資料可能要佔用大量的儲存空間。
3. 並非所有資料都適合做索引。查詢量非常大,列的資料非常多,使用使用索引。
4. 索引用於資料過濾和資料排序。如果你經常以某種特定的順序排序資料,則該資料可能適合做索引。
5. 可以在索引中定義多個列(例如,州加上城市)。這樣的索引僅在以州加城市的順序排序時有用。
所以必須唯一命名:
Create Index prod_name_index On Products(prod_name);
22.2.1 索引建立的幾大原則
組合索引的解釋:
如果建立了(state, city, zip)列作為組合索引,索引中的資料行按照state/city/zip次序排列,
這意味著,這個索引可以被用於搜尋如下所示的資料列組合:
state, city, zip
state, city
state
但是MySQL不能利用這個索引來搜尋沒有包含在最左字首的內容。例如,如果你按照city或zip來搜尋,
就不會使用到這個索引。如果你按照state,和zip來搜尋,該索引也是不能用於這種組合值的,但是可以利用索引來查詢匹配的state從而縮小搜尋的範圍。
1. 選擇唯一性索引
唯一性索引的值是唯一的,能快速的通過該索引來確定某條記錄。
2. 為經常需要排序、分組和聯合操作的欄位建立索引
經常需要Order By、Group By、Distinct和Union等操作的欄位,排序操作會浪費很多時間。
3. 為常作為查詢條件的欄位建立索引
某個欄位經常用來做查詢條件,該欄位的查詢速度會影響整個表的查詢速度。使用索引,可以極大加快查詢速度。
4. 最左字首匹配原則,非常重要的原則。
mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,
比如state='yes' and city='wuwei' and price > 3 and name = 'ppp' 如果建立(state, city, price, name)順序的索引,
name的查詢是用不到索引的,只能使用部分索引,然後在結果集上面進行排序。如果建立(state, city , ppp, price)的索引則都可以用到,state, city, name的順序可以任意調整。
5. =和in可以亂序。
比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式。
但是如果建立索引(a,b,c),結果where子句是:b =2 and c=3,則索引不起作用。
6. 儘量使用資料量少的索引
如果索引的值很長,那麼查詢的速度會受到影響。
例如,對一個CHAR(100)型別的欄位進行全文檢索需要的時間肯定要比對CHAR(10)型別的欄位需要的時間要多。
7. 儘量使用字首來索引
索引欄位的值很長,應該採用字首來索引。
8. 儘量選擇區分度高的列作為索引。
資料量區分度越高,索引的比較成本會小很多。
9. 刪除不再使用或者很少使用的索引
請定期刪除不在使用的索引。
10. 限制索引的數目
使用索引需要付出代價,索引會消耗磁碟空間,對資料庫記錄的更新和刪除產生影響。
11. 索引列不能參與計算。
堅決不能將某個計算函式作為縮影。如:from_unixtime(create_time) = ’2014-05-29’
12. 儘量的擴充套件索引,不要新建索引。
比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可
22.3 觸發器
觸發器是特殊的儲存過程,可以在特定的資料庫活動發生時自動執行。
觸發器可以與特定表上的Insert, Update或Delete操作(或組合)想關聯。
如:與Orders表上的Insert操作相關聯的觸發器只在Orders表中插入行時才會執行。
觸發器的常見用途:
1. 保證資料一致。例如,在Insert或Update操作中將所有州名轉換為大寫。
2. 基於某個表的變動在其他表上執行活動。例如,每當更新或刪除一行時將審計跟蹤記錄寫入某個日誌表。
3. 進行額外的驗證並根據需要回退資料。例如,保證某個顧客的可用資金不超限定,如果已經超出,則阻塞插入。
4. 計算計算列的值或更新時間戳。
不同的DBMS的觸發器差距很大,請參考具體文件.
如:建立一個觸發器,對所有Insert和Update操作,將Customers表中的cust_state列轉換為大寫。
1. SQL Server
Create Trigger customer_state On Customers
For Insert, Update As
Update Customers Set cust_state = Upper(cust_state)
2. Oracle
Create Trigger customer_state
After Insert Or Uupdate
For Each Row
Begin
Update Customers
Set cust_state = Upper(cust_state)
Where Customers.cust_id = :OLD.cust_id
end;
22.4 資料庫安全
一般對資料保護操作有:
1. 對資料庫管理功能(建立表、更改或刪除已存在的表等)的訪問;
2. 對特定資料庫或表的訪問;
3. 訪問的型別(只讀、對特定列的訪問等);
4. 僅通過檢視或儲存過程對錶進行訪問;
5. 建立多層次的安全措施,從而允許多種基於登入的訪問和控制;
6. 限制管理使用者賬號的能力。
相關推薦
SQL必知必會第4版讀書筆記
SQL必知必會_4前言@author 魯偉林 在讀電子版<<SQL必知必會>> 第4版時,做了下筆記。供以後自己或者其他學習者參考。 電子版<<SQL必知必會>>和書中使用的資料庫和表的原始碼, 請參看地址:https://gi
SQL必知必會 第4版 pdf
AR rep 針對 gre 通配符 環境 http 使用 總數 下載地址:網盤下載 內容簡介 · · · · · ·SQL語法簡潔,使用方式靈活,功能強大,已經成為當今程序員不可或缺的技能。本書是深受世界各地讀者歡迎的SQL經典暢銷書,內容豐富,文字簡潔明快,針對Orac
SQL必知必會 第4版pdf
目 錄 第1課 瞭解SQL 1 1.1 資料庫基礎 1 1.2 什麼是SQL 6 1.3 動手實踐 7 1.4 小結 8 第2課 檢索資料 9 2.1 SELECT語句 9 2.2 檢索單個列 10 2.3 檢索多個列
分享《SQL必知必會(第4版)》高清中文PDF+高清英文PDF+原始碼
下載:https://pan.baidu.com/s/1hRb-TS_R-0fnXPodS5OoDg 《SQL必知必會(第4版)》高清中文PDF+高清英文PDF+程式碼 下載:https://pan.baidu.com/s/1a-JepzWU77yH0IUfBiLPPw 《SQL基礎教程(第2版)》高清
《SQL必知必會(第4版)》中英文PDF及程式碼+《SQL進階教程》中文PDF及程式碼 (學習總結)
下載:https://pan.baidu.com/s/1hRb-TS_R-0fnXPodS5OoDg 《SQL必知必會(第4版)》高清中文PDF+高清英文PDF+程式碼 下載:https://pan.baidu.com/s/11-MnDu0khzwO4tiJqHznnA 《SQL進階教程》高清中文PDF
Effective Java 第三版讀書筆記——條款4:使用私有構造器來強制實現不可例項化
偶爾你會想寫一個類,這個類只是一組靜態方法和靜態屬性。 這樣的類獲得了不好的名聲,因為有些人濫用這些類而避免以面向物件的方式思考,但是它們有時候確實有實際的用處: 它們可以被用來聚集一組建立在基礎型別或陣列之上的相關方法,例如 java.lang.Math 或 java.util
《Linux程式設計》第4版 核心筆記
【前言】 讀本書的學習目標: 1. 掌握標準linux C語言函式庫和箇中linux或unix標準指定的其他工具的使用方法 2. 掌握如何使用大多數標準linux開發工具 3. 學會通過DBM和MySQL資料庫系統儲存Linux中的資料 4. 理解如何為X視窗系統建立圖形使
C Primer Plus (第6版) 讀書筆記_Chapter 1
抽象 ner 競爭 crete 個數字 面向 ref 編程 bsd 第 1 章 初識 C 語言 ■ C 的歷史和特性 ■ 編寫程序的步驟 ■ 編譯器和鏈接器的一些知識 ■ C 標準 1.1 C 語言的起源 1972年,貝爾實驗室的 丹尼斯 ? 裏奇
作業系統概述第七版讀書筆記第一章
概述 作業系統是作為計算機硬體和計算機使用者之間的中介程式 目的是為使用者提供方便有效的執行程式的環境 是管理計算機硬體的軟體 作業系統做什麼 計算機系統組成部分:計算機硬體、作業系統、系統程式和應用程式、使用者 作業系統:控制使用者的應用程式對硬體的使用 作業系統是一直
Effective Java 第三版讀書筆記——條款1.考慮使用靜態工廠方法替代構造器
lean jdb 底層 public lasso 基本 win inter nds 獲取一個類的實例的傳統方法是使用公開的構造器,除此之外,一個類還可以提供公開的靜態工廠方法(static factory method)來返回它的實例。例如 Boolean 類中的 valu
Effective Java 第三版讀書筆記——條款3:使用私有構造器或列舉型別來強制實現 singleton 屬性
單例(singleton)就是一個只例項化一次的類。使類成為單例可能會使它的測試變得困難,因為除非它實現了作為其型別的介面,否則不可能用模擬實現來代替這個單例。下面是幾種實現單例的方法: 使用 public field 方法 // Singleton with public final field pub
Effective Java 第三版讀書筆記——條款5:使用依賴注入替代替代硬連線資源
許多類都會依賴一個或多個基本資源。例如,拼寫檢查器依賴於字典。下面是兩種錯誤的實現方式: 使用 static utility classes: // Inappropriate use of static utility - inflexible & untestable! public cl
Effective Java 第三版讀書筆記——條款7:清除過期的物件引用
Java 帶有垃圾回收(garbage-collected)機制,這使程式設計師的工作變得容易了很多——因為你的物件在使用完畢以後就自動回收了。這很容易讓人覺得你不需要考慮記憶體管理,但這並不完全正確。 考慮下面這個簡單的棧實現: // Can you spot the "memor
Effective Java 第三版讀書筆記——條款6:避免建立不必要的物件
通常來講,重用一個物件比建立一個功能相同的物件更加合適。重用速度更快,並且更接近現代的程式碼風格。如果物件是不可變的(條款 17),它總是可以被重用。 考慮一個極端的例子: String s = new String("bikini"); // DON'T DO THIS! 這
Effective Java 第三版讀書筆記——條款2:當構造器引數太多時考慮使用 builder 模式
靜態工廠方法和構造器都有一個限制:不能很好地支援可選引數(optional parameters)很多的類。考慮一個代表包裝食品上營養成分標籤的類:這些標籤有幾個必需的屬性(每份建議攝入量、每個包裝所含的份數、每份的卡路里)和超過二十個可選的屬性(總脂肪、飽和脂肪、反式脂肪、鈉等等)。應該為
Effective Java 第三版讀書筆記——條款11:重寫 equals 方法的同時也要重寫 hashCode 方法
在每一個重寫 equals 方法的類中,都要重寫 hashCode 方法。如果不這樣做,你的類會違反 hashCode 的通用約定,這會阻止它在 HashMap 和 HashSet 這樣的集合中正常工作。下面是根據 Object 原始碼改編的約定: 在一個應用程式執行過程中,如果在 equal
Effective Java 第三版讀書筆記——條款12:總是重寫 toString 方法
雖然 Object 類提供了 toString 方法的實現,但它返回的字串通常不是類的使用者想要看到的。它由類名後跟一個 “ at ” 符號(@)和雜湊碼的無符號十六進位制表示組成,例如 [email protected]。toString 的通用約定要求,返回的字串應該是“一個簡潔但內容豐富的表示
Effective Java 第三版讀書筆記——條款10:重寫 equals 方法時遵守通用的規定
重寫 equals 方法看起來很簡單,但是有很多方法會導致重寫出錯。避免此問題的最簡單方法是不去重寫 equals 方法,在這種情況下,類的每個例項只與自身相等。如果滿足以下任一條件,則說明不去重寫是正確的做法: 每個類的例項都是固有唯一的。例如像 Thread 這樣代表活動實
Effective Java 第三版讀書筆記——條款8:避免使用 Finalizer 和 Cleaner 機制
Finalizer 機制通常是不可預知的、危險的、不必要的。它們的使用會導致不穩定的行為,糟糕的效能和移植性問題。從 Java 9 開始,Finalizer 機制已被棄用,但仍被 Java 類庫所使用。 Java 9 中 Cleaner 機制代替了 Finalizer 機制。 Cleaner
Effective Java 第三版讀書筆記——條款14:考慮實現 Comparable 介面
與本章討論的其他方法不同,compareTo 方法並沒有在 Object 類中宣告。相反,它是 Comparable 介面中的唯一方法。 通過實現 Comparable 介面,一個類表明它的例項有一個自然序( natural ordering )。對實現 Comparable 介面的物件所組成的陣列排序非常簡