1. 程式人生 > >SQL必知必會Note(1-10)

SQL必知必會Note(1-10)

第1章 瞭解SQL

【資料庫】儲存有組織的資料的容器(通常是一個檔案或一組檔案)。

【表】某種特定型別資料的結構化清單,儲存在表中的資料是同一種類型的資料或清單。
  在相同資料庫中不能兩次使用相同的表名,但在不同的資料庫中卻可以使用相同的表名。

【模式】關於資料庫和表的佈局及特性的資訊。

【列】表中的一個欄位。所有表都是由一個或多個列組成的。表由列組成。列儲存表中某部分的資訊。
  理解列的最好辦法是將資料庫表想象為一個網格,就像個電子表格那樣。網格中每一列儲存著某種特定的資訊。例如,在顧客表中,一列儲存顧客編號,另一列儲存顧客姓名,而地址、城市、州以及郵政編碼全都儲存在各自的列中。
  可以根據具體需求來決定把資料分解到何種程度。例如,一般可以把門牌號和街道名一起儲存在地址裡。這沒有問題,除非你哪天想用街道名來排序,這時,最好將門牌號和街道名分開。

【資料型別】所容許的資料的型別。每個表列都有相應的資料型別,它限制該列中儲存的資料。
  例如,如果列中儲存的是數字(或許是訂單中的物品數),則相應的資料型別應該為數值型別。如果列中儲存的是日期、文字、註釋、金額等,則應該規定好恰當的資料型別。

【行】表中的一條記錄。你可能聽到使用者在提到行時稱其為資料庫記錄(record)。這兩個術語多半是可以交替使用的,但從技術上說,行才是正確的術語。
  表中的資料是按行儲存的,所儲存的每個記錄儲存在自己的行內。例如,顧客表可以每行儲存一個顧客。表中的行編號為記錄的編號。

【主鍵】唯一標識表中每行的這個列(或這幾列)稱為主鍵。主鍵用來表示一個特定的行。沒有主鍵,更新或刪除表中特定行就極為困難,因為你不能保證操作只涉及相關的行。
  表中的任何列都可以作為主鍵,只要它滿足以下條件:
  任意兩行都不具有相同的主鍵值;
  每一行都必須具有一個主鍵值(主鍵列不允許NULL值);
  主鍵列中的值不允許修改或更新;
  主鍵值不能重用(如果某行從表中刪除,它的主鍵不能賦給以後的新行)。

【SQL】是Structured Query Language(結構化查詢語言)的縮寫。SQL是一種專門用來與資料庫溝通的語言。提供一種從資料庫中讀寫資料的簡單有效的方法。

第2章 檢索資料
【SELECT語句】從一個或多個表中檢索資料資訊
  為了使用SELECT檢索表資料,必須至少給出兩條資訊:想選擇什麼,從什麼地方選擇。

【檢索單個列】

SELECT prod_name FROM Products;
-- 從 Products 表中檢索一個名為 prod_name 的列。

  所需的列名寫在 SELECT 關鍵字之後,FROM 關鍵字指出從哪個表中檢索資料。
  【Hint】 SQL 語句不區分大小寫,即“SELECT”和“select”一樣;但是表名、列名和值可能有所不同。

【檢索多個列】從一個表中檢索多個列,在 SELECT 關鍵字後給出多個列名,列名之間用逗號隔開。

SELECT prod_id, prod_name, prod_price
FROM Products;
-- 從表 Products 中選擇 3 列資料

【檢索所有列()】在實際列名的位置使用星號()萬用字元

SELECT *
FROM Products

  給定一個萬用字元(*),則返回表中所有的列。列的順序一般是列在表定義中出現的物理順序。

【檢索不同的值(DISTINCT)】

--檢索 products 表中所有產品供應商的id,但是返回行有重複的id,怎麼去重?
SELECT DISTINCT vend_id
FROM Products

  DISTINCT告訴 DBMS只返回(具有唯一性)的vend_id 行。

【限制返回的行數(TOP)】

SELECT TOP 5 prod_name
FROM Products
--只返回匹配的前5行資料

【註釋】(– 和 /* */)

第3章 排序檢索資料

【排序資料(ORDER BY)】為了明確檢索的資料順序,可用 ORDER BY 子句取一個或多個列的名字,據此對輸出進行排序

SELECT prod_name
FROM Products
ORDER BY prod_name;
-- 對 prod_name 列以字母順序進行資料排列

【Hint】在指定一條order by子句時,應保證它是select語句中最後一條子句。該子句的次序不對將會出現錯誤資訊。

【按多個列排序】
  下面程式碼檢索3個列,並按其中兩個列對結果進行排序

-- 先價格,若價格相同按名稱排序
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price, prod_name;

【按列位置排序(相對位置)】

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY 2, 3;
-- 輸出與上面的查詢相同。2 指 SELECT 清單的第2列即prod_price,3 指第3列即 prod_name

【指定排序方向(ASC,DESC)】預設升序(ASC)排列,可以指定 DESC 關鍵字進行降序排序。

SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC
-- DESC 關鍵字只應用到直接位於其前面的列名。
-- 如果打算用多個列排序,該怎麼辦?
SELECT prod_id, prod_price, prod_name
FROM Products
ORDER BY prod_price DESC, prod_name
-- 多列降序排列,必須對每列指定DESC

第4章 過濾資料

【WHERE 子句:過濾】指定搜尋條件(即過濾條件)。
  WHERE 子句在表名(FROM 子句)後給出,根據 WHERE 子句中指定的條件過濾。

SELECT prod_name, prod_price
FROM Products
WHERE prod_price = 3.49;
-- 從Products 表中檢索兩個列,只返回 prod_price 值為 3.49 的行

【Hint】同時使用 ORDER BY 和 WHERE 子句時,ORDER BY 要位於 WHERE 之後。

【WHERE 子句操作符】

  

-- 列出所有價格小於 10 美元的商品:
SELECT prod_name, prod_price
FROM Products
WHERE prod_price < 10;

-- 列出所有不是供應商 DLL01 製造的產品:
SELECT vend_id, prod_name
FROM Products
WHERE vend_id <> 'DLL01';
-- 第二種寫法
SELECT vend_id, prod_name
FROM Products
WHERE vend_id != 'DLL01';

-- 檢索價格在 5 美元和 10 美元之間的所有產品:
SELECT prod_name, prod_price
FROM Products
WHERE prod_price BETWEEN 5 AND 10

-- 檢索沒有電子郵件的顧客:
SELECT cust_name, cust_email
FROM Customers
WHERE cust_email IS NULL
第5章 高階資料過濾

【AND、OR 操作符】

-- 檢索由供應商 DLL01 製造且價格小於等於 4 美元的所有產品的名稱和價格:
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;

-- 檢索任一個指定供應商製造的所有產品的名稱和價格:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01';

-- 檢索價格為 10 美元以上,且由 DLL01 或 BRS01 製造的所有產品:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
     AND prod_price >= 10;

【Hint】SQL 在處理 OR 操作符前,優先處理 AND 操作符
【Hint】在 WHERE 子句中使用圓括號:改變優先順序;明確操作順序,增強可讀性。

SELECT prod_name, prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01')
     AND prod_price >= 10;

【IN 操作符】用來指定條件範圍,範圍中的每個條件都可以進行匹配。

-- 檢索由供應商 DLL01 和 BRS01 製造的所有產品:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id IN ('DLL01', 'BRS01')
ORDER BY prod_name;
-- 用 IN 完成和 OR 同樣的操作
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
ORDER BY prod_name

【NOT 操作符】用來否定其後所跟的任何條件

-- 列出除 DLL01 之外的所有供應商製造的產品:
SELECT prod_name
FROM Products
WHERE NOT vend_id = 'DLL01'
ORDER BY prod_name;
-- another way : <>
SELECT prod_name
FROM Products
WHERE vend_id <> 'DLL01'
ORDER BY prod_name;

第6章 用萬用字元進行過濾(類似正則表示式匹配)

【LIKE操作符】用來匹配值的一部分的特殊字元,萬用字元搜尋只能用於文字欄位(字串),非文字資料型別欄位不能使用萬用字元搜尋

【百分號(%)萬用字元】任何字元出現任意次數

-- 找出所有以詞 Fish 起頭的產品
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE 'Fish%';

-- 搜尋包含文字 bean bag 的值
SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '%bean bag%';

-- 找出以 F 起頭、以 y 結尾的所有產品
SELECT prod_name
FROM Products 
WHERE prod_name LIKE 'F%y';

【下劃線(_)萬用字元】只匹配單個任意字元

SELECT prod_id, prod_name
FROM Products
WHERE prod_name LIKE '__ inch teddy bear';

【方括號([])萬用字元】用來匹配一個字符集,它必須匹配指定位置(萬用字元的位置)中的一個字元

-- 找出所有名字以 J 或 M 起頭的聯絡人
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[JM]%';
-- 匹配方括號中任意一個字元,也只能匹配單個字元。

-- 查詢匹配非 J 或 M 字元開頭的任意聯絡人名
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[^JM]%';
-- 通過字首字元 ^(脫字號)來否定
-- another way : NOT
SELECT cust_contact
FROM Customers
WHERE NOT cust_contact LIKE '[JM]%';

【Hint】萬用字元搜尋一般比前面討論的其它搜尋要耗費更長時間。
  所以:
  不要過度使用萬用字元。如果其它操作符能達到相同目的,應該使用其它操作符
  儘量不要講它們用在搜尋模式的開始處。把萬用字元置於開始處,搜尋起來是最慢的。
  注意萬用字元的位置

第7章 建立計算欄位

【計算欄位】
  儲存在資料庫表中的資料一般不是應用程式所需要的格式。我們需要直接從資料庫中檢索出轉換、計算或格式化過的資料,而不是檢索出資料,然後再在客戶機應用程式中重新格式化。
  計算欄位並不實際存在於資料庫表中。計算欄位是執行時在select語句內建立的。
  只有資料庫知道select語句中的哪些列是實際的表列,哪些列是計算欄位。從客戶機的角度來看,計算欄位的資料是以其他列的資料相同的方式返回的。

【拼接】將值聯結到一起(將一個值附加到另一個值)構成單個值

-- Vendors 表包含供應商名和地址資訊。假如要生成一個供應商報表,需要在格式化的名稱(位置)中列出供應商的位置。
SELECT vend_name + ' (' + vend_country + ')'
FROM Vendors
ORDER BY vend_name;

-- 去除空格、列別名
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors
ORDER BY vend_name;

【算數】:+-*/ (可用圓括號改變優先順序)

SELECT prod_id, quantity, item_price,
quantity * item_price AS expanded_price
FROM OrderItems
WHERE order_num = '20008'
第8章 使用資料處理函式

大多數SQL實現支援以下型別的函式:
  1)用於處理文字串(如刪除或填充值,轉換值為大寫或小寫)的文字函式。
  2)用於在數值資料上進行算術操作(如返回絕對值,進行代數運算)的數值函式。
  3)用於處理日期和時間值並從這些值中提取特定成份的日期和時間函式。
  4)返回DBMS正使用的特殊資訊的系統函式。

【文字處理函式】

-- 使用 UPPER() 函式--將文字轉換為大寫
SELECT vend_name, UPPER(vend_name) AS vend_name_upcase
FROM Vendors
ORDER BY vend_name;

常用的文字處理函式:
LEFT():返回字串左邊的字元
DATALENGTH():返回字串的長度
LOWER():將字串轉換為小寫
LTRIM():去掉字串左邊的空格
RTRIM():去掉字串右邊的空格
UPPER():將字串轉換為大寫

其他略

第9章  彙總資料

  使用聚集函式,SQL查詢可用於檢索資料,以便分析和報表生成。比如:確定表中行數,獲得表中行組的和,找出表列的最大、最小和平均值。

【聚集函式】執行在行組上,計算和返回單個值的函式。

  

【AVG】只能用來確定特定數值列的平均值,而且列名必須作為函式引數給出。為了獲得多個列的平均值,必須使用多個AVG()函式。

SELECT AVG(prod_price) AS avg_price
FROM Products
WHERE vend_id = 'DLL01';

【COUNT】確定表中行的數目或符合特定條件的行的數目。
有兩種使用方式:
  1)使用COUNT(*)對錶中行的數目進行計數,不管表列中包含的是空值還是非空值。
  2)使用COUNT(column)對特定列中具有值的行進行計數,忽略null值。

SELECT COUNT(*)  AS num_cust
FROM Customers;

【MAX】返回指定列中的最大值。MAX()要求指定列名。在用於文字資料時,如果資料按相應的列排序,則MAX()返回最後一行。它忽略列值為NULL的行。

SELECT MAX(prod_price) AS max_price
FROM Products;

【MIN】返回指定列的最小值。

【SUM】用來返回指定列值的和。它忽略值為null的行。

  利用標準的算術操作符,所有聚集函式都可用來執行多個列上的計算。

  對以上5個聚集函式都可以如下使用:
  對所有的行執行計算,指定ALL引數或不給引數;
  只包含不同的值,指定DISTINCT引數。

-- DISTINCT:平均值只考慮各個不同的價格
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM Products
WHERE vend_id = 'DLL01';

【組合聚合】

SELECT AVG(prod_price) AS avg_price
            COUNT(*) AS num_cust
        MAX(prod_price) AS max_price
FROM Products

第10章 分組資料

【GROUP BY】指示DBMS分組資料,然後對每個組而不是每個結果進行聚集。
  如果在GROUP BY子句中嵌套了分組,資料將在最後規定的分組上進行彙總。在建立分組時,指定的所有列都一起計算,所以不能從個別的列取回資料。
  GROUP BY子句中列出的每個列都必須是檢索列或有效的表示式(但不能是聚集函式)。如果在select中使用表示式,則必須在group by子句中指定相同的表示式,不能使用別名。
  大多數SQL實現不允許GROUP BY列帶有長度可變的資料型別。
  除聚集計算語句外,select語句中的每個列都必須在GROUP BY子句中給出。
  如果分組列中具有NULL值,則NULL將作為一個分組返回。如果列中有多行NULL值,它們將分為一組。
  GROUP BY子句必須出現在WHERE子句之後,ORDER BY子句之前。

SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;

  

【過濾分組】規定包括哪些分組,排除哪些分組。所有型別的WHERE子句都可以用HAVING來替代。唯一的差別是WHERE過濾行,而HAVING過濾分組。

SELECT cust_id, COUNT(*) AS orders
FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;

  WHERE在資料分組前進行過濾,HAVING在資料分組後進行過濾。WHERE排除的行不包括在分組中,這可能改變計算值,從而影響HAVING子句中基於這些值過濾掉的分組。
  應該僅在與GROUP BY子句結合時才使用HAVING,而WHERE子句用於標準的行級過濾。

【分組和排序】不要忘記ORDER BY
  一般在使用GROUP BY 子句時,應該也給出ORDER BY 子句。這是保證資料正確排序的唯一方法。千萬不要僅依賴GROUP BY 排序資料。

  

【SELECT子句順序】