文章目錄
- 7.1 計算字段
- 7.2 拼接字段
- 使用別名
- 7.3 執行算術計算
這一課介紹什么是計算字段,如何創建計算字段,以及如何從應用程序中使用別名引用它們。
7.1 計算字段
存儲在數據庫表中的數據一般不是應用程序所需要的格式,下面舉幾個例子。
- 需要顯示公司名,同時還需要顯示公司的地址,但這兩個信息存儲在不同的表列中。
- 城市、州和郵政編碼存儲在不同的列中(應該這樣),但郵件標簽打印程序需要把它們作為一個有恰當格式的字段檢索出來。
- 列數據是大小寫混合的,但報表程序需要把所有數據按大寫表示出來。
- 物品訂單表存儲物品的價格和數量,不存儲每個物品的總價格(用價格乘以數量即可)。但為打印發票,需要物品的總價格。
- 需要根據表數據進行諸如總數、平均數的計算。
在上述每個例子中,存儲在表中的數據都不是應用程序所需要的。我們需要直接從數據庫中檢索出轉換、計算或格式化過的數據,而不是檢索出數據,然后再在客戶端應用程序中重新格式化。
這就是計算字段可以派上用場的地方了。與前幾課介紹的列不同,計算字段并不實際存在于數據庫表中。計算字段是運行時在SELECT語句內創建的。
字段(field)
基本上與列(column)的意思相同,經常互換使用,不過數據庫列一般稱為列,而術語字段通常與計算字段一起使用。
需要特別注意,只有數據庫知道SELECT語句中哪些列是實際的表列,哪些列是計算字段。從客戶端(如應用程序)來看,計算字段的數據與其他列的數據的返回方式相同。
提示:客戶端與服務器的格式
在SQL語句內可完成的許多轉換和格式化工作都可以直接在客戶端應用程序內完成。但一般來說,在數據庫服務器上完成這些操作比在客戶端中完成要快得多。
7.2 拼接字段
為了說明如何使用計算字段,我們來舉一個簡單例子,創建由兩列組成的標題。
Vendors表包含供應商名和地址信息。假如要生成一個供應商報表,需要在格式化的名稱(位置)中列出供應商的位置。
此報表需要一個值,而表中數據存儲在兩個列vend_name和vend_country中。此外,需要用括號將vend_country括起來,這些東西都沒有存儲在數據庫表中。這個返回供應商名稱和地址的SELECT語句很簡單,但我們是如何創建這個組合值的呢?
拼接(concatenate)
將值聯結到一起(將一個值附加到另一個值)構成單個值。
解決辦法是把兩個列拼接起來。在SQL中的SELECT語句中,可使用一個特殊的操作符來拼接兩個列。根據你所使用的DBMS,此操作符可用加號(+)或兩個豎杠(||)表示。在MySQL和MariaDB中,必須使用特殊的函數。
說明:是+還是||?
Access和SQL Server使用+號。DB2、Oracle、PostgreSQL、SQLite和Open Office
Base使用||。詳細請參閱具體的DBMS文檔。
下面是使用加號的例子(多數DBMS使用這種語法):
輸入▼
SELECT vend_name + ' (' + vend_country + ')'
FROM Vendors
ORDER BY vend_name;
輸出▼
Bear Emporium (USA ????? ) |
Bears R Us (USA ????? ) |
Doll House Inc. (USA ????? ) |
Fun and Games (England ????? ) |
Furball Inc. (USA ????? ) |
Jouets et ours (France ????? ) |
下面是相同的語句,但使用的是||語法:
輸入▼
SELECT vend_name || ' (' || vend_country || ')'
FROM Vendors
ORDER BY vend_name;
輸出▼
Bear Emporium (USA????? ) |
Bears R Us (USA ?????) |
Doll House Inc. (USA ?????) |
Fun and Games (England ?????) |
Furball Inc. (USA ?????) |
Jouets et ours (France ?????) |
分析▼
上面兩個SELECT語句拼接以下元素:
- 存儲在vend_name列中的名字;
- 包含一個空格和一個左圓括號的字符串;
- 存儲在vend_country列中的國家;
- 包含一個右圓括號的字符串。
從上述輸出中可以看到,SELECT語句返回包含上述四個元素的一個列(計算字段)。
再看看上述SELECT語句返回的輸出。結合成一個計算字段的兩個列用空格填充。許多數據庫(不是所有)保存填充為列寬的文本值,而實際上你要的結果不需要這些空格。為正確返回格式化的數據,必須去掉這些空格。這可以使用SQL的RTRIM()函數來完成,如下所示:
輸入▼
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')'
FROM Vendors
ORDER BY vend_name;
輸出▼
Bear Emporium(USA ) |
Bears R Us(USA ) |
Doll House Inc.(USA ) |
Fun and Games(England ) |
Furball Inc.(USA ) |
Jouets et ours(France ) |
下面是相同的語句,但使用的是||:
輸入▼
SELECT RTRIM(vend_name) || ' (' || RTRIM(vend_country) || ')'
FROM Vendors
ORDER BY vend_name;
輸出▼
Bear Emporium(USA ) |
Bears R Us(USA ) |
Doll House Inc.(USA ) |
Fun and Games(England ) |
Furball Inc.(USA ) |
Jouets et ours(France ) |
分析▼
RTRIM()函數去掉值右邊的所有空格。通過使用RTRIM(),各個列都進行了整理。
說明:TRIM函數
大多數DBMS都支持RTRIM()(正如剛才所見,它去掉字符串右邊的空格)、LTRIM()(去掉字符串左邊的空格)以及TRIM()(去掉字符串左右兩邊的空格)。
使用別名
從前面的輸出可以看到,SELECT語句可以很好地拼接地址字段。但是,這個新計算列的名字是什么呢?實際上它沒有名字,它只是一個值。如果僅在SQL查詢工具中查看一下結果,這樣沒有什么不好。但是,一個未命名的列不能用于客戶端應用中,因為客戶端沒有辦法引用它。
為了解決這個問題,SQL支持列別名。別名(alias)是一個字段或值的替換名。別名用AS關鍵字賦予。請看下面的SELECT語句:
輸入▼
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors
ORDER BY vend_name;
輸出▼
vend_title |
---|
Bear Emporium(USA ) |
Bears R Us(USA ) |
Doll House Inc.(USA ) |
Fun and Games(England ) |
Furball Inc.(USA ) |
Jouets et ours(France ) |
下面是相同的語句,但使用的是||語法:
輸入▼
SELECT RTRIM(vend_name) || ' (' || RTRIM(vend_country) || ')' AS vend_title
FROM Vendors
ORDER BY vend_name;
下面是MySQL和MariaDB中使用的語句:
輸入▼
SELECT Concat(vend_name, ' (', vend_country, ')') AS vend_title FROM Vendors ORDER BY vend_name;
分析▼
SELECT語句本身與以前使用的相同,只不過這里的計算字段之后跟了文本AS vend_title。它指示SQL創建一個包含指定計算結果的名為vend_title的計算字段。從輸出可以看到,結果與以前的相同,但現在列名為vend_title,任何客戶端應用都可以按名稱引用這個列,就像它是一個實際的表列一樣。
說明:AS通常可選
在很多DBMS中,AS關鍵字是可選的,不過最好使用它,這被視為一條最佳實踐。
提示:別名的其他用途
別名還有其他用途。常見的用途包括在實際的表列名包含不合法的字符(如空格)時重新命名它,在原來的名字含混或容易誤解時擴充它。
警告:別名
別名既可以是一個單詞也可以是一個字符串。如果是后者,字符串應該括在引號中。雖然這種做法是合法的,但不建議這么去做。多單詞的名字可讀性高,不過會給客戶端應用帶來各種問題。因此,別名最常見的使用是將多個單詞的列名重命名為一個單詞的名字。
說明:導出列
別名有時也稱為導出列(derived column),不管怎么叫,它們所代表的是相同的東西。
7.3 執行算術計算
計算字段的另一常見用途是對檢索出的數據進行算術計算。舉個例子,Orders表包含收到的所有訂單,OrderItems表包含每個訂單中的各項物品。下面的SQL語句檢索訂單號20008中的所有物品:
輸入▼
SELECT prod_id, quantity, item_price
FROM OrderItems
WHERE order_num = 20008;
輸出▼
prod_id | quantity | item_price |
---|---|---|
RGAN01 | 5 | 4.9900 |
BR03 | 5 | 11.9900 |
BNBG01 | 10 | 3.4900 |
BNBG02 | 10 | 3.4900 |
BNBG03 | 10 | 3.4900 |
item_price列包含訂單中每項物品的單價。如下匯總物品的價格(單價乘以訂購數量):
輸入▼
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
輸出▼
prod_id | quantity | item_price | expanded_price |
---|---|---|---|
RGAN01 | 5 | 4.9900 | 24.9500 |
BR03 | 5 | 11.9900 | 59.9500 |
BNBG01 | 10 | 3.4900 | 34.9000 |
BNBG02 | 10 | 3.4900 | 34.9000 |
BNBG03 | 10 | 3.4900 | 34.9000 |
分析▼
輸出中顯示的expanded_price列是一個計算字段,此計算為quantity*item_price。客戶端應用現在可以使用這個新計算列,就像使用其他列一樣。
SQL支持表7-1中列出的基本算術操作符。此外,圓括號可用來區分優先順序。關于優先順序的介紹,請參閱第5課。
表7-1 SQL算術操作符
操 作 符 | 說 明 |
---|---|
+ | 加 |
- | 減 |
* | 乘 |
/ | 除 |
提示:如何測試計算 SELECT語句為測試、檢驗函數和計算提供了很好的方法。雖然SELECT通常用于從表中檢索數據,但是省略了FROM子句后就是簡單地訪問和處理表達式,例如SELECT 3 * 2;將返回6,SELECT Trim(’ abc ');將返回abc,SELECT Now();使用Now()函數返回當前日期和時間。現在你明白了,可以根據需要使用SELECT語句進行檢驗。
上一篇:第6課 SQL入門之用通配符進行過濾