目录
在SQL中,表的列被定义为存储特定类型的值,例如数字、日期或文本;这些被称为数据类型。有超过30种SQL Server数据类型可供选择,数据类型可能看起来令人生畏,但实际上,数据库中常用的只有几种。
一旦您大致了解了数据类型,它就不是一个复杂的主题。您还将了解为什么需要数据类型以及有这么多种类的原因。
在本文中,我们将介绍最常见的数据类型及其使用的最佳实践。
本课的所有示例均基于Microsoft SQL Server Management Studio和AdventureWorks2012数据库。
什么是SQL Server数据类型?
在我们进入SQL Server中使用的数据类型之前,我认为每个人都必须了解数据类型是什么,以及为什么需要在计算机中使用它们。
对于我们的示例,我们将讨论一个人。如果您正在考虑可以用来描述一个人的信息,您可能会考虑收集他们的姓名、出生日期、体重和孩子的数量。对于这些属性中的每一个,数据通常分为几类。
姓名以文本形式存储,生日以日历日期形式存储,重量以十进制值形式存储,子项数量以整数形式存储。这些值类别中的每一个都是一种数据类型。
SQL类型如何提供帮助
数据类型定义了可以存储在某个位置(例如数据库列)中的数据的特征。数据类型定义了可能接受的一组值。例如,SQL server中代表整数的INT类型只能接受整数,不允许使用十进制值。
这是一些人及其年龄的列表
年龄——只是文本值
你能看出这些年龄的问题吗?它们的格式都不一致。它们不仅难以阅读,而且对数据进行排序和计算也很困难。通过使用强制存储预期数据类型的SQL Server数据类型,我们可以获得更好的结果。这是同一张表,年龄显示为整数
符合INT数据类型的年龄
当年龄被定义为整数时,期望数据以整数形式输入。
此外,在不深入技术细节的情况下,您可以看到将年龄存储为整数比第一个表中的年龄占用的空间要少得多。对于小型数据库,这似乎不是一个重要的考虑因素,但在智能手机或“大数据”场景中处理数据时,这些考虑因素会加起来。
一旦系统理解了数据类型,它就可以按照有意义的顺序对数据进行排序并执行计算。
使用SQL Server数据类型的原因
以下是数据类型如此重要的一些原因:
- 数据以一致且已知的格式存储。
- 了解数据类型可以让您知道可以在列上使用哪些计算和公式。
- 数据类型影响存储。当存储在一种数据类型中而不是另一种时,某些值会占用更多空间。以我们上面的年龄表为例。
- 数据类型会影响性能。数据库推断值或转换它们的时间越少越好。“2015年12月32日是日期吗?”
常用的SQL Server数据类型
在SQL中,您可以定义在列中存储哪种数据。一些示例包括文本或数字数据。
这是列的数据类型,也是它最重要的属性之一,因为它单独决定了一个值是否对存储在列中有效。
在定义列时,您可以选择三十多种不同的数据类型,其中一些具有特定用途,例如存储图像。
在本文中,我们将介绍您在日常使用SQL时最常遇到的七种数据类型。
INT – 整数数据类型
整数数据类型存储整数。示例包括-23、0、5 和 10045。整数不包括小数位。由于SQL服务器使用许多计算机字来表示整数,因此它可以表示最大值和最小值。INT数据类型可以存储从-2,147,483,648到2,147,483,647的值。
INT数据类型的实际用途包括使用它来计算值、存储人的年龄或用作表的ID键。
但是INT不能很好地跟踪TB的硬盘地址空间,因为INT数据类型只有20亿,我们需要跟踪到数万亿。为此,您可以使用BIGINT。
INT数据类型在计算中使用。由于DaysToManufacture定义为INT,我们可以通过将其乘以24轻松计算小时数:
/* Answer */
SELECT Name,
DaysToManufacture,
DaysToManufacture * 24 as HoursToManufacture
FROM Production.Product
在这里你可以看到结果
INT计算结果
有许多操作和函数可以用于整数,一旦我们深入研究函数,我们将介绍这些操作和函数。
VARCHAR和NVARCHAR – 文本值
使用VARCHAR和NVARCHAR存储可变长度的文本值。“VARCHAR”代表变长字符。
在定义列时指定要存储在VARCHAR或NVARCHAR中的字符数。请注意Name是如何定义为容纳50个字符的:
SSMS对象资源管理器中显示的VARCHAR定义
流行的是VARCHAR小于50个字符的值占用更少的空间。根据需要分配空间。这与总是分配指定长度的CHAR数据类型不同,而不管存储的实际数据的长度如何。
该VARCHAR数据类型通常最多可存储8,000个字符。使用NVARCHAR数据类型存储Unicode文本。由于UNICODE字符占用空间的两倍,NVARCHAR列最多可存储4,000个字符。
NVARCHAR于VARCHAR的优势在它可以存储Unicode字符。这使得存储扩展字符集(如用于汉字等语言的字符集)变得很方便。
SQL 2008之前设计的数据库通常使用VARCHAR; 但是,更现代的数据库或那些全球性的数据库倾向于使用NVARCHAR。
DATETIME – 日期和时间
使用DATETIME数据类型存储日期和时间。一个DATATIME值的例子是
1968-10-23 1:45:37.123
这是1968年10月23日凌晨1:45的值。实际上,时间比这更精确。真的时间是45分37.123秒。
在许多情况下,您只需要存储日期。在这些情况下,时间分量被清零。因此,1972年11月5日是
1972-11-05 00:00:00.000
DATETIME可以存储从1753年1月1日到9999年12月31日的日期。这有助于DATETIME记录当今世界的日期,但在威廉莎士比亚的作品中却没有那么多。
随着您越来越熟悉各种SQL内置函数,您将能够操作数据。为了让您一目了然,我们将使用该YEAR功能来计算每年雇用的员工人数。当给定一个DATETIME值时,该YEAR函数返回年份。
我们将使用的查询是
/* Answer */
SELECT YEAR(HireDate) HireDateYear,
Count(*) HireDateCount
FROM HumanResources.Employee
GROUP BY YEAR(HireDate)
ORDER BY YEAR(HireDate)
好处是DATETIME类型确保值是有效日期。一旦确定了这一点,我们就可以使用大量函数来计算日期之间的天数、日期的月份等。
我们将在另一篇博客文章中详细探讨这些不同的功能。
DECIMAL和FLOAT – 小数点
同时使用DECIMAL和FLOAT数据类型来处理十进制值,例如10.3。
我将它们DECIMAL和FLOAT归为同一类,因为它们都可以处理带小数点的值;但是,它们的做法不同:
如果您需要精确的值,例如在处理财务或会计数据时,请使用DECIMAL。原因是DECIMAL数据类型允许您定义要维护的小数点数。
DECIMAL
DECIMAL数据类型由精度和小数位数定义。精度决定了要存储的总位数;而scale确定小数点右侧的位数。
DECIMAL数据类型指定为DECIMAL(precision,scale)。
DECIMAL数据类型不能超过38位。精度和比例必须符合以下关系
0 <= scale <= precision <= 38 digits
在Production.Product表中,权重列的数据类型定义为DECIMAL(8,2)。第一个数字是精度,第二个数字是比例。
重量被定义为共有八位数字,其中两位在小数点右侧。我们将通过以下示例查询来说明这种数据类型如何。
/* Answer */
SELECT DISTINCT Weight
FROM Production.Product
WHERE Weight BETWEEN 29.00 and 189.00
ORDER BY Weight DESC
FLOAT
数据DECIMAL类型非常适合精确数字,而FLOAT 非常适合长数值。尽管一个DECIMAL值总共可以有38位数字,但在许多工程和科学应用中这是不够的。在遇到极端数值的科学应用中,FLOAT上升到了顶峰!
浮点数的范围从– 1.79E+308到1.79E+308。这意味着最大值可以是179,后跟306个零(确实很大!)。
由于浮点数据在计算机中的存储方式(参见IEEE 754浮点规范),存储的数字非常接近。对于许多应用程序来说,这已经足够了。
由于近似行为,请避免在WHERE子句中使用<>和=运算符。这句话已经烧毁了可能的DBA!
WHERE mass = 2.5
当质量应该等于2.5时,他们的期望破灭了,但实际上,在计算机上,它存储为2.499999999999999;因此,不等于2.500000000000000!
这就是浮点数和计算机的本质。你和我看到2.499999999999999并认为出于实际目的它是2.5,但对计算机来说,只是稍微偏离了一点。
BIT – 布尔值或是/否值
有时您只需要存储某物是“是”还是“不是”。例如,员工是否活跃。正是在这些情况下,BIT数据类型才出现。此数据类型是以下三种状态之一:1、0或NULL。
值1表示TRUE,0表示FALSE。
在此查询中,我们列出了所有带薪职位职位
SELECT DISTINCT JobTitle
FROM HumanResources.Employee
WHERE SalariedFlag = 1
我们也可以使用'True'而不是1。这是使用'True'的相同示例
SELECT DISTINCT JobTitle
FROM HumanResources.Employee
WHERE SalariedFlag = 'True'
相反使用'False'
SELECT DISTINCT JobTitle
FROM HumanResources.Employee
WHERE SalariedFlag = 'False'
我倾向于坚持使用1和0,因为它更容易输入,但如果你想要可读性,那么“True”和“False”是不错的选择。