码迷,mamicode.com
首页 > 其他好文 > 详细

insert into linksvr select VS insert into from linksvr

时间:2016-09-09 00:46:59      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

通过链接服务器将实例A上的数据写入实例B,通常有以下两种方式
--方案1:在实例A上执行
insert into LinkForB.B..TableB select * from TableA
--方案2:在实例B上执行
insert into TableB select * from LinkForA.A..TableA
目前接手的数据库,大量使用链接服务器来搬迁数据,并且使用者随心所欲。本地写入到链接服务器,从链接服务器读数据写入本地,从链接服务器读数据写入到另一链接服务器。更有坑爹的,本来是写入本地,却在本地的前面加上本地实例的链接服务器!
以前没有特别关注哪种方式更好,有在群里针对搬迁数据的方式请教过,有朋友建议最好采用pull的形式链接方式,即insert into TableB select * from LinkForA.A..TableA
直到看到这篇文章,结合自己遇到的问题,尝试分析通过链接服务器insert数据的区别
此处为了方便,我所创建的链接服务器[MY]实际是指向当前实例,但是不影响对结果的分析。
首先创建测试表,并在测试表上创建触发器

技术分享
USE TEST
GO
--创建测试表
CREATE TABLE [dbo].[Product](
[ProductID] INT,
[Name] [nvarchar](50),
[Remark] [nvarchar](50)
)
GO
--创建触发器
CREATE TRIGGER [dbo].[Product_TR]
ON [dbo]. [Product]
FOR INSERT
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRY
IF (select len(ProductID) from inserted)>0--当select查询只返回一个值时才能操作=、!=、<、<=、>、>=
BEGIN
PRINT one row
END
END TRY
BEGIN CATCH
PRINT 消息 +CONVERT(VARCHAR,ERROR_NUMBER())+,级别 +CONVERT(VARCHAR,ERROR_SEVERITY())
+,状态 +CONVERT(VARCHAR,ERROR_STATE())+,过程 +CONVERT(VARCHAR,ERROR_PROCEDURE())
+,第 +CONVERT(VARCHAR,ERROR_LINE())+
PRINT ERROR_MESSAGE()
END CATCH
END
GO
View Code

注意触发器脚本,是为了在批量插入数据,select...from inserted子查询返回多条记录,进行>操作出错。
插入数据检验

技术分享
--step1:插入1条数据,成功
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 1 [ProductID],[Name],one row
FROM [AdventureWorks2008R2].[Production].[Product]
--step2:插入5条数据,失败
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],more than one row
FROM [AdventureWorks2008R2].[Production].[Product]
--step3:插入5条数据到链接服务器,成功
INSERT [MY].[Test].[dbo].[Product]([ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],ToLink more than one row
FROM [AdventureWorks2008R2].[Production].[Product]
--Step4:从链接服务器获取5条数据再插入,失败
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],FromLink more than one row
FROM [MY].[AdventureWorks2008R2].[Production].[Product]
View Code

我们查看表中结果
技术分享
通过图中的Remark字段,可以看出step1和step3的语句执行成功,step2和step4的语句执行失败
step1:插入1条数据时,select...from inserted子查询返回1行值,它可和0进行比较(>),数据insert成功。
step2:插入5条数据时,select...from inserted子查询返回5行值,它不能和单一的0进行比较,触发器报错,整个insert语句失败。
step3:插入5条数据到链接服务器,竟然成功!对比前面的语句,说明insert into linksvr.db.sch.tb是一行一行的insert(因为表上有触发器,如果一次多行insert会报错)
step4:当从链接服务器获取5条数据,再insert失败!它近似等效于step2。
现在我们的问题是step3和step4到底哪个更高效?虽然此时我们已经知道,step3会拆分成单条写入,step4一次写入多条。为了让这两个语句正常执行,我们禁用表上的触发器

技术分享
--禁用/启用触发器
alter table [dbo].[Product]
disable trigger [Product_TR] --disable/enable
--查看触发器
select name,type_desc,create_date,modify_date,is_disabled from sys.triggers t
View Code

技术分享
开启跟踪,然后再次执行step3、step4中的语句

技术分享
INSERT [MY].[Test].[dbo].[Product]([ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],ToLink more than one row
FROM [AdventureWorks2008R2].[Production].[Product]
View Code

技术分享
在SPID=52窗口执行INSERT Linksvr SELECT TOP 5 FROM语句,链接服务器在SPID=55下执行,有5个RPC:Completed事件

技术分享
INSERT [Test].[dbo].[Product]( [ProductID],[Name],[Remark])
SELECT TOP 5 [ProductID],[Name],FromLink more than one row
FROM [MY].[AdventureWorks2008R2].[Production].[Product]
View Code

技术分享
在SPID=52窗口执行INSERT Tab SELECT TOP 5 FROM Linksvr语句,链接服务器在SPID=55的会话中执行,仅一个RPC:Completed事件
此时表中的数据如下
技术分享
此时全部将表写入到测试表 
技术分享
Duration字段可以看出insert linksvr要比insert select linksvr耗时些
profile启动跟踪,sys.traces 增加一新记录(status=1),暂停跟踪,原记录的status=0,停止跟踪,原记录删除
profile启动跟踪,sys.traces 增加一新记录(status=1)
SELECT * FROM sys.traces t
语句暂停跟踪
exec sp_trace_setstatus 2, 0
sys.traces 对应记录删除,profile如新创建的跟踪样(暂未开启)
profile启动跟踪,sys.traces 增加一新记录(status=1),暂停跟踪,原记录的status=0
语句启动跟踪
exec sp_trace_setstatus 2, 1
sys.traces 对应记录status=1,说明已启动,但是profile中依旧是暂停状态!
请问此时sys.traces 中的traceid=2的跟踪是否有开启,如果开启了它收集的数据在哪?
此时点击profile中的启动按钮,弹出"在进行修改之前,必须先停止活动跟踪。"
确定,profile恢复成初始状态!

insert into linksvr select VS insert into from linksvr

标签:

原文地址:http://www.cnblogs.com/Uest/p/5853977.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!