1. 程式人生 > >SQL必知必會第4版讀書筆記

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 使用註釋
  1. 單行註釋: #
  2. 多行註釋: /*. ... */

第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子句
  1. OR操作符和AND操作符。
select prod_name, prod_price, vend_id from products where vend_id = '1001' OR vend_id = '1005' and prod_price >= 10;

結果:

prod_nameprod_pricevend_id
.5 ton anvil5.991001
1 ton anvil9.991001
2 ton anvil14.991001
JetPack 100035.001005
JetPack 200055.001005

分析:

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操作符的優點

  1. IN操作符一般比一組OR操作符更快
  2. IN最大的優點是:可以包含其他SELECT語句,能夠動態的建立WHERE子句。
5.3 NOT操作符

Not操作符用作否定其後所跟的任何條件。

  • select * from products where Not vendid = 1001 and prodname = 'Safe';
prod_idvend_idprod_nameprod_priceprod_desc
SAFE1003Safe50.00Safe 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 使用萬用字元的技巧
  1. 要知道,使用萬用字元可能比其他的搜尋耗費更長的時間,對資料庫的壓力更大。
  2. 不要過度使用萬用字元,在其他操作符能達到效果的情況下,儘量不要使用萬用字元。
  3. 儘量不要把萬用字元放在搜尋模式的開始處,把萬用字元置於開始處,搜尋起來最慢的。

第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 byGroup 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 更新和刪除的指導原則
  1. 除非確實刪除所有行或更新所有行,否則絕不能不使用where語句。
  2. 保證每個表都要有主鍵,儘可能像where子句那樣使用它。
  3. 在update和delete語句使用where子句前,應該先用select進行測試,保證過濾條件是正確無誤的。
  4. 使用強制實施引用完整性的資料庫,這樣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 為什麼使用儲存過程
  1. 儲存過程有3個優點:簡單,安全和高效能。
  2. 多數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 約束
  1. 約束: 管理如何插入或處理資料庫資料的規則。
  2. 引用完整性(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. 限制管理使用者賬號的能力。

相關推薦

SQL4讀書筆記

SQL必知必會_4前言@author 魯偉林 在讀電子版<<SQL必知必會>> 第4版時,做了下筆記。供以後自己或者其他學習者參考。 電子版<<SQL必知必會>>和書中使用的資料庫和表的原始碼, 請參看地址:https://gi

SQL 4 pdf

AR rep 針對 gre 通配符 環境 http 使用 總數 下載地址:網盤下載 內容簡介 · · · · · ·SQL語法簡潔,使用方式靈活,功能強大,已經成為當今程序員不可或缺的技能。本書是深受世界各地讀者歡迎的SQL經典暢銷書,內容豐富,文字簡潔明快,針對Orac

SQL 4pdf

目    錄 第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 介面的物件所組成的陣列排序非常簡