在本節中,我們將介紹SQL Server內置的數據類型。一些常用的主要數據類型如下所示:
* [BIT]- 使用BIT數據類型在數據庫中存儲位數據,即:`0`,`1`或`NULL`。
* [INT] - 了解SQL服務器中的各種整數類型,包括:`BIGINT`,`INT`,`SMALLINT`和`TINYINT`。
SQL Server支持標準SQL整數類型,包括:`BIGINT`,`INT`,`SMALLINT`和`TINYINT`。 下表說明了每種整數類型的范圍和存儲:
| 數據類型 | 數值范圍 | 存儲 |
| --- | --- | --- |
| BIGINT | `-2^63` 至 `2^63 -1` | 8位 |
| INT | `-2^31` 至 `2^31 -1` | 4位 |
| SMALLINT | `-2^15` 至 `2^15 -1` | 2位 |
| TINYINT | `0` 至 `255` | 1位 |
最好使用可以可靠地包含所有可能值的最小整數數據類型。 例如,要存儲一個家庭中的孩子數量,`TINYINT`類型就足夠了,因為現在沒有人可以擁有超過`255`個孩子。 然而,`TINYINT`不足以存儲建筑物數量,因為建筑物數量可以有超過`255`個。
* [DECIMAL] - 演示如何使用`DECIMAL`或`NUMERIC`數據類型在數據庫中存儲精確數值。
要存儲具有固定精度和比例的數字,請使用`DECIMAL`數據類型。
以下是`DECIMAL`數據類型的語法:
~~~sql
DECIMAL(p,s)
~~~
在上面的語法中,
* `p`是指有效位數(精度),它是將存儲的小數位總數,包括小數點的左側和右側。 精度范圍為`1`到`38`。默認精度為`38`。
* `s`是小數位數(刻度),它是指定存儲在小數點右側的小數位數。刻度范圍從`0`到`p`。 只有在指定精度時才能指定刻度。 默認情況下,刻度為零。
存儲大小因精度而異,如下表所示:
| 精度 | 存儲字節 |
| --- | --- |
| `1 – 9` | `5` |
| `10-19` | `9` |
| `20-28` | `13` |
| `29-38` | `19` |
`NUMERIC`和`DECIMAL`是同義詞,因此可以互換使用它們。
以下聲明是等效的:
~~~sql
DECIMAL(10,2)
NUMERIC(10,2)
~~~
因為`DECIMAL`的ISO同義詞是`DEC`和`DEC(p,s)`,所以可以使用`DECIMAL`或`DEC`:
~~~sql
DECIMAL(10,2)
DEC(10,2)
~~~
## SQL Server DECIMAL示例
下面舉一個使用`DECIMAL`和`NUMERIC`數據類型的例子。
首先,創建一個包含兩列的新表:一個小數和一個數字:
~~~sql
CREATE TABLE test.sql_server_decimal (
dec_col DECIMAL (4, 2),
num_col NUMERIC (4, 2)
);
~~~
其次,向`test.sql_server_decimal`表中插入一個新行:
~~~sql
INSERT INTO test.sql_server_decimal (dec_col, num_col)
VALUES
(10.05, 20.05);
~~~
第三,查詢表中的數據:
~~~sql
SELECT
dec_col,
num_col
FROM
test.sql_server_decimal;
~~~
第四,以下示例嘗試向表中插入一個新行,其值超過列定義中指定的精度和小數位數:
~~~sql
INSERT INTO test.sql_server_decimal (dec_col, num_col)
VALUES
(99.999, 12.345);
~~~
SQL Server發出錯誤并終止了該語句執行:
Arithmetic overflow error converting numeric to data type numeric. The statement has been terminated
* [CHAR] - 了解如何在數據庫中存儲固定長度的非`Unicode`字符串。
## CHAR數據類型簡介
在SQL Server中,如果要存儲固定長度的非Unicode字符串數據,請使用`CHAR`數據類型:
~~~sql
CHAR(n)
~~~
在此語法中,`n`指定字符串長度,范圍從`1`到`8000`。
因為`n`是可選的,如果不在數據定義或變量聲明語句中指定它,則其默認值為`1`。
僅當在列中值的大小固定時,才應使用`CHAR`數據類型。
將字符串值插入`CHAR`列時。 如果字符串值的長度小于列中指定的長度,SQL Server將向字符串值添加尾隨空格到列中聲明的長度。 但是,當查詢選擇此字符串值時,SQL Server會在返回之前刪除尾隨空格。
另一方面,如果插入長度超過列長度的值,SQL Server將發出錯誤消息。
請注意,`CHAR`的ISO同義詞是`CHARACTER`,可以互換使用它們。
## CHAR數據類型示例
以下語句創建一個包含`CHAR`列的新表:
~~~sql
CREATE TABLE test.sql_server_char (
val CHAR(3)
);
~~~
請注意,如果數據庫中沒有`test`模式,則可以在創建`sql_server_char`表之前使用以下語句創建它:
~~~sql
CREATE SCHEMA test;
GO
~~~
要將固定長度的字符串插入`CHAR`列,請使用[INSERT]語句,如下所示:
~~~sql
INSERT INTO test.sql_server_char (val)
VALUES
('ABC');
~~~
上面語句按預期那樣工作。以下語句嘗試插入長度超過列長度的新字符串:
~~~sql
INSERT INTO test.sql_server_char (val)
VALUES ('XYZ1');
~~~
SQL Server發出以下錯誤:
~~~sql
String or binary data would be truncated.
The statement has been terminated.
~~~
以下語句將單個字符插入`test.sql_server_char`表的`val`列:
~~~sql
INSERT INTO test.sql_server_char (val)
VALUES
('A');
~~~
在SQL Server中,`LEN`函數返回指定列中排除尾隨空白的字符數,`DATALENGTH`函數返回字節數。
請參閱以下語句:
~~~sql
SELECT
val,
LEN(val) len,
DATALENGTH(val) data_length
FROM
sql_server_char;
~~~
執行上面查詢,得到以下結果:

即使字符`“A”`只是一個字符,列的字節數也是固定的,即:`3`
* [NCHAR]- 演示如何存儲固定長度的`Unicode`字符串,并解釋`CHAR`和`NCHAR`數據類型之間的區別。
要在數據庫中存儲固定長度的Unicode字符串數據,請使用SQL Server NCHAR數據類型:
~~~sql
NCHAR(n)
~~~
在此語法中,`n`指定字符串長度,范圍從`1`到`4000`。 `NCHAR`值的存儲大小是`n`個字節的兩倍。
`NCHAR`的ISO同義詞是`NATIONAL CHAR`和`NATIONAL CHARACTER`,因此可以互換使用它們。
與`CHAR`數據類型類似,只能使用`NCHAR`存儲固定長度的字符串。如果數據值的長度是可變的,則應考慮使用`VARCHAR`或`NVARCHAR`數據類型。
## CHAR與NCHAR比較
以下是`CHAR`和`NCHAR`數據類型之間的主要區別:
| CHAR | NCHAR |
| --- | --- |
| 僅存儲非Unicode字符。 | 以UNICODE UCS-2字符的形式存儲Unicode字符。 |
| 需要`1`個字節來存儲一個字符。 | 需要`2`個字節來存儲一個字符。 |
| 存儲大小等于列定義或變量聲明中指定的大小。 | 存儲大小等于列定義或變量聲明中指定的大小的兩倍。 |
| 最多可存儲`8000`個字符。 | 最多可存儲4000個字符。 |
## SQL Server NCHAR示例
以下語句是用來創建一個包含一個`NCHAR`列的新表:
~~~sql
CREATE TABLE test.sql_server_nchar (
val NCHAR(1) NOT NULL
);
~~~
以下[INSERT語句]將中文漢字:`"易"`插入`NCHAR`列:
~~~sql
INSERT INTO test.sql_server_nchar (val)
VALUES
(N'易');
~~~
請注意,必須在Unicode字符串常量前加上字母`N`前綴。否則,SQL Server會將字符串轉換為數據庫的默認代碼頁,這可能無法識別某些特定的Unicode字符。
如果插入長度大于列定義中指定長度的字符串,SQL Server將發出錯誤并終止該語句。
例如,以下語句嘗試將包含兩個字符的字符串插入`test.sql_server_nchar`表的`val`列中:
~~~sql
INSERT INTO test.sql_server_nchar (val)
VALUES
(N'易百');
~~~
SQL Server發出以下錯誤消息:
~~~sql
消息 8152,級別 16,狀態 13,第 1 行
將截斷字符串或二進制數據。
語句已終止。
~~~
要查找`val`列的字符數和字節數,可以使用`LEN`和`DATALENGTH`函數,如下所示:
~~~sql
SELECT
val,
len(val) length,
DATALENGTH(val) data_length
FROM
test.sql_server_nchar;
~~~
執行上面查詢語句,得到以下結果:

* [VARCHAR] - 在數據庫中存儲可變長度的非`Unicode`字符串數據。
## Varchar數據類型簡介
SQL Server `VARCHAR`數據類型用于存儲可變長度的非Unicode字符串數據。以下是它的語法:
~~~sql
VARCHAR(n)
~~~
在此語法中,`n`定義字符串長度,范圍從`1`到`8000`。 如果未指定`n`,則其默認值為`1`。
聲明`VARCHAR`列的另一種方法是使用以下語法:
~~~sql
VARCHAR(max)
~~~
在此語法中,`max`定義最大存儲大小`2^31 -1`字節(2GB)。
通常,`VARCHAR`值的存儲大小是存儲數據的實際長度加上`2`個字節。
`VARCHAR`的ISO同義詞是`CHARVARYING`或`CHARACTERVARYING`,因此可以互換使用它們。
## Varchar數據類型示例
以下語句用來創建一個包含一個`VARCHAR`列的新表:
~~~sql
CREATE TABLE test.sql_server_varchar (
val VARCHAR NOT NULL
);
~~~
因為沒有指定`val`列的字符串長度,所以它默認為`1`。
要更改`val`列的字符串長度,請使用`ALTER TABLE ALTER COLUMN`語句,例如要修改它的長度為`10`,可使用以下語句:
~~~sql
ALTER TABLE test.sql_server_varchar
ALTER COLUMN val VARCHAR (10) NOT NULL;
~~~
以下語句將新字符串插入`test.sql_server_varchar`表的`val`列中:
~~~sql
INSERT INTO test.sql_server_varchar (val)
VALUES
('SQL Server');
~~~
該語句按預期那樣工作,因為字符串值的長度等于列定義中定義的長度。
以下語句嘗試插入長度大于列的字符串長度的新字符串數據:
~~~sql
INSERT INTO test.sql_server_varchar (val)
VALUES
('SQL Server VARCHAR');
~~~
SQL Server發出錯誤并終止了該語句:

要查找存儲在`VARCHAR`列中的字符數和字節數,可以使用`LEN`和`DATALENGTH`函數,如以下查詢所示:

* [NVARCHAR] - 了解如何在表中存儲可變長度的`Unicode`字符串數據,并了解`VARCHAR`和`NVARCHAR`之間的主要區別。
SQL Server `NVARCHAR`數據類型用于存儲可變長度的Unicode字符串數據。 以下是`NVARCHAR`的語法:
~~~sql
NVARCHAR(n)
~~~
在此語法中,`n`定義字符串長度,范圍從`1`到`4000`。 如果未指定字符串長度,則其默認值為`1`。
聲明`NVARCHAR`列的另一種方法是使用以下語法:
~~~sql
NVARCHAR(max)
~~~
在此語法中,`max`是以字節為單位的最大存儲大小,即`2^31 - 1`個字節(2GB)。
通常,`NVARCHAR`值的實際存儲大小(以字節為單位)是輸入的字符數加上`2`個字節的兩倍。
`NVARCHAR`的ISO同義詞是`NATIONAL CHAR VARYING`或`NATIONAL CHARACTER VARYING`,因此可以在變量聲明或列數據定義中互換使用它們。
## VARCHAR與NVARCHAR比較
下表說明了`VARCHAR`和`NVARCHAR`數據類型之間的主要區別:
| 比較項 | VARCHAR | NVARCHAR |
| --- | --- | --- |
| 字符數據類型 | 可變長度的非Unicode字符 | 可變長度,Unicode和非Unicode字符,如:中文,日語和韓語。 |
| 最大長度 | 最多`8000`個字符 | 最多`4000`個字符 |
| 字符大小 | 每個字符占用`1`個字節 | 每個Unicode/非Unicode字符占用`2`個字節 |
| 使用 | 當數據長度為可變或可變長度列且實際數據始終小于容量時使用。 | 僅限存儲,僅在需要Unicode支持時使用,例如:漢字,日語或韓文字符。 |
## SQL Server VARCHAR示例
以下語句創建一個包含一個`VARCHAR`列的新表:
~~~sql
CREATE TABLE test.sql_server_nvarchar (
val NVARCHAR NOT NULL
);
~~~
在此示例中,默認情況下`NVARCHAR`列的字符串長度為`1`。
要更改`val`列的字符串長度,請使用`ALTER TABLE ALTER COLUMN`語句:
~~~sql
ALTER TABLE test.sql_server_Nvarchar
ALTER COLUMN val NVARCHAR (10) NOT NULL;
~~~
以下語句將新字符串插入`test.sql_server_nvarchar`表的`val`列:
~~~sql
INSERT INTO test.sql_server_Nvarchar (val)
VALUES
(N'易百教程網');
~~~
該語句按預期工作,因為字符串值的長度小于列定義中定義的字符串長度。
以下語句嘗試插入長度大于`val`列的字符串長度的新字符串數據:
~~~sql
NSERT INTO test.sql_server_nvarchar (val)
VALUES
(N'訪問易百教程學習新技術');
~~~
SQL Server發出錯誤并終止了該語句:

要查找存儲在`NVARCHAR`列中的值的字符數和存儲大小(以字節為單位),請使用`LEN`和`DATALENGTH`函數,如下所示:
~~~sql
SELECT
val,
LEN(val) len,
DATALENGTH(val) data_length
FROM
test.sql_server_nvarchar;
~~~
執行上面查詢語句,得到以下結果:

* [DATETIME2] - 介紹如何將日期和時間數據存儲在數據庫中。
要在數據庫中存儲日期和時間,請使用SQL Server `DATETIME2`數據類型。
`DATETIME2`的語法如下:
~~~sql
DATETIME2(fractional seconds precision)
~~~
* `precision` - 小數秒精度是可選的,范圍從`0`到`7`。
以下語句說明了如何創建包含`DATETIME2`列的表:
~~~sql
CREATE TABLE table_name (
...
column_name DATETIME2(3),
...
);
~~~
`DATETIME2`有兩個組成部分:日期和時間。
* 日期范圍為1月01日(`0001-01-01`)至12月31日(`9999-12-31`)
* 時間范圍為`00:00:00`至`23:59:59.9999999`。
`DATETIME2`值的存儲大小取決于小數秒精度。 對于小于`3`的精度,它需要`6`個字節,對于`3`到`4`之間的精度,它需要`7`個字節,對于所有其他精度,它需要`8`個字節。
`DATETIME2`的默認字符串文字格式如下:
~~~sql
YYYY-MM-DD hh:mm:ss[.fractional seconds]
~~~
在上面的格式中,
* `YYYY`是一個四位數字,代表年份。例如`2018`,它的范圍從`0001`到`9999`。
* `MM`是一個兩位數的數字,代表一年中的月份。例如`12`,它的范圍從`01`到`12`。
* `DD`是一個兩位數的數字,代表指定月份的第幾天。例如`23`。它的范圍從`01`到`31`。
* `hh`是一個代表小時的兩位數字。它的范圍從`00`到`23`。
* `mm`是代表分鐘的兩位數字。 范圍從`00`到`59`。
* `ss`是一個兩位數字,表示秒數。 范圍從`00`到`59`。
* `fractional seconds`表示秒小數點值,它是`0`到`7`位數字。范圍從`0`到`9999999`。
## SQL Server DATETIME2示例
以下語句創建一個新表,其中包含一個`created_at`列,它的數據類型為`DATETIME2`:
~~~sql
CREATE TABLE test.product_colors (
color_id INT PRIMARY KEY IDENTITY,
color_name VARCHAR (50) NOT NULL,
created_at DATETIME2
);
~~~
要將當前日期和時間插入`created_at`列,請將以下`INSERT`語句與`GETDATE()`函數一起使用:
~~~sql
INSERT INTO test.product_colors (color_name, created_at)
VALUES
('紅色', GETDATE());
~~~
`GETDATE()`函數類似于其他數據庫系統(如MySQL)中的`NOW()`函數。要將文字值插入`DATETIME2`列,請使用以下語句:
~~~sql
INSERT INTO test.product_colors (color_name, created_at)
VALUES
('紅色', '2020-06-23 09:36:37');
~~~
如果要將`created_at`列的默認值設置為當前日期和時間,請使用以下`ALTER TABLE`語句:
~~~sql
ALTER TABLE production.product_colors
ADD CONSTRAINT df_current_time
DEFAULT CURRENT_TIMESTAMP FOR created_at;
~~~
在此語句中,使用`CURRENT_TIMESTAMP`作為`created_at`列的默認值。 請注意,`CURRENT_TIMESTAMP`返回的值與`GETDATE()`函數返回的值相同。
現在,當向表中插入新行而未指定`created_at`列的值時,SQL Server將使用該列的當前日期和時間值:
~~~sql
INSERT INTO production.product_colors (color_name)
VALUES
('藍色');
~~~
* [DATE] - 介紹日期數據類型以及如何在表格中存儲日期。
要將日期數據存儲在數據庫中,請使用SQL Server `DATE`數據類型。`DATE`的語法如下:
~~~sql
DATE
~~~
與`DATETIME2`數據類型不同,`DATE`數據類型只有日期組件。 `DATE`值的范圍是從1月1日(`0001-01-01`)到12月31日(`9999-12-31`)。
存儲`DATE`值需要`3`個字節。 `DATE`值的默認文字字符串格式如下:
~~~sql
YYYY-DD-MM
~~~
在上面格式中,
* `YYYY`是代表年份的四位數。 范圍從`0001`到`9999`。
* `MM`是兩位數,表示一年中的月份。 范圍從`01`到`12`。
* `DD`是兩位數字,代表指定月份的第幾天。 它的范圍從`01`到`31`,具體取決于月份。
## SQL Server DATE示例
以下語句創建一個名為`test.list_prices`的表,該表具有兩個`DATE`列:
~~~sql
CREATE TABLE sales.list_prices (
product_id INT NOT NULL,
valid_from DATE NOT NULL,
valid_to DATE NOT NULL,
amount DEC (10, 2) NOT NULL,
PRIMARY KEY (
product_id,
valid_from,
valid_to
),
FOREIGN KEY (product_id) REFERENCES production.products (product_id)
);
~~~
以下[INSERT]語句說明了如何將包含文字日期值的行插入表中:
~~~sql
INSERT INTO sales.list_prices (
product_id,
valid_from,
valid_to,
amount
)
VALUES
(
1,
'2020-01-01',
'2020-12-31',
400
);
~~~
* [TIME] - 演示如何使用`TIME`數據類型將時間數據存儲在數據庫中。
SQL Server `TIME`數據類型根據24小時制定義一天的時間。 `TIME`數據類型的語法如下:
~~~sql
TIMET [ (fractional second scale) ]
~~~
小數秒標度(`fractional second scale`)指定秒的小數部分的位數。 小數秒標度范圍為`0`到`7`。默認情況下,如果未明確指定,則小數秒標度為`7`。
以下示例說明如何使用`TIME`列創建表:
~~~sql
CREATE TABLE table_name(
...,
start_at TIME(0),
...
);
~~~
`TIME`值的默認文字格式是:
~~~sql
hh:mm:ss[.nnnnnnn]
~~~
在上面的格式中:
* `hh`是兩位數,代表小時,范圍從`0`到`23`。
* `mm`是兩位數,表示分鐘,范圍從`0`到`59`。
* `ss`是兩位數,表示秒數,范圍從`0`到`59`。
* `.nnnnnnn`表示秒的小數部分,可以是`0`到`7`位,范圍從`0`到`9999999`。
默認值為`100ms`小數秒精度的時間值,需要`5`個字節的存儲空間。
請注意,`TIME`數據類型不是時區。
## SQL Server TIME數據類型示例
以下語句創建一個名為`sales.visits`的表,其中包含兩個`TIME`列,用于記錄客戶對商店的訪問時間:
~~~sql
CREATE TABLE sales.visits (
visit_id INT PRIMARY KEY IDENTITY,
customer_name VARCHAR (50) NOT NULL,
phone VARCHAR (25),
store_id INT NOT NULL,
visit_on DATE NOT NULL,
start_at TIME (0) NOT NULL,
end_at TIME (0) NOT NULL,
FOREIGN KEY (store_id) REFERENCES sales.stores (store_id)
);
~~~
以下[INSERT]語句向`sales.visits`表插入一行:
~~~sql
INSERT INTO sales.visits (
customer_name,
phone,
store_id,
visit_on,
start_at,
end_at
)
VALUES
(
'Maxsu',
'(+86)18318303853',
1,
'2020-08-23',
'10:10:00',
'10:35:00'
);
~~~
- 第三章-數據庫
- 3.1 SQL Server簡介及安裝
- 3.2 SQL Server示例數據庫
- 3.3 SQL Server 加載示例
- 3.3 SQL Server 中的數據類型
- 3.4 SQL Server 數據定義語言DDL
- 3.5 SQL Server 修改數據
- 3.6 SQL Server 查詢數據
- 3.7 SQL Server 連表
- 3.8 SQL Server 數據分組
- 3.9 SQL Server 子查詢
- 3.10.1 SQL Server 集合操作符
- 3.10.2 SQL Server聚合函數
- 3.10.3 SQL Server 日期函數
- 3.10.4 SQL Server 字符串函數