SQL 中各種各樣的函數


學習重點

  • 根據用途,函數可以大致分為算術函數、字符串函數、日期函數、轉換函聚合函數。

  • 函數的種類很多,無需全都記住,只需要記住具有代表性的函數就可以了,其他的可以在使用時再進行查詢。

一、函數的種類

前幾篇和大家一起學習了 SQL 的語法結構等必須要遵守的規則。本文將會進行一點改變,來學習一些 SQL 自帶的便利工具——函數

我們在 對表進行聚合查詢 中已經學習了函數的概念,這里再回顧一下。所謂函數,就是輸入某一值得到相應輸出結果的功能,輸入值稱為參數(parameter),輸出值稱為返回值

KEYWORD

  • 函數

  • 參數(parameter)

  • 返回值

函數大致可以分為以下幾種。

  • 算術函數(用來進行數值計算的函數)

  • 字符串函數(用來進行字符串操作的函數)

  • 日期函數(用來進行日期操作的函數)

  • 轉換函數(用來轉換數據類型和值的函數)

  • 聚合函數(用來進行數據聚合的函數)

KEYWORD

  • 算術函數

  • 字符串函數

  • 日期函數

  • 轉換函數

  • 聚合函數

我們已經在 對表進行聚合查詢 中學習了聚合函數的相關內容,大家應該對函數有初步的了解了吧。聚合函數基本上只包含 COUNTSUMAVGMAXMIN 這 5 種,而其他種類的函數總數則超過 200 種。可能大家會覺得怎么會有那么多函數啊,但其實並不需要擔心,雖然數量眾多,但常用函數只有 30 ~ 50 個。不熟悉的函數大家可以查閱參考文檔(詞典)來了解 [1]

本節我們將學習一些具有代表性的函數。大家並不需要一次全部記住,只需要知道有這樣的函數就可以了,實際應用時可以查閱參考文檔。

接下來,讓我們來詳細地看一看這些函數。

二、算術函數

算術函數是最基本的函數,其實之前我們已經學習過了,可能有些讀者已經想起來了。沒錯,就是 算術運算符和比較運算符 介紹的加減乘除四則運算。

KEYWORD

  • 算術函數
  • +(加法)

  • -(減法)

  • *(乘法)

  • /(除法)

KEYWORD

  • + 運算符

  • - 運算符

  • * 運算符

  • / 運算符

由於這些算術運算符具有“根據輸入值返回相應輸出結果”的功能,因此它們是出色的算術函數。在此我們將會給大家介紹除此之外的具有代表性的函數。

為了學習算術函數,我們首先根據代碼清單 1 創建一張示例用表(SampleMath)。

NUMERIC 是大多數 DBMS 都支持的一種數據類型,通過 NUMBERIC ( 全體位數, 小數位數 ) 的形式來指定數值的大小。接下來,將會給大家介紹常用的算術函數——ROUND 函數,由於 PostgreSQL 中的 ROUND 函數只能使用 NUMERIC 類型的數據,因此我們在示例中也使用了該數據類型。

代碼清單 1 創建 SampleMath

-- DDL :創建表
CREATE TABLE SampleMath
(m  NUMERIC (10,3),
 n  INTEGER,
 p  INTEGER);

SQL Server PostgreSQL

-- DML :插入數據
BEGIN TRANSACTION; -----①

INSERT INTO SampleMath(m, n, p) VALUES (500, 0,     NULL);
INSERT INTO SampleMath(m, n, p) VALUES (-180, 0,    NULL);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, NULL, NULL);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 7,    3);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 5,    2);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 4,    NULL);
INSERT INTO SampleMath(m, n, p) VALUES (8,    NULL, 3);
INSERT INTO SampleMath(m, n, p) VALUES (2.27, 1,    NULL);
INSERT INTO SampleMath(m, n, p) VALUES (5.555,2,    NULL);
INSERT INTO SampleMath(m, n, p) VALUES (NULL, 1,    NULL);
INSERT INTO SampleMath(m, n, p) VALUES (8.76, NULL, NULL);

COMMIT;

特定的 SQL

不同的 DBMS 事務處理的語法也不盡相同。代碼清單 1 中的 DML 語句在 MySQL 中執行時,需要將 ① 部分更改為“STARTTRANSACTION;”,在 Oracle 和 DB2 中執行時,無需用到 ① 的部分(請刪除)。

詳細內容請大家參考 事務 中的“創建事務”。

下面讓我們來確認一下創建好的表中的內容,其中應該包含了 mnp 三列。

SELECT * FROM SampleMath;

執行結果

    m    | n | p
---------+---+--
 500.000 | 0 |
-180.000 | 0 |
         |   |
         | 7 | 3
         | 5 | 2
         | 4 |
   8.000 |   | 3
   2.270 | 1 |
   5.555 | 2 |
         | 1 |
   8.760 |   |

2.1 ABS——絕對值

語法 1 ABS 函數

ABS(數值)

ABS 是計算絕對值的函數。絕對值(absolute value)不考慮數值的符號,表示一個數到原點的距離。簡單來講,絕對值的計算方法就是:0 和正數的絕對值就是其本身,負數的絕對值就是去掉符號后的結果。

KEYWORD

  • ABS 函數

  • 絕對值

代碼清單 2 計算數值的絕對值

SELECT m,
      ABS(m) AS abs_col
FROM SampleMath;

執行結果

ABS 函數執行結果

右側的 abs_col 列就是通過 ABS 函數計算出的 m 列的絕對值。請大家注意,-180 的絕對值就是去掉符號后的結果 180

通過上述結果我們可以發現,ABS 函數的參數為 NULL 時,結果也是 NULL。並非只有 ABS 函數如此,其實絕大多數函數對於 NULL 都返回 NULL [2]

2.2 MOD——求余

語法 2 MOD 函數

MOD(被除數,除數)

MOD 是計算除法余數(求余)的函數,是 modulo 的縮寫。例如,7/3 的余數是 1,因此 MOD(7, 3) 的結果也是 1(代碼清單 3)。因為小數計算中並沒有余數的概念,所以只能對整數類型的列使用 MOD 函數。

KEYWORD

  • MOD 函數

代碼清單 3 計算除法 (n ÷ p) 的余數

Oracle DB2 PostgreSQL MySQL

SELECT n, p,
       MOD(n, p) AS mod_col
  FROM SampleMath;

執行結果

 n | p | mod_col
---+---+--------
 0 |   |
 0 |   |
   |   |
 7 | 3 |    1
 5 | 2 |    1
 4 |   |
   | 3 |
 1 |   |
 2 |   |
 1 |   |
   |   |

凡例

mod_colMOD(n,p)的返回值(n÷p 的余數)

這里有一點需要大家注意:主流的 DBMS 都支持 MOD 函數,只有 SQL Server 不支持該函數

特定的 SQL

SQL Server 使用特殊的運算符(函數)“%”來計算余數,使用如下的專用語法可以得到與代碼清單 3 相同的結果。需要使用 SQL Server 的讀者需要特別注意。

KEYWORD

  • % 運算符(SQL Server)

SQL Server

SELECT n, p,
      n % p AS mod_col
FROM SampleMath;

2.3 ROUND——四舍五入

語法 3 ROUND 函數

ROUND(對象數值,保留小數的位數)

ROUND 函數用來進行四舍五入操作。四舍五入在英語中稱為 round。如果指定四舍五入的位數為 1,那么就會對小數點第 2 位進行四舍五入處理。如果指定位數為 2,那么就會對第 3 位進行四舍五入處理(代碼清單 4)。

KEYWORD

  • ROUND 函數

代碼清單 4 對 m 列的數值進行 n 列位數的四舍五入處理

SELECT m, n,
       ROUND(m, n) AS round_col
  FROM SampleMath;

執行結果

    m    | n | round_col
---------+---+----------
 500.000 | 0 |       500
-180.000 | 0 |      -180
         |   |
         | 7 |
         | 5 |
         | 4 |
   8.000 |   |
   2.270 | 1 |       2.3
   5.555 | 2 |      5.56
         | 1 |
   8.760 |   |

凡例

m:對象數值

n:四舍五入位數

round_colROUND(m,n) 的返回值(四舍五入的結果)

三、字符串函數

截至目前,我們介紹的函數都是主要針對數值的算術函數,但其實算術函數只是 SQL(其他編程語言通常也是如此)自帶的函數中的一部分。雖然算術函數是我們經常使用的函數,但是字符串函數也同樣經常被使用。

KEYWORD

  • 字符串函數

在日常生活中,我們經常會像使用數字那樣,對字符串進行替換、截取、簡化等操作,因此 SQL 也為我們提供了很多操作字符串的功能。

為了學習字符串函數,我們再來創建一張表(SampleStr),參見代碼清單 5。

代碼清單 5 創建 SampleStr

-- DDL :創建表
CREATE TABLE SampleStr
(str1   VARCHAR(40),
 str2   VARCHAR(40),
 str3   VARCHAR(40);)

SQL Server PostgreSQL

-- DML :插入數據
BEGIN TRANSACTION; -------------①

INSERT INTO SampleStr (str1, str2, str3) VALUES ('opx' ,'rt',NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES ('abc' ,'def' ,NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES ('山田' ,'太郎' ,'是我');
INSERT INTO SampleStr (str1, str2, str3) VALUES ('aaa' ,NULL ,NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES (NULL ,'xyz',NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES ('@!#$%' ,NULL ,NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES ('ABC' ,NULL ,NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES ('aBC' ,NULL ,NULL);
INSERT INTO SampleStr (str1, str2, str3) VALUES ('abc太郎' ,'abc' ,'ABC');
INSERT INTO SampleStr (str1, str2, str3) VALUES ('abcdefabc' ,'abc' ,'ABC');
INSERT INTO SampleStr (str1, str2, str3) VALUES ('micmic' ,'i'   ,'I');

COMMIT;

特定的 SQL

不同的 DBMS 事務處理的語法也不盡相同。代碼清單 5 中的 DML 語句在 MySQL 中執行時,需要將①部分更改為“START TRANSACTION;”。在 Oracle 和 DB2 中執行時,無需用到 ① 的部分(請刪除)。

詳細內容請大家參考 事務 節中的“創建事務”。

下面讓我們來確認一下創建好的表中的內容,其中應該包含了 str1str2str3 三列。

SELECT * FROM SampleStr;

執行結果

   str1    | str2 | str3
-----------+------+-----
 opx       | rt   |
 abc       | def  |
 山田      | 太郎  | 是我
 aaa       |      |
           | xyz  |
 @!#$%     |      |
 ABC       |      |
 aBC       |      |
 abc太郎   | abc  | ABC
 abcdefabc | abc  | ABC
 micmic    | i    | I

3.1 ||——拼接

語法 4 || 函數

字符串1||字符串2

在實際業務中,我們經常會碰到 abc + de = abcde 這樣希望將字符串進行拼接的情況。在 SQL 中,可以通過由兩條並列的豎線變換而成的“||”函數來實現(代碼清單 6)。

KEYWORD

  • || 函數

代碼清單 6 拼接兩個字符串(str1+str2

Oracle DB2 PostgreSQL

SELECT str1, str2,
       str1 || str2 AS str_concat
  FROM SampleStr;

執行結果

   str1    | str2 | str_concat
-----------+------+------------
 opx       | rt   | opxrt
 abc       | def  | abcdef
 山田      | 太郎  | 山田太郎
 aaa       |      |
           | xyz  |
 @!#$%     |      |
 ABC       |      |
 aBC       |      |
 abc太郎   | abc  | abc太郎abc
 abcdefabc | abc  | abcdefabcabc
 micmic    | i    | micmaci

凡例

str_concatstr1 || str2 的返回值(拼接結果)

進行字符串拼接時,如果其中包含 NULL,那么得到的結果也是 NULL。這是因為“||”也是變了形的函數。當然,三個以上的字符串也可以進行拼接(代碼清單 7)。

代碼清單 7 拼接三個字符串(str1+str2+str3

Oracle DB2 PostgreSQL

SELECT str1, str2, str3,
       str1 || str2 || str3 AS str_concat
  FROM SampleStr
 WHERE str1 = '山田';

執行結果

 str1 | str2 | str3 | str_concat
------+------+------+-----------
 山田 | 太郎 | 是我 | 山田太郎是我

凡例

str_concatstr1 || str2 || str3 的返回值(拼接結果)

這里也有一點需要大家注意,|| 函數在 SQL Server 和 MySQL 中無法使用。

特定的 SQL

SQL Server 使用“+”運算符(函數)來連接字符串 [3]。MySQL 使用 CONCAT 函數來完成字符串的拼接。使用如下 SQL Server/MySQL 的專用語法能夠得到與代碼清單 7 相同的結果。另外,在 SQL Server 2012 及其之后的版本中也可以使用 CONCAT 函數

KEYWORD

  • + 運算符(SQL Server)

  • CONCAT 函數(MySQL)

SQL Server

SELECT str1, str2, str3,
     str1 + str2 + str3 AS str_concat
 FROM SampleStr;

MySQL SQL Server 2012 及之后

SELECT str1, str2, str3,
      CONCAT(str1, str2, str3) AS str_concat
 FROM SampleStr;

3.2 LENGTH——字符串長度

語法 5 LENGTH 函數

LENGTH(字符串)

想要知道字符串中包含多少個字符時,可以使用 LENGTH(長度)函數(代碼清單 8)。

KEYWORD

  • LENGTH 函數

代碼清單 8 計算字符串長度

Oracle DB2 PostgreSQL MySQL

SELECT str1,
       LENGTH(str1) AS len_str
  FROM SampleStr;

執行結果

   str1    | len_str
-----------+--------
 opx       |    3
 abc       |    3
 山田      |    2
 aaa       |    3
           |
 @!#$%     |    5
 ABC       |    3
 aBC       |    3
 abc太郎   |    5
 abcdefabc |    9
 micmic    |    6

凡例

len_strLENGTH(str1) 的返回值(str1 的字符長度)

需要注意的是,該函數也無法在 SQL Server 中使用

特定的 SQL

SQL Server 使用 LEN 函數來計算字符串的長度。使用如下 SQL Server 的專用語法能夠得到與代碼清單 8 相同的結果。

KEYWORD

  • LEN 函數(SQL Server)

SQL Server

SELECT str1,
      LEN(str1) AS len_str
 FROM SampleStr;

我想大家應該逐漸明白“SQL 中有很多特定的用法”這句話的含義了吧。

專欄

對 1 個字符使用 LENGTH 函數有可能得到 2 字節以上的結果

LENGTH 函數中,還有一點需要大家特別注意,那就是該函數究竟以什么為單位來計算字符串的長度。這部分是初級以上階段才會學習到的內容,在此先簡單介紹一下。

可能有些讀者已經有所了解,與半角英文字母占用 1 字節不同,漢字這樣的全角字符會占用 2 個以上的字節(稱為多字節字符)。因此,使用 MySQL 中的 LENGTH 這樣以字節為單位的函數進行計算時,“LENGTH(山田)”的返回結果是 4。同樣是 LENGTH 函數,不同 DBMS 的執行結果也不盡相同 [4]

KEYWORD

  • 字節

  • 多字節字符

    字節(byte)是計算機中用來表述數據大小的基本單位。通常情況下“1 字符 = 1 字節”。單位字節(KB)是字節的 1024 倍,單位兆字節(MB)是千字節的 1024 倍,單位千兆字 節(GB)是兆 字節 的 1024 倍。表示硬盤容量時經常會使用的“100 GB”“250 GB”,其中 100 GB 指的是可以存儲 1024× 1024× 1024×100=107,374,182,400 個半角英文字母。

  • LENGTH 函數(MySQL)

  • CHAR_LENGTH 函數(MySQL)

雖然有些混亂,但這正是我希望大家能夠牢記的。

3.3 LOWER——小寫轉換

語法 6 LOWER 函數

LOWER(字符串)

LOWER 函數只能針對英文字母使用,它會將參數中的字符串全都轉換為小寫(代碼清單 9)。因此,該函數並不適用於英文字母以外的場合。此外,該函數並不影響原本就是小寫的字符。

KEYWORD

  • LOWER 函數

代碼清單 9 大寫轉換為小寫

SELECT str1,
       LOWER(str1) AS low_str
  FROM SampleStr
 WHERE str1 IN ('ABC', 'aBC', 'abc', '山田');

執行結果

 str1 | low_str
------+--------
 abc  | abc
 山田 | 山田
 ABC  | abc
 aBC  | abc

凡例

low_strLOWER(str1) 的返回值

既然存在小寫轉換函數,那么肯定也有大寫轉換函數,UPPER 就是大寫轉換函數。

3.4 REPLACE——字符串的替換

語法 7 REPLACE 函數

REPLACE(對象字符串,替換前的字符串,替換后的字符串)

使用 REPLACE 函數,可以將字符串的一部分替換為其他的字符串(代碼清單 10)。

KEYWORD

  • REPLACE 函數

代碼清單 10 替換字符串的一部分

SELECT str1, str2, str3,
       REPLACE(str1, str2, str3) AS rep_str
  FROM SampleStr;

執行結果

   str1    | str2 | str3 | rep_str
-----------+------+------+---------
 opx       | rt   |      |
 abc       | def  |      |
 山田      | 太郎  | 是我 | 山田
 aaa       |      |      |
           | xyz  |      |
 @!#$%     |      |      |
 ABC       |      |      |
 aBC       |      |      |
 abc太郎   | abc  | ABC  | ABC太郎
 abcdefabc | abc  | ABC  | ABCdefABC
 micmic    | i    | I    | mIcmIc

凡例

str1 :對象字符串

str2 :替換前的字符串

str3 :替換后的字符串

rep_strREPLACE(str1,str2,str3) 的返回值(替換結果)

3.5 SUBSTRING——字符串的截取

語法 8 SUBSTRING 函數(PostgreSQL/MySQL 專用語法)

SUBSTRING(對象字符串 FROM 截取的起始位置 FOR 截取的字符數)

使用 SUBSTRING 函數可以截取出字符串中的一部分字符串(代碼清單 11)。截取的起始位置從字符串最左側開始計算 [5]

KEYWORD

  • SUBSTRING 函數

代碼清單 11 截取出字符串中第 3 位和第 4 位的字符

PostgreSQL MySQL

SELECT str1,
       SUBSTRING(str1 FROM 3 FOR 2) AS sub_str
  FROM SampleStr;

執行結果

   str1    | sub_str
-----------+--------
 opx       | x
 abc       | c
 山田      |
 aaa       | a
           |
 @!#$%     | #$
 ABC       | C
 aBC       | C
 abc太郎   | c太
 abcdefabc | cd
 micmic    | cm

凡例

sub_strSUBSTRING(str1 FROM 3 FOR 2) 的返回值

雖然上述 SUBSTRING 函數的語法是標准 SQL 承認的正式語法,但是現在只有 PostgreSQL 和 MySQL 支持該語法。

特定的 SQL

SQL Server 將語法 8a 中的內容進行了簡化(語法 8b)。

語法 8a SUBSTRING 函數(SQL Server 專用語法)

SUBSTRING(對象字符串,截取的起始位置,截取的字符數)

Oracle 和 DB2 將該語法進一步簡化,得到了如下結果。

語法 8b SUBSTR 函數(Oracle/DB2 專用語法)

SUBSTR(對象字符串,截取的起始位置,截取的字符數)

SQL 有這么多特定的語法,真是有些讓人頭疼啊。各 DBMS 中能夠得到與代碼清單 11 相同結果的專用語法如下所示。

SQL Server

SELECT str1,
      SUBSTRING(str1, 3, 2) AS sub_str
 FROM SampleStr;

Oracle DB2

SELECT str1,
      SUBSTR(str1, 3, 2) AS sub_str
 FROM SampleStr;

3.6 UPPER——大寫轉換

語法 9 UPPER 函數

UPPER(字符串)

UPPER 函數只能針對英文字母使用,它會將參數中的字符串全都轉換為大寫(代碼清單 12)。因此,該函數並不適用於英文字母以外的情況。此外,該函數並不影響原本就是大寫的字符。

KEYWORD

  • UPPER 函數

代碼清單 12 將小寫轉換為大寫

SELECT str1,
       UPPER(str1) AS up_str
  FROM SampleStr
 WHERE str1 IN ('ABC', 'aBC', 'abc', '山田');

執行結果

 str1 | up_str
------+--------
 abc  | ABC
 山田 | 山田
 ABC  | ABC
 aBC  | ABC

凡例

up_strUPPER(str1) 的返回值

與之相對,進行小寫轉換的是 LOWER 函數。

四、日期函數

雖然 SQL 中有很多日期函數,但是其中大部分都依存於各自的 DBMS,因此無法統一說明 [6]。本節將會介紹那些被標准 SQL 承認的可以應用於絕大多數 DBMS 的函數。

KEYWORD

  • 日期函數

4.1 CURRENT_DATE——當前日期

語法 10 CURRENT_DATE 函數

CURRENT_DATE

CURRENT_DATE 函數能夠返回 SQL 執行的日期,也就是該函數執行時的日期。由於沒有參數,因此無需使用括號。

KEYWORD

  • CURRENT_DATE 函數

執行日期不同,CURRENT_DATE 函數的返回值也不同。如果在 2009 年 12 月 13 日執行該函數,會得到返回值“2009-12-13”。如果在 2010 年 1 月 1 日執行,就會得到返回值“2010-01-01”(代碼清單 13)。

代碼清單 13 獲得當前日期

SELECT CURRENT_DATE;

執行結果

    date
------------
 2016-05-20

該函數無法在 SQL Server 中執行。此外,Oracle 和 DB2 中的語法略有不同

特定的 SQL

SQL Server 使用如下的 CURRENT_TIMESTAMP(后述)函數來獲得當前日期。

SQL Server

-- 使用CAST(后述)函數將CURRENT_TIMESTAMP轉換為日期類型
SELECT CAST(CURRENT_TIMESTAMP AS DATE) AS CUR_DATE;

執行結果

  CUR_DATE
  ----------
  2010-05-25

在 Oracle 中使用該函數時,需要在 FROM 子句中指定臨時表(DUAL)。而在 DB2 中使用時,需要在 CRUUENTDATE 之間添加半角空格,並且還需要指定臨時表 SYSIBM.SYSDUMMY1(相當於 Oracle 中的 DUAL)。這些容易混淆的地方請大家多加注意。

Oracle

SELECT CURRENT_DATE
FROM dual;

DB2

SELECT CURRENT DATE
FROM SYSIBM.SYSDUMMY1;

4.2 CURRENT_TIME ——當前時間

語法 11 CURRENT_TIME** 函數**

CURRENT_TIME

CURRENT_TIME 函數能夠取得 SQL 執行的時間,也就是該函數執行時的時間(代碼清單 14)。由於該函數也沒有參數,因此同樣無需使用括號。

KEYWORD

  • CURRENT_TIME 函數

代碼清單 14 取得當前時間

PostgreSQL MySQL

SELECT CURRENT_TIME;

執行結果

    timetz
-----------------
17:26:50.995+09

該函數同樣無法在 SQL Server 中執行,在 Oracle 和 DB2 中的語法同樣略有不同

特定的 SQL

SQL Server 使用如下的 CURRENT_TIMESTAMP 函數(后述)來獲得當前日期。

-- 使用CAST函數(后述)將CURRENT_TIMESTAMP轉換為時間類型
SELECT CAST(CURRENT_TIMESTAMP AS TIME) AS CUR_TIME;

執行結果

  CUR_TIME
  ----------------
  21:33:59.3400000

在 Oracle 和 DB2 中使用時的語法如下所示。需要注意的地方和 CURRENT_DATE 函數相同。在 Oracle 中使用時所得到的結果還包含日期。

Oracle

-- 指定臨時表(DUAL)
SELECT CURRENT_TIMESTAMP
 FROM dual;

DB2

/* CURRENT和TIME之間使用了半角空格,指定臨時表SYSIBM.SYSDUMMY1 */
SELECT CURRENT TIME
 FROM SYSIBM.SYSDUMMY1;

4.3 CURRENT_TIMESTAMP——當前日期和時間

語法 12 CURRENT_TIMESTAMP函數

CURRENT_TIMESTAMP

CURRENT_TIMESTAMP 函數具有 CURRENT_DATE + CURRENT_TIME 的功能。使用該函數可以同時得到當前的日期和時間,當然也可以從結果中截取日期或者時間。

KEYWORD

  • CURRENT_TIMESTAMP 函數

代碼清單 15 取得當前日期和時間

SQL Server PostgreSQL MySQL

SELECT CURRENT_TIMESTAMP;

執行結果

           now
---------------------------
2016-04-25 18:31:03.704+09

該函數可以在 SQL Server 等各個主要的 DBMS 中使用 [7]。但是,與之前的 CURRENT_DATECURRENT_TIME 一樣,在 Oracle 和 DB2 中該函數的語法略有不同

特定的 SQL

Oracle 和 DB2 使用如下寫法可以得到與代碼清單 15 相同的結果。其中需要注意的地方與 CURRENT_DATE 時完全相同。

Oracle

-- 指定臨時表(DUAL)
SELECT CURRENT_TIMESTAMP
 FROM dual;

DB2

/* CURRENT和TIME之間使用了半角空格,指定臨時表SYSIBM.SYSDUMMY1 */
SELECT CURRENT TIMESTAMP
 FROM SYSIBM.SYSDUMMY1;

4.4 EXTRACT——截取日期元素

語法 13 EXTRACT 函數

EXTRACT(日期元素 FROM 日期)

使用 EXTRACT 函數可以截取出日期數據中的一部分,例如“年”“月”,或者“小時”“秒”等(代碼清單 16)。該函數的返回值並不是日期類型而是數值類型。

KEYWORD

  • EXTRACT 函數

代碼清單 16 截取日期元素

PostgreSQL MySQL

SELECT CURRENT_TIMESTAMP,
       EXTRACT(YEAR   FROM CURRENT_TIMESTAMP)  AS year,
       EXTRACT(MONTH  FROM CURRENT_TIMESTAMP)  AS month,
       EXTRACT(DAY    FROM CURRENT_TIMESTAMP)  AS day,
       EXTRACT(HOUR   FROM CURRENT_TIMESTAMP)  AS hour,
       EXTRACT(MINUTE FROM CURRENT_TIMESTAMP)  AS minute,
       EXTRACT(SECOND FROM CURRENT_TIMESTAMP)  AS second;

執行結果

           now             | year | month | day | hour | minute | second
---------------------------+------+-------+-----+------+--------+-------
2010-04-25 19:07:33.987+09 | 2010 |     4 |  25 |   19 |      7 | 33.987

需要注意的是 SQL Server 也無法使用該函數。

特定的 SQL

SQL Server 使用如下的 DATEPART 函數會得到與代碼清單 16 相同的結果。

KEYWORD

  • DATEPART 函數(SQL Server)

SQL Server

SELECT CURRENT_TIMESTAMP,
      DATEPART(YEAR   , CURRENT_TIMESTAMP) AS year,
      DATEPART(MONTH  , CURRENT_TIMESTAMP) AS month,
      DATEPART(DAY    , CURRENT_TIMESTAMP) AS day,
      DATEPART(HOUR   , CURRENT_TIMESTAMP) AS hour,
      DATEPART(MINUTE , CURRENT_TIMESTAMP) AS minute,
      DATEPART(SECOND , CURRENT_TIMESTAMP) AS second;

Oracle 和 DB2 想要得到相同結果的話,需要進行如下改變。注意事項與 CURRENT_DATE 時完全相同。

Oracle

-- 在FROM子句中指定臨時表(DUAL)
SELECT CURRENT_TIMESTAMP,
      EXTRACT(YEAR   FROM CURRENT_TIMESTAMP) AS year,
      EXTRACT(MONTH  FROM CURRENT_TIMESTAMP) AS month,
      EXTRACT(DAY    FROM CURRENT_TIMESTAMP) AS day,
      EXTRACT(HOUR   FROM CURRENT_TIMESTAMP) AS hour,
      EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) AS minute,
      EXTRACT(SECOND FROM CURRENT_TIMESTAMP) AS second
FROM DUAL;

DB2

/* CURRENT和TIME之間使用了半角空格,指定臨時表SYSIBM.SYSDUMMY1 */
SELECT CURRENT TIMESTAMP,
      EXTRACT(YEAR   FROM CURRENT TIMESTAMP) AS year,
      EXTRACT(MONTH  FROM CURRENT TIMESTAMP) AS month,
      EXTRACT(DAY    FROM CURRENT TIMESTAMP) AS day,
      EXTRACT(HOUR   FROM CURRENT TIMESTAMP) AS hour,
      EXTRACT(MINUTE FROM CURRENT TIMESTAMP) AS minute,
      EXTRACT(SECOND FROM CURRENT TIMESTAMP) AS second
FROM SYSIBM.SYSDUMMY1;

五、轉換函數

最后將要給大家介紹一類比較特殊的函數——轉換函數。雖說有些特殊,但是由於這些函數的語法和之前介紹的函數類似,數量也比較少,因此很容易記憶。

KEYWORD

  • 轉換函數

“轉換”這個詞的含義非常廣泛,在 SQL 中主要有兩層意思:一是數據類型的轉換,簡稱為類型轉換,在英語中稱為 cast [8];另一層意思是值的轉換。

KEYWORD

  • 類型轉換

  • cast

5.1 CAST——類型轉換

語法 14 CAST 函數

CAST(轉換前的值 AS 想要轉換的數據類型)

進行類型轉換需要使用 CAST 函數

KEYWORD

  • CAST 函數

之所以需要進行類型轉換,是因為可能會插入與表中數據類型不匹配的數據,或者在進行運算時由於數據類型不一致發生了錯誤,又或者是進行自動類型轉換會造成處理速度低下。這些時候都需要事前進行數據類型轉換(代碼清單 17、代碼清單 18)。

代碼清單 17 將字符串類型轉換為數值類型

SQL Server PostgreSQL

SELECT CAST('0001' AS INTEGER) AS int_col;

MySQL

SELECT CAST('0001' AS SIGNED INTEGER) AS int_col;

Oracle

SELECT CAST('0001' AS INTEGER) AS int_col
  FROM DUAL;

DB2

SELECT CAST('0001' AS INTEGER) AS int_col
  FROM SYSIBM.SYSDUMMY1;

執行結果

int_col
---------
      1

代碼清單 18 將字符串類型轉換為日期類型

SQL Server PostgreSQL MySQL

SELECT CAST('2009-12-14' AS DATE) AS date_col;

Oracle

SELECT CAST('2009-12-14' AS DATE) AS date_col
  FROM DUAL;

DB2

SELECT CAST('2009-12-14' AS DATE) AS date_col
  FROM SYSIBM.SYSDUMMY1;

執行結果

date_col
------------
2009-12-14

從上述結果可以看到,將字符串類型轉換為整數類型時,前面的“000”消失了,能夠切實感到發生了轉換。但是,將字符串轉換為日期類型時,從結果上並不能看出數據發生了什么變化,理解起來也比較困難。從這一點我們也可以看出,類型轉換其實並不是為了方便用戶使用而開發的功能,而是為了方便 DBMS 內部處理而開發的功能。

5.2 COALESCE——將 NULL 轉換為其他值

語法 15 COALESCE 函數

COALESCE(數據1,數據2,數據3……)

COALESCE 是 SQL 特有的函數。該函數會返回可變參數 [9] 中左側開始第 1 個不是 NULL 的值。參數個數是可變的,因此可以根據需要無限增加。

KEYWORD

  • COALESCE 函數

其實轉換函數的使用還是非常頻繁的。在 SQL 語句中將 NULL 轉換為其他值時就會用到轉換函數(代碼清單 19、代碼清單 20)。就像之前我們學習的那樣,運算或者函數中含有 NULL 時,結果全都會變為 NULL。能夠避免這種結果的函數就是 COALESCE

代碼清單 19 將 NULL 轉換為其他值

SQL Server PostgreSQL MySQL

SELECT COALESCE(NULL, 1)                  AS col_1,
       COALESCE(NULL, 'test', NULL)       AS col_2,
       COALESCE(NULL, NULL, '2009-11-01') AS col_3;

Oracle

SELECT COALESCE(NULL, 1)                  AS col_1,
       COALESCE(NULL, 'test', NULL)       AS col_2,
       COALESCE(NULL, NULL, '2009-11-01') AS col_3
  FROM DUAL;

DB2

SELECT COALESCE(NULL, 1)                  AS col_1,
       COALESCE(NULL, 'test', NULL)       AS col_2,
       COALESCE(NULL, NULL, '2009-11-01') AS col_3
  FROM SYSIBM.SYSDUMMY1;

執行結果

 col_1 | col_2 |    col_3
-------+-------+-----------
     1 |  test | 2009-11-01

代碼清單 20 使用 SampleStr 表中的列作為例子

SELECT COALESCE(str2, 'NULL')
  FROM SampleStr;

執行結果

 coalesce
----------
 rt
 def
 太郎
 'NULL'
 xyz
 'NULL'
 'NULL'
 'NULL'
 abc
 abc
 i

這樣,即使包含 NULL 的列,也可以通過 COALESCE 函數轉換為其他值之后再應用到函數或者運算當中,這樣結果就不再是 NULL 了。

此外,多數 DBMS 中都提供了特有的 COALESCE 的簡化版函數(如 Oracle 中的 NVL 等),但由於這些函數都依存於各自的 DBMS,因此還是推薦大家使用通用的 COALESCE 函數。

請參閱

(完)


  1. 參考文檔是 DBMS 手冊的一部分。大家也可以從介紹各種函數的書籍以及 Web 網站上獲取相關信息。 ↩︎

  2. 但是轉換函數中的 COALESCE 函數除外。 ↩︎

  3. 由於這和 Java 中連接字符串的方法相同,估計有些讀者已經比較熟悉了。 ↩︎

  4. MySQL 中還存在計算字符串長度的自有函數 CHAR_LENGTH↩︎

  5. 需要大家注意的是,該函數也存在和 LENGTH 函數同樣的多字節字符的問題。詳細內容請大家參考專欄“對 1 個字符使用 LENGTH 函數有可能得到 2 字節以上的結果”。 ↩︎

  6. 如果想要了解日期函數的詳細內容,目前只能查閱各個 DBMS 的手冊。 ↩︎

  7. 之前我們已經介紹過,在 SQL Server 中無法使用 CURRENT_DATECURRENT_TIME 函數。可能是因為在 SQL Server 中,CURRENT_TIMESTAMP 已經涵蓋了這兩者的功能吧。 ↩︎

  8. 類型轉換在一般的編程語言中也會使用,因此並不是 SQL 特有的功能。 ↩︎

  9. 參數的個數並不固定,可以自由設定個數的參數。 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM