sql 指令


 

SELECT

 

 

是用來做什麼的呢?一個最常用的方式是將資料從數據庫中的表格內選出。從這一句回答中,我們馬上可以看到兩個關鍵字:從 (FROM)數據庫中的表格內選出 (SELECT)。(表格是一個數據庫內的結構,它的目的是儲存資料。在表格處理這一部分中,我們會提到如何使用 SQL 來設定表格。) 我們由這裏可以看到最基本的 SQL 架構:

 

SELECT "欄位名"FROM "表格名"

 

我們用以下的例子來看看實際上是怎麼用的。假設我們有以下這個表格:

 

 

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

 

 

若要選出所有的店名(store_Name),我們就打入:

 

SELECT store_name FROM Store_Information

 

結果:

store_name

Los Angeles

San Diego

Los Angeles

Boston

 

我們一次可以讀取好幾個欄位,也可以同時由好幾個表格中選資料。

 

簡單的SQL查詢只包括選擇列表、FROM子句和WHERE子句。它們分別說明所查詢列、查詢的表或視圖、以及搜索條件等。

1、選擇所有列
例如,下面語句顯示testtable表中所有列的數據:

代碼:SELECT * FROMtesttable

 

2、選擇部分列並指定它們的顯示次序查詢結果集合中數據的排列順序與選擇列表中所指定的列名排列順序相同。例如:
代碼:SELECT nickname,email FROMtesttable

 

3、更改列標題
在選擇列表中,可重新指定列標題。定義格式爲:列標題=列名

如果指定的列標題不是標準的標識符格式時,應使用引號定界符,例如,下列語句使用漢字顯示列標題:
代碼:SELECT 暱稱=nickname,電子郵件=email  FROM testtable

 

4、刪除重複行
SELECT語句中使用ALL或DISTINCT選項來顯示錶中符合條件的所有行或刪除其中重複的數據行,默認爲ALL。使用DISTINCT選項時,對於所有重複的數據行在SELECT返回的結果集合中只保留一行。


5、限制返回的行數
使用TOP n [PERCENT]選項限制返回的數據行數,TOP n說明返回n行,而TOP n PERCENT時,說明n是表示一百分數,指定返回的行數等於總行數的百分之幾。例如:
代碼:SELECT TOP 2 * FROM `testtable`
代碼:SELECT TOP 20 PERCENT* FROM `testtable`

 

 

DISTINCT

 

SELECT 指令讓我們能夠讀取表格中一個或數個欄位的所有資料。這將把所有的資料都抓出,無論資料值有無重複。在資料處理中,我們會經常碰到需要找出表格內的不同資料值的情況。換句話說,我們需要知道這個表格/欄位內有哪些不同的值,而每個值出現的次數並不重要。這要如何達成呢?在 SQL 中,這是很容易做到的。我們只要在 SELECT 後加上一個 DISTINCT 就可以了。DISTINCT 的語法如下:

 

SELECT DISTINCT"欄位名"

FROM "表格名"

 

舉例來說,若要在以下的表格,Store_Information,找出所有不同的店名時,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

 

SELECT DISTINCT store_name FROM Store_Information

 

結果:

store_name

Los Angeles

San Diego

Boston

 

WHERE

 

我們並不一定每一次都要將表格內的資料都完全抓出。在許多時候,我們會需要選擇性地抓資料。就我們的例子來說,我們可能只要抓出營業額超過 $1,000 的資料。要做到這一點,我們就需要用到 WHERE 這個指令。這個指令的語法如下:

 

 

SELECT "欄位名"

FROM "表格名"

WHERE "條件"

 

比較運算符(大小比較):>、>=、=、<、<=、!<、!>、!=

 

例:返回96年1月的定單
SELECT orderID, CustomerID, orderDate
FROM orders
WHERE orderDate〉#1/1/96#AND orderDate〈#1/30/96#
注意:
Mcirosoft JET SQL 中,日期用‘#’定界。日期也可以用Datevalue()函數來代替。在比較字符型的數據時,要加上單引號’’,尾空格在比較中被忽略。
例:
WHERE orderDate〉#96-1-1#
也可以表示爲:
WHERE orderDate〉Datevalue(‘1/1/96’)

 

 

若我們要由以下的表格抓出營業額超過 $1,000 的資料,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

 

我們就鍵入,

 

 

SELECT store_name

FROM Store_Information

WHERE Sales > 1000

 

結果:

 

store_name

Los Angeles

 

ANDOR

 

在上一頁中,我們看到 WHERE 指令可以被用來由表格中有條件地選取資料。 這個條件可能是簡單的 (像上一頁的例子),也可能是複雜的。複雜條件是由二或多個簡單條件透過 AND 或是 OR的連接而成。一個 SQL 語句中可以有無限多個簡單條件的存在。

 

複雜條件的語法如下:

 

SELECT "欄位名"

FROM "表格名"

WHERE "簡單條件"

{[AND|OR] "簡單條件"}+

 

{}+ 代表{}之內的情況會發生一或多次。在這裏的意思就是 AND 加簡單條件及 OR 加簡單條件的情況可以發生一或多次。另外,我們可以用 () 來代表條件的先後次序。

 

舉例來說,我們若要在 Store_Information 表格中選出所有 Sales 高於 $1,000或是 Sales 在 $500 及 $275 之間的資料的話,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

San Francisco

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

SELECT store_name

FROM Store_Information

WHERE Sales > 1000

OR (Sales < 500 ANDSales > 275)

 

結果:

 

store_name

Los Angeles

San Francisco

 

IN

 

在 SQL 中,在兩個情況下會用到IN 這個指令;這一頁將介紹其中之一:與 WHERE 有關的那一個情況。在這個用法下,我們事先已知道至少一個我們需要的值,而我們將這些知道的值都放入 IN 這個子句。 IN 指令的語法爲下:

 

SELECT "欄位名"

FROM "表格名"

WHERE "欄位名"IN ('值一', '值二', ...)

 

在括號內可以有一或多個值,而不同值之間由逗點分開。值可以是數目或是文字。若在括號內只有一個值,那這個子句就等於

 

WHERE "欄位名"= '值一'

 

舉例來說,若我們要在 Store_Information 表格中找出所有含蓋 Los Angeles 或 SanDiego 的資料,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

San Francisco

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

SELECT *

FROM Store_Information

WHERE store_name IN ('Los Angeles', 'San Diego')

 

結果:

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

 

BETWEEN

 

IN 這個指令可以讓我們依照一或數個不連續 (discrete) 的值的限制之內抓出資料庫中的值,而 BETWEEN 則是讓我們可以運用一個範圍 (range) 內抓出資料庫中的值。BETWEEN這個子句的語法如下:

 

SELECT "欄位名"

FROM "表格名"

WHERE "欄位名"BETWEEN '值一' AND '值二'

 

這將選出欄位值包含在值一及值二之間的每一筆資料。

 

舉例來說,若我們要由 Store_Information 表格中找出所有介於 January 6, 1999 及 January10, 1999 中的資料,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

San Francisco

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

SELECT *

FROM Store_Information

WHERE Date BETWEEN 'Jan-06-1999' AND'Jan-10-1999'

 

請讀者注意:在不同的數據庫中,日期的儲存法可能會有所不同。在這裏我們選擇了其中一種儲存法。

 

結果:

store_name

Sales

Date

San Diego

$250

Jan-07-1999

San Francisco

$300

Jan-08-1999

Boston

$700

Jan-08-1999

 

LIKE

 

LIKE 是另一個在 WHERE 子句中會用到的指令。基本上, LIKE 能讓我們依據一個模式 (pattern) 來找出我們要的資料。相對來說,在運用 IN 的時候,我們完全地知道我們需要的條件;在運用 BETWEEN 的時候,我們則是列出一個範圍。 LIKE 的語法如下:

 

SELECT "欄位名"

FROM "表格名"

WHERE "欄位名"LIKE {模式}

 

LIKE運算符裏使用的通配符
通配符含義
?任何一個單一的字符
* 任意長度的字符
# 0~9之間的單一數字
[字符列表]在字符列表裏的任一值
[!字符列表] 不在字符列表裏的任一值
- 指定字符範圍,兩邊的值分別爲其上下限

{模式} 經常包括野卡 (wildcard). 以下是幾個例子:

 

'A_Z': 所有以 'A' 起頭,另一個任何值的字原,且以 'Z' 爲結尾的字符串。'ABZ' 和 'A2Z' 都符合這一個模式,而'AKKZ' 並不符合 (因爲在 A 和 Z 之間有兩個字原,而不是一個字原)。

 

'ABC%': 所有以 'ABC' 起頭的字符串。舉例來說,'ABCD' 和'ABCABC' 都符合這個模式。

 

'%XYZ': 所有以 'XYZ' 結尾的字符串。舉例來說,'WXYZ' 和 'ZZXYZ'都符合這個模式。

 

'%AN%': 所有含有 'AN'這個模式的字符串。舉例來說, 'LOS ANGELES' 和 'SANFRANCISCO' 都符合這個模式。

我們將以上最後一個例子用在我們的 Store_Information 表格上:

 

Store_Information 表格

store_name

Sales

Date

LOS ANGELES

$1500

Jan-05-1999

SAN DIEGO

$250

Jan-07-1999

SAN FRANCISCO

$300

Jan-08-1999

BOSTON

$700

Jan-08-1999

我們就鍵入,

 

SELECT *

FROM Store_Information

WHERE store_name LIKE '%AN%'

 

結果:

store_name

Sales

Date

LOS ANGELES

$1500

Jan-05-1999

SAN FRANCISCO

$300

Jan-08-1999

SAN DIEGO

$250

Jan-07-1999

 

 

ODERBY

 

到目前爲止,我們已學到如何藉由 SELECT WHERE 這兩個指令將資料由表格中抓出。不過我們尚未提到這些資料要如何排列。這其實是一個很重要的問題。事實上,我們經常需要能夠將抓出的資料做一個有系統的顯示。這可能是由小往大 (ASCENDing) 或是由大往小(DESCENDing)。在這種情況下,我們就可以運用 ODER BY 這個指令來達到我們的目的。

 

ODER BY 的語法如下:

 

SELECT "欄位名"

FROM "表格名"

[WHERE "條件"]

ODER BY "欄位名"[ASC, DESC]

 

[] 代表 WHERE 子句不是一定需要的。不過,如果 WHERE 子句存在的話,它是在ODER BY 子句之前。 ASC 代表結果會以由小往大的順序列出,而 DESC 代表結果會以由大往小的順序列出。如果兩者皆沒有被寫出的話,那我們就會用 ASC

 

我們可以照好幾個不同的欄位來排順序。在這個情況下, ODER BY 子句的語法如下(假設有兩個欄位):

 

ODER BY "欄位一"[ASC, DESC],"欄位二" [ASC, DESC]

 

若我們對這兩個欄位都選擇由小往大的話,那這個子句就會造成結果是依據 "欄位一"由小往大排。若有好幾筆資料 "欄位一"的值相等,那這幾筆資料就依據 "欄位二"由小往大排。

 

舉例來說,若我們要依照 Sales 欄位的由大往小列出Store_Information 表格中的資料,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

San Francisco

$300

an-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

SELECT store_name, Sales, Date

FROM Store_Information

ODER BY Sales DESC

 

結果:

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

Boston

$700

Jan-08-1999

San Francisco

$300

Jan-08-1999

San Diego

$250

Jan-07-1999

在以上的例子中,我們用欄位名來指定排列順序的依據。除了欄位名外,我們也可以用欄位的順序 (依據 SQL 句中的順序)。在 SELECT 後的第一個欄位爲 1,第二個欄位爲 2,以此類推。在上面這個例子中,我們用以下這句 SQL 可以達到完全一樣的效果:

 

SELECT store_name, Sales, Date

FROM Store_Information

ODER BY 2 DESC

 

 

函數

 

既然數據庫中有許多資料都是已數字的型態存在,一個很重要的用途就是要能夠對這些數字做一些運算,例如將它們總合起來,或是找出它們的平均值。SQL 有提供一些這一類的函數。它們是:

 

AVG (平均)

COUNT (計數)

MAX (最大值)

MIN (最小值)

SUM (總合)

VAR (方差)
STDEV (標準誤差)
FIRST (第一個值)
LAST (最後一個值)

運用函數的語法是:

 

SELECT "函數名"("欄位名")

FROM "表格名"

 

舉例來說,若我們要由我們的範例表格中求出 Sales 欄位的總合,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

SELECT SUM(Sales) FROM Store_Information

 

結果:

 

SUM(Sales)

$2750

 

$2750 代表所有 Sales 欄位的總合: $1500 + $250 + $300 + $700.

 

除了函數的運用外,SQL 也可以做簡單的數學運算,例如加(+)和減(-)。對於文字類的資料,SQL也有好幾個文字處理方面的函數,例如文字相連 (concatenation),文字修整(trim),以及子字符串 (substring)。不同的數據庫對這些函數有不同的語法,所以最好是參考您所用數據庫的信息,來確定在那個數據庫中,這些函數是如何被運用的。

 

COUNT

 

在上一頁有提到, COUNT 是函數之一。由於它的使用廣泛,我們在這裏特別提出來討論。基本上, COUNT 讓我們能夠數出在表格中有多少筆資料被選出來。它的語法是:

 

SELECT COUNT("欄位名")

FROM "表格名"

 

 

舉例來說,若我們要找出我們的範例表格中有幾筆 store_name 欄不是空白的資料時,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

 

SELECT COUNT(store_name)

FROM Store_Information

WHERE store_name is not NULL

 

結果:

 

Count(store_name)

4

 

 

"is not NULL" 是 "這個欄位不是空白"的意思。

 

COUNT 和 DISTINCT 經常被合起來使用,目的是找出表格中有多少筆不同的資料 (至於這些資料實際上是什麼並不重要)。舉例來說,如果我們要找出我們的表格中有多少個不同的 store_name,我們就鍵入,

 

SELECT COUNT(DISTINCT store_name)

FROM Store_Information

 

結果:

 

Count(DISTINCTstore_name)

3

 

 

GROUP BY

 

我們現在回到函數上。記得我們用 SUM 這個指令來算出所有的 Sales (營業額)吧!如果我們的需求變成是要算出每一間店 (store_name) 的營業額 (sales),那怎麼辦呢?在這個情況下,我們要做到兩件事:第一,我們對於 store_name 及 Sales 這兩個欄位都要選出。第二,我們需要確認所有的 sales 都要依照各個store_name 來分開算。這個語法爲:

 

SELECT "欄位1",SUM("欄位2")

FROM "表格名"

GROUP BY "欄位1"

 

在我們的範例上,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們就鍵入,

 

 

SELECT store_name, SUM(Sales)

FROM Store_Information

GROUP BY store_name

 

結果:

 

store_name  SUM(Sales)

Los Angeles $1800

San Diego   $250

Boston      $700

 

 

當我們選不只一個欄位,且其中至少一個欄位有包含函數的運用時,我們就需要用到 GROUP BY 這個指令。在這個情況下,我們需要確定我們有 GROUP BY 所有其他的欄位。換句話說,除了有包括函數的欄位外,我們都需要將其放在 GROUP BY 的子句中。

 

HAVING

 

那我們如何對函數產生的值來設定條件呢?舉例來說,我們可能只需要知道哪些店的營業額有超過 $1,500。在這個情況下,我們不能使用 WHERE 的指令。那要怎麼辦呢?很幸運地,SQL 有提供一個 HAVING 的指令,而我們就可以用這個指令來達到這個目標。 HAVING 子句通常是在一個 SQL 句子的最後。一個含有HAVING 子句的 SQL 並不一定要包含 GROUP BY 子句。HAVING 的語法如下:

 

SELECT "欄位1",SUM("欄位2")

FROM "表格名"

GROUP BY "欄位1"

HAVING (函數條件)

 

請讀者注意: 如果被 SELECT 的只有函數欄, 那就不需要 GROUP BY 子句。

 

在我們 Store_Information 表格這個例子中,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

若我們要找出 Sales 大於 $1,500的 store_name,我們就鍵入,

 

 

SELECT store_name, SUM(sales)

FROM Store_Information

GROUP BY store_name

HAVING SUM(sales) > 1500

 

結果:

 

store_name SUM(Sales)

Los Angeles $1800

 

 

ALIAS

 

接下來,我們討論 alias (別名) 在 SQL 上的用處。最常用到的別名有兩種:欄位別名及表格別名。

 

簡單地來說,欄位別名的目的是爲了讓 SQL 產生的結果易讀。在之前的例子中,每當我們有營業額總合時,欄位名都是 SUM(sales)。雖然在這個情況下沒有什麼問題,可是如果這個欄位不是一個簡單的總合,而是一個複雜的計算,那欄位名就沒有這麼易懂了。若我們用欄位別名的話,就可以確認結果中的欄位名是簡單易懂的。

 

第二種別名是表格別名。要給一個表格取一個別名,只要在 FROM 子句中的表格名後空一格,然後再列出要用的表格別名就可以了。這在我們要用 SQL 由數個不同的表格中獲取資料時是很方便的。這一點我們在之後談到連接 (join) 時會看到。

 

我們先來看一下欄位別名和表格別名的語法:

 

SELECT "表格別名"."欄位1" "欄位別名"

FROM "表格名""表格別名"

 

或者:

 

SELECT "表格名"AS "表格別名"

 

基本上,這兩種別名都是放在它們要替代的物件後面,而它們中間由一個空白分開。我們繼續使用 Store_Information 這個表格來做例子:

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

我們用跟 SQL GROUP BY 那一頁一樣的例子。這裏的不同處是我們加上了欄位別名以及表格別名:

 

SELECT A1.store_name Store, SUM(A1.Sales) "Total Sales"

FROM Store_Information A1

GROUP BY A1.store_name

 

結果:

 

Store      Total Sales

Los Angeles $1800

San Diego  $250

Boston     $700

 

 

在結果中,資料本身沒有不同。不同的是欄位的標題。這是運用欄位別名的結果。在第二個欄位上,原本我們的標題是 "Sum(Sales)",而現在我們有一個很清楚的 "Total Sales"。很明顯地, "Total Sales" 能夠比 "Sum(Sales)" 更精確地闡述這個欄位的含意。用表格別名的好處在這裏並沒有顯現出來,不過這在 下一頁就會很清楚了。

 

 

表格鏈接

 

現在我們介紹連接(join)的概念。要了解連接,我們需要用到許多我們之前已介紹過的指令。我們先假設我們有以下的兩個表格,

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Geography 表格

region_name

store_name

East

Boston

East

New York

West

Los Angeles

West

San Diego

而我們要知道每一區 (region_name) 的營業額(sales)。 Geography 這個表格告訴我們每一區有哪些店,而 Store_Information 告訴我們每一個店的營業額。若我們要知道每一區的營業額,我們需要將這兩個不同表格中的資料串聯起來。當我們仔細瞭解這兩個表格後,我們會發現它們可經由一個相同的欄位,store_name,連接起來。我們先將SQL 句列出,之後再討論每一個子句的意義:

 

SELECT A1.region_name REGION, SUM(A2.Sales) SALES

FROM Geography A1, Store_Information A2

WHERE A1.store_name = A2.store_name

GROUP BY A1.region_name

 

結果:

 

REGION SALES

East     $700

West     $2050

 

 

在第一行中,我們告訴 SQL 去選出兩個欄位:第一個欄位是Geography 表格中的 region_name 欄位 (我們取了一個別名叫做 REGION);第二個欄位是 Store_Information 表格中的 sales 欄位 (別名爲 SALES)。請注意在這裏我們有用到表格別名:Geography 表格的別名是 A1,Store_Information 表格的別名是 A2。若我們沒有用表格別名的話,第一行就會變成

 

SELECT Geography.region_name REGION, SUM(Store_Information.Sales) SALES

 

 

很明顯地,這就複雜多了。在這裏我們可以看到表格別名的功用:它能讓 SQL 句容易被瞭解,尤其是這個 SQL 句含蓋好幾個不同的表格時。

 

接下來我們看第三行,就是 WHERE 子句。這是我們闡述連接條件的地方。在這裏,我們要確認 Geography 表格中store_name 欄位的值與 Store_Information 表格中 store_name 欄位的值是相等的。這個 WHERE 子句是一個連接的靈魂人物,因爲它的角色是確定兩個表格之間的連接是正確的。如果 WHERE 子句是錯誤的,我們就極可能得到一個笛卡兒連接 (Cartesian join)。笛卡兒連接會造成我們得到所有兩個表格每兩行之間所有可能的組合。在這個例子中,笛卡兒連接會讓我們得到 4 x 4 = 16 行的結果。

 

 

外部鏈接

 

之前我們看到的左連接 (left join),又稱內部連接(inner join)。在這個情況下,要兩個表格內都有同樣的值,那一筆資料纔會被選出。那如果我們想要列出一個表格中每一筆的資料,無論它的值在另一個表格中有沒有出現,那該怎麼辦呢?在這個時候,我們就需要用到 SQL OUTER JOIN (外部連接) 的指令。

 

外部連接的語法是依數據庫的不同而有所不同的。舉例來說,在 Oracle 上,我們會在 WHERE 子句中要選出所有資料的那個表格之後加上一個"(+)" 來代表說這個表格中的所有資料我們都要。

 

假設我們有以下的兩個表格:

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Geography 表格

region_name

store_name

East

Boston

East

New York

West

Los Angeles

West

San Diego

我們需要知道每一間店的營業額。如果我們用一個普通的連接,我們將會漏失掉 'New York'這個店,因爲它並不存在於 Store_Information 這個表格。所以,在這個情況下,我們需要用外部連接來串聯這兩個表格:

 

SELECT A1.store_name, SUM(A2.Sales) SALES

FROM Georgraphy A1, Store_Information A2

WHERE A1.store_name = A2.store_name (+)

GROUP BY A1.store_name

 

我們在這裏是使用了 Oracle 的外部連接語法。

 

結果:

 

store_name  SALES

Boston      $700

New York 

Los Angeles  $1800

San Diego    $250

 

 

請注意: 當第二個表格沒有相對的資料時, SQL 會傳回 NULL 值。在這一個例子中, 'New York' 並不存在於Store_Information 表格,所以它的 "SALES" 欄位是 NULL.

 

CONCATENATE

 

有的時候,我們有需要將由不同欄位獲得的資料串連在一起。每一種數據庫都有提供方法來達到這個目的:

 

MySQL: CONCAT()

Oracle: CONCAT(), ||

SQL Server: +

CONCAT() 的語法如下:

 

CONCAT(字符串1, 字符串2, 字符串3, ...): 將字符串1、字符串2、字符串3,等字符串連在一起。請注意,Oracle的CONCAT()只允許兩個參數;換言之,一次只能將兩個字符串串連起來。不過,在Oracle中,我們可以用'||'來一次串連多個字符串。

 

來看一個例子。假設我們有以下的表格:

 

Geography 表格

region_name

store_name

East

Boston

East

New York

West

Los Angeles

West

San Diego

例子1:

 

MySQL/Oracle:

SELECT CONCAT(region_name,store_name) FROMGeography

WHERE store_name = 'Boston';

 

結果:

 

'EastBoston'

 

例子2:

 

Oracle:

SELECT region_name || ' ' || store_name FROMGeography

WHERE store_name = 'Boston';

 

結果:

 

'East Boston'

 

例子3:

 

SQL Server:

SELECT region_name + ' ' + store_name FROMGeography

WHERE store_name = 'Boston';

 

結果:

 

'East Boston'

 

 

SUBSTRING

 

SQL 中的 substring 函數是用來抓出一個欄位資料中的其中一部分。這個函數的名稱在不同的數據庫中不完全一樣:

 

MySQL: SUBSTR(), SUBSTRING()

Oracle: SUBSTR()

SQL Server: SUBSTRING()

最常用到的方式如下 (在這裏我們用SUBSTR()爲例):

 

SUBSTR(str,pos): 由<str>中,選出所有從第<pos>位置開始的字符。請注意,這個語法不適用於SQL Server上。

 

SUBSTR(str,pos,len): 由<str>中的第<pos>位置開始,選出接下去的<len>個字符。

 

假設我們有以下的表格:

 

Geography 表格

region_name

store_name

East

Boston

East

New York

West

Los Angeles

West

San Diego

例1:

 

SELECT SUBSTR(store_name, 3)

FROM Geography

WHERE store_name = 'Los Angeles';

 

結果:

 

's Angeles'

 

例2:

 

SELECT SUBSTR(store_name,2,4)

FROM Geography

WHERE store_name = 'San Diego';

 

結果:

 

'an D'

 

進階SQL

 

 

在這一部分,我們將介紹以下的 SQL 概念及關鍵字:

 

SQL UNION

SQL UNION ALL

SQL INTERSECT

SQLMINUS

SQLSubquery

SQLEXISTS

SQL CASE

 

我們並介紹如何用 SQL 來做出以下的運算:

 

排名 (Rank)

中位數 (Median)

累積總計 (Running Total)

總合百分比 (Percent to Total)

累積總合百分比 (Cumulative Percent to Total)

 

 

UNION

 

UNION 指令的目的是將兩個 SQL 語句的結果合併起來。從這個角度來看, UNION 跟 JOIN 有些許類似,因爲這兩個指令都可以由多個表格中擷取資料。 UNION 的一個限制是兩個 SQL 語句所產生的欄位需要是同樣的資料種類。另外,當我們用 UNION 這個指令時,我們只會看到不同的資料值 (類似 SELECT DISTINCT)。

 

UNION 的語法如下:

 

[SQL 語句 1]

UNION

[SQL 語句 2]

 

假設我們有以下的兩個表格,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Internet_Sales 表格

Date

Sales

Jan-07-1999

$250

Jan-10-1999

$535

Jan-11-1999

$320

Jan-12-1999

$750

而我們要找出來所有有營業額 (sales) 的日子。要達到這個目的,我們用以下的 SQL 語句:

 

SELECT Date FROM Store_Information

UNION

SELECT Date FROM Internet_Sales

 

結果:

 

Date

Jan-05-1999

Jan-07-1999

Jan-08-1999

Jan-10-1999

Jan-11-1999

Jan-12-1999

 

 

有一點值得注意的是,如果我們在任何一個 SQL 語句 (或是兩句都一起) 用 "SELECT DISTINCTDate" 的話,那我們會得到完全一樣的結果。

 

 

UNION ALL

 

 

UNION ALL 這個指令的目的也是要將兩個 SQL 語句的結果合併在一起。UNION ALL 和 UNION 不同之處在於 UNION ALL 會將每一筆符合條件的資料都列出來,無論資料值有無重複。

 

UNION ALL 的語法如下:

 

[SQL 語句 1]

UNION ALL

[SQL 語句 2]

 

我們用和上一頁同樣的例子來顯示出UNION ALL 和 UNION 的不同。同樣假設我們有以下兩個表格,

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Internet_Sales 表格

Date

Sales

Jan-07-1999

$250

Jan-10-1999

$535

Jan-11-1999

$320

Jan-12-1999

$750

而我們要找出有店面營業額以及網絡營業額的日子。要達到這個目的,我們用以下的 SQL 語句:

 

SELECT Date FROM Store_Information

UNION ALL

SELECT Date FROM Internet_Sales

 

結果:

 

Date

Jan-05-1999

Jan-07-1999

Jan-08-1999

Jan-08-1999

Jan-07-1999

Jan-10-1999

Jan-11-1999

Jan-12-1999

 

 

 

INTERSECT

 

 

UNION 指令類似,INTERSECT 也是對兩個 SQL 語句所產生的結果做處理的。不同的地方是, UNION 基本上是一個 OR (如果這個值存在於第一句或是第二句,它就會被選出),而 INTERSECT則比較像 AND (這個值要存在於第一句和第二句纔會被選出)。 UNION是聯集,而 INTERSECT 是交集。

 

INTERSECT 的語法如下:

 

[SQL 語句 1]

INTERSECT

[SQL 語句 2]

 

假設我們有以下的兩個表格,

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Internet_Sales 表格

Date

Sales

Jan-07-1999

$250

Jan-10-1999

$535

Jan-11-1999

$320

Jan-12-1999

$750

而我們要找出哪幾天有店面交易和網絡交易。要達到這個目的,我們用以下的 SQL 語句:

 

SELECT Date FROM Store_Information

INTERSECT

SELECT Date FROM Internet_Sales

 

結果:

 

Date

Jan-07-1999

 

 

請注意,在 INTERSECT 指令下,不同的值只會被列出一次。

 

 

MINUS

 

 

MINUS 指令是運用在兩個 SQL 語句上。它先找出第一個SQL 語句所產生的結果,然後看這些結果有沒有在第二個 SQL 語句的結果中。如果有的話,那這一筆資料就被去除,而不會在最後的結果中出現。如果第二個 SQL 語句所產生的結果並沒有存在於第一個 SQL 語句所產生的結果內,那這筆資料就被拋棄。

 

MINUS 的語法如下:

 

[SQL 語句 1]

MINUS

[SQL 語句 2]

 

我們繼續使用一樣的例子:

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

 

 Internet_Sales 表格

Date

Sales

Jan-07-1999

$250

Jan-10-1999

$535

Jan-11-1999

$320

Jan-12-1999

$750

而我們要知道有哪幾天是有店面營業額而沒有網絡營業額的。要達到這個目的,我們用以下的 SQL 語句:

 

SELECT Date FROM Store_Information

MINUS

SELECT Date FROM Internet_Sales

 

結果:

 

Date

Jan-05-1999

Jan-08-1999

 

 

"Jan-05-1999","Jan-07-1999", AND"Jan-08-1999" 是 "SELECTDate FROM Store_Information" 所產生的結果。在這裏面, "Jan-07-1999" 是存在於 "SELECT Date FROMInternet_Sales" 所產生的結果中。因此"Jan-07-1999" 並不在最後的結果中。

 

請注意,在 MINUS 指令下,不同的值只會被列出一次。

 

 

子查詢

 

我們可以在一個 SQL 語句中放入另一個SQL 語句。當我們在 WHERE 子句或 HAVING 子句中插入另一個SQL 語句時,我們就有一個子查詢 (subquery) 的架構。 子查詢的作用是什麼呢?第一,它可以被用來連接表格。另外,有的時候子查詢是唯一能夠連接兩個表格的方式。

 

子查詢的語法如下:

 

SELECT "欄位1"

FROM "表格"

WHERE "欄位2"[比較運算素]

(SELECT "欄位1"

FROM "表格"

WHERE [條件])

 

[比較運算素] 可以是相等的運算素,例如 =, >, <, >=, <=. 這也可以是一個對文字的運算素,例如 "LIKE"。綠色的部分代表外查詢,紅色的部分代表內查詢。

 

我們就用剛剛在闡述 SQL 連接時用過的例子:

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Geography 表格

region_name

store_name

East

Boston

East

New York

West

Los Angeles

West

San Diego

我們要運用 subquery 來找出所有在西部的店的營業額。我們可以用下面的 SQL 來達到我們的目的:

 

SELECT SUM(Sales) FROM Store_Information

WHERE Store_name IN

(SELECTstore_name FROM Geography

WHERE region_name = 'West')

 

結果:

 

SUM(Sales)

2050

 

 

在這個例子中,我們並沒有直接將兩個表格連接起來,然後由此直接算出每一間西區店面的營業額。我們做的是先找出哪些店是在西區的,然後再算出這些店的營業額總共是多少。

 

在以上的例子,內部查詢本身與外部查詢沒有關係。這一類的子查詢稱爲『簡單子查詢』 (Simple Subquery)。如果內部查詢是要利用到外部查詢提到的表格中的欄位,那這個字查詢就被稱爲『相關子查詢』 (Correlated Subquery)。以下是一個相關子查詢的例子:

 

SELECT SUM(a1.Sales) FROMStore_Information a1

WHERE a1.Store_name IN

(SELECTstore_name FROM Geography a2

WHERE a2.store_name = a1.store_name)

 

紅色部分即是外部查詢提到的表格中的欄位。

 

 

EXISTS

 

在上一頁中,我們用 IN 來連接內查詢和外查詢。另外有數個方式,例如 >, <, 及 =,都可以用來連接內查詢和外查詢。 EXISTS 也是其中一種方式。這一頁我們將討論 EXISTS 的用法。

 

基本上, EXISTS 是用來測試內查詢有沒有產生任何結果。如果有的話,系統就會執行外查詢中的 SQL。若是沒有的話,那整個SQL 語句就不會產生任何結果。

 

EXISTS 的語法是:

 

SELECT "欄位1"

FROM "表格1"

WHERE EXISTS

(SELECT *

FROM "表格2"

WHERE [條件])

 

在內查詢中,我們並不一定要用 * 來選出所有的欄位。我們也可以選擇表格2中的任何欄位。這兩種做法最後的結果是一樣的。

 

來看一個例子。假設我們有以下的兩個表格:

 

Store_Information 表格

store_name

Sales

Date

Los Angeles

$1500

Jan-05-1999

San Diego

$250

Jan-07-1999

Los Angeles

$300

Jan-08-1999

Boston

$700

Jan-08-1999

Geography 表格

region_name

store_name

East

Boston

East

New York

West

Los Angeles

West

San Diego

而我們打入的 SQL 是:

 

SELECT SUM(Sales) FROM Store_Information

WHERE EXISTS

(SELECT * FROM Geography

WHERE region_name = 'West')

 

我們會得到以下的答案:

 

SUM(Sales)

2750

 

 

乍看之下,這個答案似乎不太正確,因爲內查詢有包含一個 [region_name = 'West'] 的條件,可是最後的答案並沒有包含這個條件。實際上,這並沒有問題。在這個例子中,內查詢產生了超過一筆的資料,所以 EXISTS 的條件成立,所以外查詢被執行。而外查詢本身並沒有包含 [region_name = 'West'] 這個條件。

 

 

 

CASE

 

 

 

CASE 是 SQL 用來做爲 IF-THEN-ELSE 之類邏輯的關鍵字。 CASE 的語法如下:

 

SELECT CASE ("欄位名")

  WHEN "條件1" THEN "結果1"

  WHEN "條件2" THEN "結果2"

  ...

  [ELSE "結果N"]

  END

FROM "表格名"

 

 

"條件" 可以是一個數值或是公式。 ELSE 子句則並不是必須的。

 

在我們的 Store_Information 中

 

Store_Information 表格

store_name    Sales  Date

Los Angeles   $1500 Jan-05-1999

San Diego     $250  Jan-07-1999

San Francisco  $300  Jan-08-1999

Boston       $700   Jan-08-1999

 

 

若我們要將 'Los Angeles' 的 Sales 數值乘以2,以及將 'San Diego' 的 Sales 數值乘以1.5,我們就鍵入以下的 SQL:

 

SELECT store_name, CASE store_name

  WHEN 'Los Angeles' THENSales * 2

  WHEN 'San Diego' THENSales * 1.5

  ELSE Sales

  END

"New Sales",

Date

FROM Store_Information

 

 

"New Sales" 是用到 CASE 那個欄位的欄位名。

 

結果:

store_name

New Sales

Date

Los Angeles

$3000

Jan-05-1999

San Diego

$375

Jan-07-1999

San Francisco

$300

Jan-08-1999

Boston

$700

Jan-08-1999

 

 

算排名

 

列出每一行的排名是一個常見的需求,可惜 SQL 並沒有一個很直接的方式達到這個需求。要以 SQL 列出排名,基本的概念是要做一個表格自我連結 (self join),將結果依序列出,然後算出每一行之前 (包含那一行本身) 有多少行數。這樣講讀者聽得可能有點困惑,所以最好的方式是用一個實例來介紹。假設我們有以下的表格:

 

 

 

Total_Sales 表格

Name

Sales

John

10

Jennifer

15

Stella

20

Sophia

40

Greg

50

Jeff

20

要找出每一行的排名,我們就打入以下的 SQL 語句:

 

SELECT a1.Name, a1.Sales, COUNT(a2.sales) Sales_Rank

FROM Total_Sales a1, Total_Sales a2

WHERE a1.Sales <= a2.Sales OR(a1.Sales=a2.Sales AND a1.Name = a2.Name)

GROUP BY a1.Name, a1.Sales

ODER BY a1.Sales DESC, a1.Name DESC;

 

結果:

Name    Sales   Sales_Rank

Greg     50       1

Sophia    40       2

Stella     20       3

Jeff      20       3

Jennifer   15       5

John      10       6

 

我們先來看 WHERE 子句。在字句的第一部分(a1.Sales <= a2.Sales),我們算出有多少筆資料Sales 欄位的值是比自己本身的值小或是相等。如果在 Sales 欄位中沒有同樣大小的資料,那這部分的 WHERE 子句本身就可以產生出正確的排名。

 

子句的第二部分,(a1.Sales=a2.Sales ANDa1.Name = a2.Name),則是讓我們在 Sales 欄位中有同樣大小的資料時 (像 Stella 及 Jeff 這兩筆資料),仍然能夠產生正確的排名。

 

 

算中位數

 

要算出中位數,我們必須要能夠達成以下幾個目標:

 

將資料依序排出,並找出每一行資料的排名。

找出『中間』的排名爲何。舉例來說,如果總共有 9 筆資料,那中間排名就是5 (有 4 筆資料比第 5 筆資料大,有 4 筆資料比第 5 筆資料小)。

找出中間排名資料的值。

來看看以下的例子。假設我們有以下的表格:

 

Total_Sales 表格

Name

Sales

John

10

Jennifer

15

Stella

20

Sophia

40

Greg

50

Jeff

20

要找出中位數,我們就鍵入:

 

SELECT Sales Median FROM

(SELECTa1.Name, a1.Sales, COUNT(a1.Sales) Rank

FROM Total_Sales a1, Total_Sales a2

WHERE a1.Sales < a2.Sales OR(a1.Sales=a2.Sales AND a1.Name <=a2.Name)

GROUP BY a1.Name, a1.Sales

ODER BY a1.Sales DESC) a3

WHERE Rank = (SELECT (COUNT(*)+1) DIV 2 FROM Total_Sales);

 

結果:

 

Median

20

 

讀者將會發現,第 2 行到第 6 行是跟產生 排名 的語句完全一樣。第 7 行則是算出中間的排名。DIV 是在 MySQL 中算出商的方式。在不同的數據庫中會有不同的方式求商。第 1 行則是列出排名中間的資料值。

 

 

算累積總計

算出累積總計是一個常見的需求,可惜以 SQL 並沒有一個很直接的方式達到這個需求。要以 SQL 算出累積總計,基本上的概念與列出排名類似:第一是先做個表格自我連結 (self join),然後將結果依序列出。在做列出排名時,我們算出每一行之前 (包含那一行本身) 有多少行數;而在做累積總計時,我們則是算出每一行之前 (包含那一行本身) 的總合。

 

來看看以下的例子。假設我們有以下的表格:

 

Total_Sales 表格

Name

Sales

John

10

Jennifer

15

Stella

20

Sophia

40

Greg

50

Jeff

20

要算出累積總計,我們就鍵入:

 

SELECT a1.Name, a1.Sales, SUM(a2.Sales) Running_Total

FROM Total_Sales a1, Total_Sales a2

WHERE a1.Sales <= a2.sales OR(a1.Sales=a2.Sales AND a1.Name = a2.Name)

GROUP BY a1.Name, a1.Sales

ODER BY a1.Sales DESC, a1.Name DESC;

 

結果:

 

Name   Sales  Running_Total

Greg    50     50

Sophia   40    90

Stella    20    110

Jeff      20    130

Jennifer  15     145

John     10     155

 

在以上的 SQL 語句中, WHERE 子句和 ODER BY 子句讓我們能夠在有重複值時能夠算出正確的累積總計。

 

 

 

算總合百分比

 

 

要用 SQL 算出總合百分比,我們需要用到算排名和累積總計的概念,以及運用子查詢的做法。在這裏,我們把子查詢放在外部查詢的 SELECT 子句中。讓我們來看以下的例子:

 

Total_Sales 表格

Name

Sales

John

10

Jennifer

15

Stella

20

Sophia

40

Greg

50

Jeff

20

要算出總合百分比,我們鍵入:

 

SELECT a1.Name, a1.Sales, a1.Sales/(SELECTSUM(Sales) FROM Total_Sales) Pct_To_Total

FROM Total_Sales a1, Total_Sales a2

WHERE a1.Sales <= a2.sales OR(a1.Sales=a2.Sales AND a1.Name = a2.Name)

GROUP BY a1.Name, a1.Sales

ODER BY a1.Sales DESC, a1.Name DESC;

 

結果:

 

Name  Sales   Pct_To_Total

Greg   50     0.3226

Sophia  40     0.2581

Stella   20     0.1290

Jeff     20     0.1290

Jennifer  15     0.0968

John    10      0.0645

 

"SELECTSUM(Sales) FROM Total_Sales" 這一段子查詢是用來算出總合。總合算出後,我們就能夠將每一行一一除以總合來求出每一行的總合百分比。

 

 

算累積總合百分比

 

要用 SQL 累積總合百分比算出,我們運用類似總合百分比的概念。兩者的不同處在於在這個情況下,我們要算出到目前爲止的累積總合是所有總合的百分之幾,而不是光看每一筆資料是所有總合的百分之幾。讓我們來看看以下的例子:

 

Total_Sales 表格

Name

Sales

John

10

Jennifer

15

Stella

20

Sophia

40

Greg

50

Jeff

20

要算出累積總合百分比,我們鍵入:

 

SELECT a1.Name, a1.Sales,SUM(a2.Sales)/(SELECT SUM(Sales) FROM Total_Sales) Pct_To_Total

FROM Total_Sales a1,Total_Sales a2

WHERE a1.Sales <=a2.sales OR (a1.Sales=a2.Sales AND a1.Name = a2.Name)

GROUP BY a1.Name,a1.Sales

ODER BY a1.Sales DESC, a1.Name DESC;

 

結果:

 

Name    Sales  Pct_To_Total

Greg      50  0.3226

Sophia     40  0.5806

Stella      20   0.7097

Jeff       20   0.8387

Jennifer   15    0.9355

John      10   1.0000

 

"SELECTSUM(Sales) FROM Total_Sales" 這一段子查詢是用來算出總合。我們接下來用累積總計 "SUM(a2.Sales)" 除以總合來求出每一行的累積總合百分比。

 

 

數據類型

 

1.  SQL SERVER的數據類型 

 

SQLServer 提供了 25 種數據類型:
  ·Binary [(n)]
  ·Varbinary [(n)]
  ·Char [(n)]
  ·Varchar[(n)]
  ·Nchar[(n)]
  ·Nvarchar[(n)]
  ·Datetime
  ·Smalldatetime
  ·Decimal[(p[,s])]
  ·Numeric[(p[,s])]
  ·Float[(n)]
  ·Real
  ·Int
  ·Smallint
  ·Tinyint
  ·Money
  ·Smallmoney
  ·Bit
  ·Cursor
  ·Sysname
  ·Timestamp
  ·Uniqueidentifier
  ·Text
  ·Image
  ·Ntext  

1)二進制數據類型

 

  二進制數據包括 Binary、Varbinary和 Image

  Binary 數據類型既可以是固定長度的(Binary),也可以是變長度的。

  Binary[(n)] 是 n 位固定的二進制數據。其中,n 的取值範圍是從 1到 8000。其存儲窨的大小是n + 4 個字節。

  Varbinary[(n)] 是 n 位變長度的二進制數據。其中,n 的取值範圍是從 1到 8000。其存儲窨的大小是n + 4個字節,不是n 個字節。

在 Image 數據類型中存儲的數據是以位字符串存儲的,不是由 SQL Server 解釋的,必須由應用程序來解釋。例如,應用程序可以使用BMP、TIEF、GIF 和 JPEG 格式把數據存儲在Image 數據類型中。

 

2)字符數據類型

 

  字符數據的類型包括 Char,Varchar 和 Text

  字符數據是由任何字母、符號和數字任意組合而成的數據。

Varchar 是變長字符數據,其長度不超過 8KB。Char 是定長字符數據,其長度最多爲 8KB。超過 8KB 的ASCII 數據可以使用Text數據類型存儲。例如,因爲 Html 文檔全部都是 ASCII 字符,並且在一般情況下長度超過 8KB,所以這些文檔可以 Text 數據類型存儲在SQLServer 中。

 

3Unicode 數據類型

 

  Unicode 數據類型包括Nchar,Nvarchar 和Ntext

  在 Microsoft SQL Server 中,傳統的非 Unicode 數據類型允許使用由特定字符集定義的字符。在 SQL Server安裝過程中,允許選擇一種字符集。使用 Unicode 數據類型,列中可以存儲任何由Unicode 標準定義的字符。在Unicode 標準中,包括了以各種字符集定義的全部字符。使用Unicode數據類型,所戰勝的窨是使用非 Unicode 數據類型所佔用的窨大小的兩倍。

在 SQLServer 中,Unicode 數據以 Nchar、Nvarchar 和 Ntext 數據類型存儲。使用這種字符類型存儲的列可以存儲多個字符集中的字符。當列的長度變化時,應該使用Nvarchar 字符類型,這時最多可以存儲 4000 個字符。當列的長度固定不變時,應該使用 Nchar 字符類型,同樣,這時最多可以存儲4000 個字符。當使用 Ntext 數據類型時,該列可以存儲多於 4000 個字符。

 

4)日期和時間數據類型

 

  日期和時間數據類型包括 Datetime 和Smalldatetime兩種類型

  日期和時間數據類型由有效的日期和時間組成。例如,有效的日期和時間數據包括“4/01/98 12:15:00:00:00 PM”和“1:28:29:15:01AM 8/17/98”。前一個數據類型是日期在前,時間在後一個數據類型是霎時間在前,日期在後。在 Microsoft SQL Server中,日期和時間數據類型包括Datetime 和 Smalldatetime 兩種類型時,所存儲的日期範圍是從 1753 年 1 月 1 日開始,到9999年12 月 31 日結束(每一個值要求 8 個存儲字節)。使用 Smalldatetime 數據類型時,所存儲的日期範圍是 1900年 1 月 1日 開始,到 2079 年 12 月 31 日結束(每一個值要求 4 個存儲字節)。

  日期的格式可以設定。設置日期格式的命令如下:

  Set DateFormat {format | @format _var|

  其中,format | @format_var 是日期的順序。有效的參數包括 MDY、DMY、YMD、YDM、MYD 和 DYM。在默認情況下,日期格式爲MDY。

例如,當執行Set DateFormat YMD 之後,日期的格式爲年 月 日 形式;當執行 Set DateFormat DMY 之後,日期的格式爲日 月有年 形式

 

5)數字數據類型

 

  數字數據只包含數字。數字數據類型包括正數和負數、小數(浮點數)和整數

  整數由正整數和負整數組成,例如 39、25、0-2 和 33967。在Micrsoft SQL Server 中,整數存儲的數據類型是    Int,Smallint和 Tinyint。Int 數據類型存儲數據的範圍大於 Smallint 數據類型存儲數據的範圍,而 Smallint 據類型存儲數據的範圍大於Tinyint 數據類型存儲數據的範圍。使用 Int 數據狗昔存儲數據的範圍是從 -2 147 483 648 到 2 147483 647(每一個值要求4個字節存儲空間)。使用 Smallint 數據類型時,存儲數據的範圍從 -32 768 到 32 767(每一個值要求2個字節存儲空間)。使用Tinyint 數據類型時,存儲數據的範圍是從0 到255(每一個值要求1個字節存儲空間)。

  精確小婁數據在 SQL Server 中的數據類型是Decimal 和 Numeric。這種數據所佔的存儲空間根據該數據的位數後的位數來確定。

在SQLServer 中,近似小數數據的數據類型是 Float 和 Real。例如,三分之一這個分數記作。3333333,當使用近似數據類型時能準確表示。因此,從系統中檢索到的數據可能與存儲在該列中數據不完全一樣。

 

6)貨幣數據表示正的或者負的貨幣數量

 

  在 Microsoft SQL Server 中,貨幣數據的數據類型是Money 和Smallmoney

  Money數據類型要求 8 個存儲字節,Smallmoney 數據類型要求 4 個存儲字節。

 

7)特殊數據類型

 

  特殊數據類型包括前面沒有提過的數據類型。特殊的數據類型有3種,即    Timestamp、Bit 和Uniqueidentifier。

  Timestamp 用於表示SQLServer 活動的先後順序,以二進投影的格式表示。Timestamp 數據與插入數據或者日期和時間沒有關係。

  Bit 由 1 或者 0 組成。當表示真或者假、ON 或者 OFF 時,使用 Bit 數據類型。例如,詢問是否是每一次訪問的客戶機請求可以存儲在這種數據類型的列中。

Uniqueidentifier 由 16 字節的十六進制數字組成,表示一個全局唯一的。當表的記錄行要求唯一時,GUID是非常有用。例如,在客戶標識號列使用這種數據類型可以區別不同的客戶。

 

2.用戶定義的數據類型

 

  用戶定義的數據類型基於在 Microsoft SQL Server 中提供的數據類型。當幾個表中必須存儲同一種數據類型時,並且爲保證這些列有相同的數據類型、長度和可空性時,可以使用用戶定義的數據類型。例如,可定義一種稱爲   postal_code 的數據類型,它基於 Char 數據類型。

當創建用戶定義的數據類型時,必須提供三個數:數據類型的名稱、所基於的系統數據類型和數據類型的可空性。

 

1)創建用戶定義的數據類型

 

  創建用戶定義的數據類型可以使用 Transact-SQL 語句。系統存儲過程sp_addtype 可以來創建用戶定義的數據類型。其語法形式如下:

  sp_addtype{type},[,system_data_bype][,'null_type']

  其中,type 是用戶定義的數據類型的名稱。system_data_type 是系統提供的數據類型,例如 Decimal、Int、Char等等。null_type 表示該數據類型是如何處理空值的,必須使用單引號引起來,例如'NULL'、'NOTNULL'或者'NONULL'。

  例子:

  Use cust

  Exec sp_addtype ssn,'Varchar(11)',"Not Null'

  創建一個用戶定義的數據類型 ssn,其基於的系統數據類型是變長爲11 的字符,不允許空。

  例子:

  Use cust

  Exec sp_addtype birthday,datetime,'Null'

  創建一個用戶定義的數據類型 birthday,其基於的系統數據類型是 DateTime,允許空。

  例子:

  Use master

  Exec sp_addtype telephone,'varchar(24),'Not Null'

  Eexc sp_addtype fax,'varchar(24)','Null'

創建兩個數據類型,即telephone 和 fax

 

2)刪除用戶定義的數據類型

 

  當用戶定義的數據類型不需要時,可刪除。刪除用戶定義的數據類型的命令是 sp_droptype {'type'}。

  例子:

  Use master

  Exec sp_droptype 'ssn'

  注意:當表中的列還正在使用用戶定義的數據類型時,或者在其上面還綁定有默認或者規則時,這種用戶定義的數據類型不能刪除。

 

SQL SERVER的字段類型說明

 

  以下爲SQL SERVER7.0以上版本的字段類型說明。SQL SERVER6.5的字段類型說明請參考SQL SERVER提供的說明。

 

字段類型 描述

 bit  0或1的整型數字

 int  從-2^31(-2,147,483,648)到2^31(2,147,483,647)的整型數字

 smallint 從-2^15(-32,768)到2^15(32,767)的整型數字

 tinyint 從0到255的整型數字

   

 decimal 從-10^38到10^38-1的定精度與有效位數的數字

 numeric decimal的同義詞

   

 money  從-2^63(-922,337,203,685,477.5808)到2^63-1(922,337,203,685,477.5807)的貨幣數據,最小貨幣單位千分之十

 smallmoney 從-214,748.3648到214,748.3647的貨幣數據,最小貨幣單位千分之十

   

 float  從-1.79E+308到1.79E+308可變精度的數字

 real  從-3.04E+38到3.04E+38可變精度的數字

   

 datetime 從1753年1月1日到9999年12日31的日期和時間數據,最小時間單位爲百分之三秒或3.33毫秒

 smalldatetime 從1900年1月1日到2079年6月6日的日期和時間數據,最小時間單位爲分鐘

   

 timestamp 時間戳,一個數據庫寬度的唯一數字

 uniqueidentifier  全球唯一標識符GUID

   

 char  定長非Unicode的字符型數據,最大長度爲8000

 varchar 變長非Unicode的字符型數據,最大長度爲8000

 text  變長非Unicode的字符型數據,最大長度爲2^31-1(2G)

   

 nchar  定長Unicode的字符型數據,最大長度爲8000

 nvarchar 變長Unicode的字符型數據,最大長度爲8000

 ntext  變長Unicode的字符型數據,最大長度爲2^31-1(2G)

   

 binary  定長二進制數據,最大長度爲8000

 varbinary 變長二進制數據,最大長度爲8000

 image  變長二進制數據,最大長度爲2^31-1(2G)

 

 

 

SQL語法

 

SELECT

SELECT "欄位" FROM "表格名"

 

DISTINCT

SELECT DISTINCT"欄位"

FROM "表格名"

 

WHERE

SELECT "欄位"

FROM "表格名"

WHERE "condition"

 

AND /OR

SELECT "欄位"

FROM "表格名"

WHERE "簡單條件"

{[AND|OR] "簡單條件"}+

 

In

SELECT "欄位"

FROM "表格名"

WHERE "欄位" IN ('值1', '值2', ...)

 

Between

SELECT "欄位"

FROM "表格名"

WHERE "欄位" BETWEEN '值1' AND'值2'

 

Like

SELECT "欄位"

FROM "表格名"

WHERE "欄位" LIKE {模式}

 

ODER BY

SELECT "欄位"

FROM "表格名"

[WHERE"條件"]

ODER BY "欄位" [ASC, DESC]

 

Count

SELECT COUNT("欄位")

FROM "表格名"

 

GROUP BY

SELECT "欄位1", SUM("欄位2")

FROM "表格名"

GROUP BY "欄位1"

 

HAVING

SELECT "欄位1", SUM("欄位2")

FROM "表格名"

GROUP BY "欄位1"

HAVING (函數條件)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章