65.9K
CodeProject 正在变化。 阅读更多。
Home

SQL Server 2012 的 20 个激动人心的功能 – 第 1 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (71投票s)

2013年1月12日

CPOL

8分钟阅读

viewsIcon

384942

本文将讨论 SQL Server 2012 的 5 个功能,其余功能将在其他部分介绍。

引言
功能一(革命性):- 列存储索引
功能二(进化性):- 序列对象
功能三(革命性):- 分页
功能四(革命性):- 独立数据库
功能五(进化性):- 错误处理
接下来的 5 个功能是什么?

引言

SQL Server 2012 于 2012 年 4 月发布,并开始受到专业人士的青睐。每当微软推出新产品,我个人首先会问自己,它是否值得投入?是否值得花费客户辛苦赚来的钱来购买该产品?评估它的方法是将产品功能分为“革命性”和“进化性”。“革命性”意味着它是全新的事物,而“进化性”意味着之前已经存在某些东西,并且得到了改进。

在本文中,我将讨论 SQL Server 2012 中我个人喜欢的 20 个功能(我们可以在我的列表上达成一致),其中 7 个是革命性的,13 个是进化性的。本文分为 4 部分,每部分讨论 5 个功能。那么,让我们从前 5 个亮点功能开始。

功能一(革命性):- 列存储索引

列存储索引是一个出乎意料且出色的功能。第一次读到这个功能时,我简直惊呆了。您可以通过右键单击“索引”文件夹并选择“非聚集列存储索引”来获得此功能,如下图所示。

那么,让我们快速了解一下它到底做什么。现在的关系数据库是以“行”为单位存储数据的。这些行进一步存储在 8 KB 的页面大小中。

例如,您可以看到下图中有一个包含“Column1”和“Column2”两列的表。您可以看到数据是如何存储在两个页面中的,即“page1”和“page2”。“Page1”包含两行,“Page2”也包含两行。现在,如果您只想获取“column1”,则需要从两个页面(即“Page1”和“Page2”)中读取记录,请参见下图。

由于需要从两个页面中提取数据,因此性能会受到一定影响。

如果我们能以“列”为单位存储数据,就可以避免从多个页面提取数据。这就是列存储索引所做的。当您创建列存储索引时,它会将相同的列数据存储在同一个页面中。从下面的示意图中可以看出,现在我们只需要从一个页面中获取“column1”数据,而无需查询多个页面。

功能二(进化性):- 序列对象

这是一个不错的功能,我个人认为它只是模仿了 Oracle 的序列对象。看起来它只是一个“有就好”的功能,如果 Oracle 有,为什么 SQL Server 没有。序列对象根据规范生成唯一的数字序列。许多开发人员现在可能会想到,我们有类似“标识”列的东西。但最大的区别在于,序列对象独立于表,而标识列则附加到表。

下面是一个创建序列对象的简单代码。您可以看到我们创建了一个名为“MySeq”的序列对象,其规范如下:

  • 从 1 开始。
  • 以 1 递增。最小值应为零。
  • 最大值为 100。不循环表示一旦达到 100,就会抛出错误。
  • 如果您想从 0 重新开始,应提供“循环”。
  • “缓存 50”指定最多 50 个值已缓存,以减少 IO。如果您指定“无缓存”,它将在磁盘上进行输入输出。
create sequence MySeq as int
	start with 1  -- Start with value 1
	increment by 1-- Increment with value 1
	minvalue 0 -- Minimum value to start is zero
	maxvalue 100 -- Maximum it can go to 100
	no cycle -- Do not go above 100
	cache 50 -- Increment 50 values in memory rather than incrementing from 
IO

要递增值,我们需要调用以下 SELECT 语句。与标识列相比,这是另一个大的区别。在标识列中,当添加行时值会递增,而在这里我们需要显式调用。

SELECT NEXT VALUE FOR dbo.MySequence AS seq_no;

功能三(革命性):- 分页

有时您希望将大型结果集显示给最终用户。显示大型结果集的最佳方法是将其拆分,即应用分页。因此,开发人员曾使用“top”、“row_number”等方法来完成分页。但从 SQL Server 2012 开始,我们可以使用“OFFSET”和“FETCH”命令来实现分页。

例如,假设我们有以下客户表,其中包含 12 条记录。我们希望将记录拆分为 6 条和 6 条。

因此,分页是一个两步过程:

  • 首先使用“OFFSET”命令标记行的开始。
  • 然后使用“FETCH”命令指定要获取的行数。

您可以在下面的代码片段中看到,我们使用“OFFSET”从“0”位置标记了行的开始。一个非常重要的注意事项是,ORDER BY 子句对“OFFSET”命令是强制性的。

select * from
tblcustomer order by customercode
offset 0 rows – start from zero

在下面的代码片段中,我们指定要从“OFFSET”指定的“0”位置开始获取“6”行。

fetch next 6 rows only

现在,如果您运行上述 SQL,您应该会看到 6 行。

要获取接下来的 6 行,只需更改“OFFSET”位置。您可以在下面的代码片段中看到,我已将偏移量修改为 6。这意味着行的开始位置将从“6”开始。

select * from
tblcustomer order by customercode
offset 6 rows



fetch next 6 rows only

上面的代码片段显示了接下来的“6”条记录,输出如下所示。

功能四(革命性):- 独立数据库

对于那些经常面临 SQL Server 数据库迁移痛苦的人来说,这是一个很棒的功能。数据库迁移中最棘手的问题之一是用户帐户。SQL Server 用户要么存在于 Windows ADS 中,要么以 SQL Server 用户的方式存在于 SQL Server 级别。因此,当我们将 SQL Server 数据库从一个服务器迁移到另一个服务器时,必须重新创建这些用户。如果您有很多用户,您需要指定一个人专门为您创建一个个用户。

因此,从易于迁移的角度来看,其中一项要求是创建独立的数据库。换句话说,我们是否可以在数据库本身中包含元数据信息、安全信息等?这样,当我们迁移数据库时,就可以将所有内容一起迁移。这就是 SQL Server 2012 中引入的“独立”数据库。

创建独立数据库是一个 3 步过程:

步骤 1:- 首先,需要在 SQL Server 实例级别启用独立数据库。您可以通过右键单击 SQL Server 实例并将“启用独立数据库”设置为“true”来完成此操作。

您也可以使用以下 SQL 语句来实现此目的。

sp_configure 'show advanced options',1
GO
RECONFIGURE WITH OVERRIDE
GO
sp_configure 'contained database authentication', 1
GO
RECONFIGURE WITH OVERRIDE
GO

步骤 2 - 下一步是在数据库级别启用独立数据库。因此,当您创建一个新数据库时,将“包含类型”设置为“部分”,如下面的图所示。

您也可以使用以下 SQL 代码创建“包含”设置为“部分”的数据库。

CREATE DATABASE [MyDb]
CONTAINMENT = PARTIAL
ON PRIMARY
( NAME = N'My', FILENAME = N'C:\My.mdf')
LOG ON
( NAME = N'My_log', FILENAME =N'C:\My_log.ldf')

步骤 3:- 现在最后一步是测试“独立”数据库的基本功能是否正常工作。现在我们希望用户凭据成为数据库的一部分,因此我们需要将用户创建为“带密码的 SQL 用户”。

您可以使用以下脚本来实现此目的。

CREATE USER MyUser
WITH PASSWORD = 'pass@123';
GO

现在,如果您尝试使用创建的用户登录,您会收到一个错误,如下面的图所示。这证明该用户不在 SQL Server 级别。

现在单击“选项”并在“连接到数据库”中指定数据库名称,您应该能够登录,这证明用户是数据库的一部分,而不是 SQL Server 的一部分。

功能五(进化性):- 错误处理

作为一名开发人员,我个人在 C# 或 VB.NET 中使用“try/catch/throw”语法结构进行错误处理非常舒适。感谢 SQL Server 团队在 2005 年引入了“try/catch”结构,它与我作为开发人员在 C# 中进行错误处理的方式非常兼容。在 SQL Server 2005 之前,使用“IF”条件和“@error”代码处理错误简直是一场噩梦。下面是一个示例代码,展示了“try/catch”代码的样子。

begin try


declare @n int = 0;
set @n = 1/0;


end try


begin catch


print('divide by zero');
RAISERROR ( ‘Divide by zero‘, 16, 1) ;


end catch

但上面的代码中仍然让我不满意的是,在将错误传播回客户端时,我缺少“THROW”命令。我们仍然需要使用“RAISEERROR”,它可以完成工作,但缺乏“THROW”所具有的许多功能。例如,要抛出用户定义的错误消息,您需要在“sys.messages”表中进行条目。

下面的代码显示了带有“throw”的代码。

begin try
-- The code where error has occurred.
end try


begin catch
-- throw error to the client
Throw;
end catch

如果您想抛出带有用户定义消息的异常,可以使用以下代码。无需在“sys.messages”表中进行条目。

THROW 49903, 'User define exception.', 1

从 SQL Server 2012 开始,请使用“Throw”而不是“raiseerror”。从“throw”的功能来看,早晚“raiseerror”会被弃用。下面是一个比较表,解释了“throw”与“raiseerror”之间的区别。

  Throw RaiseError
用户和系统异常 只能生成用户异常。 可以生成用户和系统异常。
“Sys.Messages”表 可以提供临时文本,不需要在“Sys.Messages”表中进行条目。 需要在“Sys.Messages”表中进行条目。
原始异常。 原始异常会传播到客户端。 原始异常会丢失给客户端。

接下来的 5 个功能是什么?

在下一部分中,我们将讨论以下功能:https://codeproject.org.cn/Articles/561797/Top-20-exciting-features-of-SQL-Server-2012-Part-2  

功能六(进化性):- 用户定义角色

功能七(进化性):- Windows Server Core 支持

功能八(革命性):- 表格模型(SSAS)

功能九(革命性):- Power View

功能十(革命性):- DQS 数据质量服务 

如果您有机会,请访问我的网站,了解有关 .NET 和 SQL Server 面试问题和答案的视频。  

如需进一步阅读,请观看以下面试准备视频和分步视频系列。

© . All rights reserved.