多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
在本节中,我们将介绍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; ~~~ 执行上面查询,得到以下结果: ![](https://www.yiibai.com/uploads/article/2019/02/12/222852_64636.png) 即使字符`“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; ~~~ 执行上面查询语句,得到以下结果: ![](https://www.yiibai.com/uploads/article/2019/02/12/224538_97141.png) * [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发出错误并终止了该语句: ![](https://www.yiibai.com/uploads/article/2019/02/12/225541_12747.png) 要查找存储在`VARCHAR`列中的字符数和字节数,可以使用`LEN`和`DATALENGTH`函数,如以下查询所示: ![](https://www.yiibai.com/uploads/article/2019/02/12/225637_56276.png) * [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发出错误并终止了该语句: ![](https://www.yiibai.com/uploads/article/2019/02/13/091726_60169.png) 要查找存储在`NVARCHAR`列中的值的字符数和存储大小(以字节为单位),请使用`LEN`和`DATALENGTH`函数,如下所示: ~~~sql SELECT val, LEN(val) len, DATALENGTH(val) data_length FROM test.sql_server_nvarchar; ~~~ 执行上面查询语句,得到以下结果: ![](https://www.yiibai.com/uploads/article/2019/02/13/092336_91194.png) * [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' ); ~~~