Linked Server简介

我们日常使用SQL Server数据库时,经常遇到需要在实例Instance01中跨实例访问Instance02中的数据。例如在做数据迁移时,如下语句:

insert into Instance01.DB01.dbo.Table01
select * from Instance02.DB01.dbo.Table01

普通情况下,这样做是不允许的,因为SQL Server默认不可以跨实例访问数据。解决方案是使用存储过程sp_addlinkedserver进行实例注册。

链接服务器让用户可以对 OLE DB 数据源进行分布式异类查询。在创建某一链接服务器后,可对该服务器运行分布式查询,并且查询可以联接来自多个数据源的表。如果链接服务器定义为 SQL Server 实例,则可执行远程存储过程。链接服务器具有以下优点:

  • 能够访问 SQL Server之外的数据。
  • 能够对企业内的异类数据源发出分布式查询、更新、命令和事务。
  • 能够以相似的方式确定不同的数据源。
Linked Server组件

链接服务器定义指定了下列对象:

  • OLE DB 访问接口
  • OLE DB 数据源

“OLE DB 访问接口” 是管理特定数据源并与其交互的 DLL。 “OLE DB 数据源” 标识可通过 OLE DB 访问的特定数据库。 虽然通过链接服务器定义查询的数据源通常是数据库,但 OLE DB 访问接口对各种文件和文件格式仍可用。 这些文件和文件格式包括文本文件、电子表格数据和全文内容搜索的结果。

Microsoft SQL Server本机客户端 OLE DB 访问接口 (PROGID: SQLNCLI11) 是 SQL Server 的正式 OLE DB 访问接口。

通常,链接服务器用于处理分布式查询。 当客户端应用程序通过链接服务器执行分布式查询时, SQL Server 将分析命令并向 OLE DB 发送请求。 为使数据源能通过链接服务器返回数据,该数据源的 OLE DB 访问接口 (DLL) 必须与 SQL Server 的实例位于同一服务器上

Linked Server的安全性

当用户登录到本地服务器并执行分布式查询,以访问链接服务器上的表时,本地服务器必须登录链接服务器上,代表该用户访问该表。使用存储过程sp_addlinkedsrvlogin来指定本地服务器用于登录链接服务器的登录凭据。

例如,使用远程密码 8r4li034j7$ 为链接服务器 S1 建立了一个从本地登录名 U1 到远程登录名 U2 的映射(如在SQL Server中使用sa账户登录到远程oracle服务器的sys账户)。在本地登录名 U1 执行访问链接服务器 S1 中存储的表的分布式查询时,如果 SQL Server 连接到链接服务器 S1,则将 U2 和 8r4li034j7$ 分别作为用户 ID 和密码进行传递。

本地服务器上的所有登录和链接服务器上的远程登录之间的默认映射通过执行 sp_addlinkedserver 自动创建。默认映射表示,当代表本地登录连接到链接服务器时,SQL Server 使用本地登录的用户凭据。这相当于在链接服务器的 @useself 设置为 true 的情况下执行 sp_addlinkedsrvlogin,无需指定本地用户名。

创建或更新 SQL Server 本地实例上的登录名与远程服务器中安全帐户之间的映射语法如下:

sp_addlinkedsrvlogin [ @rmtsrvname = ] 'rmtsrvname'
[ , [ @useself = ] 'TRUE' | 'FALSE' | NULL ]
[ , [ @locallogin = ] 'locallogin' ]
[ , [ @rmtuser = ] 'rmtuser' ]
[ , [ @rmtpassword = ] 'rmtpassword' ]
  • @rmtsrvname:应用登录映射的链接服务器的名称。
  • @useself:确定是否通过模拟本地登录名或显式提交登录名和密码来连接到 rmtsrvname。默认值为 TRUE。

    值为 TRUE 指定登录名使用其自己的凭据来连接到rmtsrvname,rmtuser和rmtpassword自变量被忽略。 FALSE指定rmtuser和rmtpassword参数用于连接到rmtsrvname。 如果rmtuser和rmtpassword也是设置为 NULL,任何登录名或密码用于连接到链接服务器。

  • @locallogin:指要本地哪个账户登录到远程服务器。如果不为 NULL, locallogin可以是一个SQL Server登录或 Windows NT用户。
  • @rmtuser:用于连接到远程服务器的登录名。
  • @rmtpassword:用于连接到远程服务器的密码。

【示例】

A. 使用各自的用户凭据将所有本地登录连接到链接服务器

以下示例将创建一个映射,以确保所有到本地服务器的登录都使用其各自的用户凭据连接到链接服务器 Accounts。

EXEC sp_addlinkedsrvlogin 'Accounts'

EXEC sp_addlinkedsrvlogin 'Accounts', 'true'

B. 使用不同的用户凭据将特定的登录连接到链接服务器

以下示例将创建一个映射,以确保 Windows 用户 Domain\Mary 使用登录名 MaryP 和密码 d89q3w4u 连接到链接服务器 Accounts。

EXEC sp_addlinkedsrvlogin
'Accounts',
'false',
'Domain\Mary',
'MaryP',
'd89q3w4u'

C. 不使用任何用户凭据将所有本地登录连接到链接服务器

此示例创建一个映射,以确保所有到本地服务器的登录都连接到链接服务器 mydb,而不使用登录或密码(mydb 不需要登录或密码)。

EXEC sp_addlinkedsrvlogin 'mydb', 'false', NULL, NULL, NULL
or
EXEC sp_addlinkedsrvlogin 'mydb', 'false'

D. 将特定的登录连接到 Excel 电子表格(链接服务器)

EXEC sp_addlinkedserver 'ExcelSource', 'Jet 4.0',
'Microsoft.Jet.OLEDB.4.0',
'c:\MyData\DistExcl.xls',
NULL,
'Excel 5.0'
GO
EXEC sp_addlinkedsrvlogin 'ExcelSource', 'false', 'sa', 'Admin', NULL
创建Linked Server

(1)在SSMS中创建链接服务器

  1. 在 SQL Server Management Studio 中,打开对象资源管理器,展开“Server Object”,右键单击“Linked Servers”,然后单击“New Linked Servers”。

  2. 在“常规”页上的“链接服务器”框中,键入您链接到的 SQL Server 实例的名称。

    如果该 SQL Server 实例是默认实例,则输入承载 SQL Server 实例的计算机的名称。如果该 SQL Server 是命名实例,则输入计算机名称和实例名称,例如 Accounting\SQLExpress。

  3. 在“服务器类型”区域中,选择 SQL Server 以便指示该链接服务器是 SQL Server 的另一个实例。

  4. 在“安全性”页上,指定在原始 SQL Server 连接到链接服务器时将使用的安全上下文。在通过使用其域登录名连接用户的域环境中,选择“使用登录名的当前安全上下文建立连接”通常是最佳选择。在用户通过使用 SQL Server 登录名连接到原始 SQL Server 时,最佳选择通常是选择“通过使用此安全上下文”,然后提供在链接服务器上进行身份验证时所必需的凭据。
  5. 单击“确定”。

(2)使用 Transact-SQL创建链接服务器

sp_addlinkedserver [@server=] 'server'
[ , [ @srvproduct= ] 'product_name']
[ , [ @provider= ] 'provider_name' ]
[ , [ @datasrc= ] 'data_source' ]
[ , [ @location= ] 'location' ]
[ , [ @provstr= ] 'provider_string' ]
[ , [ @catalog= ] 'catalog' ]

参数说明

  • @server:链接服务器别名(习惯上直接使用目标服务器IP,或取个别名如:Test,反正想取什么名就取什么)
  • @srvproduct:要添加为链接服务器的 OLE DB 数据源的产品名称。 如果为 SQL Server,则不必指定provider_name、data_source、location、provider_string 和 catalog。
  • @provider:与此数据源对应的 OLE DB 访问接口的唯一编程标识符 (PROGID)。但如果忽略 provider_name,则使用 SQLNCLI。
  • @datasrc:链接服务器名,也就是与指定链接服务器对应的OLE DB数据源属性。
  • @location:与指定链接服务器对应的OLE DB位置属性。
  • @catalog:与指定链接服务器对应的OLE DB目录属性。

@xxx这些名词在写的时候是可以省略的。

【注释】

下表显示为能通过 OLE DB 访问数据源而建立链接服务器的方法。对于特定的数据源,可以使用多种方法为其设置链接服务器;该表中可能有多行适用于一种数据源类型。该表还显示了用于设置链接服务器的 sp_addlinkedserver 参数值。

  • “任何”指产品名称可以任意。
  • 如果未指定访问接口名称或将 SQL Server 指定为产品名称,则 Microsoft SQL Server Native Client OLE DB 访问接口将是用于 SQL Server 的访问接口。即使指定了较早版本的访问接口名称 SQLOLEDB,在保存到目录时该名称也将改为 SQLNCLI。

【示例】

A. 访问MSSQL

  1. 在查询编辑器中,输入以下 Transact-SQL 命令以便链接到名为 SRVR002\ACCTG 的 SQL Server 实例:

    USE [master]
    GO
    EXEC master.dbo.sp_addlinkedserver
    @server = N'SRVR002\ACCTG',
    @srvproduct = N'SQL Server' ;
    GO
  2. 执行以下代码,以便将链接服务器配置为使用正在使用链接服务器的登录名的域凭据。
    EXEC master.dbo.sp_addlinkedsrvlogin
    @rmtsrvname = N'SRVR002\ACCTG',
    @locallogin = NULL ,
    @useself = N'True' ;
    GO
  3. 跟进:在创建链接服务器后采取的步骤

    查询的数据库格式为:

    [别名].[数据库名].[架构名].[表名]

    插入数据库格式为:

    insert [数据库名].[架构名].[表名] select * from [别名].[数据库名].[架构名].[表名]
    select * into [数据库名].[架构名].[新表名] from [别名].[数据库名].[架构名].[表名]
    • 执行下面的代码,测试与链接服务器的连接。以下示例返回链接服务器上数据库的名称。

      SELECT name FROM [SRVR002\ACCTG].master.sys.sysdatabases;
    • 使用由四部分组成的名称引用链接服务器上的对象。执行以下代码,以便返回本地服务器上所有登录名的列表及其在链接服务器上的匹配登录名。
      -- sys.server_principals可以查询登入名拥有的服务器角色
      SELECT local.name AS LocalLogins, linked.name AS LinkedLogins
      FROM master.sys.server_principals AS local
      LEFT JOIN [SRVR002\ACCTG].master.sys.server_principals AS linked
      ON local.name = linked.name;

B. 访问ACCESS数据库

  1. Microsoft.Jet.OLEDB.4.0 访问接口连接到使用 2002-2003 格式的 Microsoft Access 数据库。 下面的示例将创建一个名为 SEATTLE Mktg 的链接服务器。

    EXEC sp_addlinkedserver
    @server = N'SEATTLE Mktg',
    @provider = N'Microsoft.Jet.OLEDB.4.0',
    @srvproduct = N'OLE DB Provider for Jet',
    @datasrc = N'C:\MSOffice\Access\Samples\Northwind.mdb';
    GO

    @datasrc='ServiceName',即数据源的格式如下:

    (1)盘符:\路径\文件名

    (2)网络名\共享名\文件名 (网络版本)

  2. 若要访问Access数据库中的数据,使用以下的查询格式:

    select * from 别名...表名

    C. 访问Oracle数据库

    访问前需要SQL SERVER服务器中安装ORACLE客户端。

  3. 创建链接服务器

    EXEC sp_addlinkedserver
    @server ='ora', -- 要创建的链接服务器别名
    @srvproduct='Oracle', --产品名称
    @provider='MSDAORA',
    @datasrc='oracle客户端设置的本地net服务名' --数据源
    GO

    @datasrc可以在oracle\ora92\network\admin\tnsnames.ora文件中查看,文件中的SERVICE_NAME就是服务名。

  4. 若要访问Oracle数据库中的数据,使用以下的查询格式:

    -- 四部分名称全部用大写,因为在Oracle的数据字典中为大写
    SELECT * FROM 链接服务器别名..ORACLE用户名.表名(视图)
  5. 若要执行Oracle数据库中的存储过程,使用以下的查询:
    SELECT * FROM OPENQUERY(别名, ’exec 用户名.存储过程名’)

D. 访问EXCEL

  1. 若要创建链接的服务器定义使用MicrosoftOLE DB Provider for Jet 访问 Excel 电子表格中 1997年-2003年格式中,首先创建的命名的区域在 Excel 中通过指定要选择的 Excel 工作表的行和列。 这样,可以在分布式查询中将此范围的名称引用为表名称。

    EXEC sp_addlinkedserver 'ExcelSource',
    'Jet 4.0', -- 产品名称
    'Microsoft.Jet.OLEDB.4.0', -- provider
    'c:\MyData\DistExcl.xls',
    NULL,
    'Excel 5.0';
    GO

    若要访问 Excel 电子表格中的数据,请将单元范围与名称相关联。 以下查询通过使用先前设置的链接服务器,将指定的命名范围 SalesData 作为表来访问。

    SELECT * FROM ExcelSource...SalesData;
  2. 如果 SQL Server 在可以访问远程共享的域帐户下运行,则可以使用 UNC 路径来代替映射驱动器。
    EXEC sp_addlinkedserver 'ExcelShare',
    'Jet 4.0',
    'Microsoft.Jet.OLEDB.4.0',
    '\\MyServer\MyShare\Spreadsheets\DistExcl.xls', -- UNC 路径
    NULL,
    'Excel 5.0';

如何在SSMS查看Linked Server?

在SSMS的Server Object——>Linked Servers可以找到本数据库所有的数据库链接,如下图:

此外,通过执行Programmability——>Store Procedures——>System Stored Procedures——>sp_linkedservers 这个存储过程也可以查询到当前数据库的所有linked server。如下图:

OpenQuery

有时候我们希望在一个sqlserver下访问另一个sqlserver数据库上的数据,或者访问其他oracle数据库上的数据,要想完成这些操作,我们首要的是创建数据库链接(Linked Server)。 数据库链接能够让本地的一个sqlserver登录用户映射到远程的一个数据库服务器上,并且像操作本地数据库一样。OpenQuery 就是SQL Server用来与其他Server交互的一种技术,其他数据库在OpenQuery 表达式中是以Linked Server 存在的。

OPENQUERY 可以在查询的 FROM 子句中引用,就好象它是一个表名。OPENQUERY 也可以作为 INSERT、UPDATE 或 DELETE 语句的目标表进行引用。

语法

OPENQUERY ( linked_server ,'query' )
  • linked_server :表示链接服务器名称的标识符。
  • query:在链接服务器中执行的查询字符串。 该字符串的最大长度为 8 KB。

示例

A. 执行 UPDATE 传递查询

UPDATE OPENQUERY(MSSQLSvr, 'SELECT * FROM tableName') SET role_id = 'ForTest' WHERE id = 3

可以简写为:

UPDATE MSSQLSvr.DataBaseName.dbo.tableName SET role_id = 'ForTest' WHERE id = 3;

B. 执行 INSERT 传递查询

INSERT INTO OPENQUERY(MSSQLSvr, 'SELECT * FROM tableName WHERE 1>1') VALUES(3,6,'ANDY');

可以简写为:

INSERT INTO MSSQLSvr.DataBaseName.dbo.tableName VALUES(3,6,'ANDY');

C. 执行 DELETE 传递查询

DELETE OPENQUERY(MSSQLSvr, 'SELECT * FROM tableName') WHERE id IN (1,3);

可以简写为:

DELETE MSSQLSvr.DataBaseName.dbo.tableName WHERE id IN (1,3);

D. 执行SELECT传递查询

SELECT 1 FROM OPENQUERY(OracleSvr,'SELECT * FROM stuMan.person WHERE id > 10');

E. 执行存储过程

SELECT EXECUTE testProcedure(isnull(name,' '))
FROM OPENQUERY(OracleSvr,'SELECT name FROM stuMan.person')

备注

(1)OPENQUERY 不接受参数变量,也就是说:

DELETE OPENQUERY (linked_server, 'SELECT id FROM msgs WHERE id=' + @id);

是不正确的,但可以这样做:

DELETE OPENQUERY (linked_server, 'SELECT id FROMmsgs') WHERE id=@id); 。

(2)若没有参数变量,最好把条件表达式卸载OPENQUERY如里面,因为在linked_server执行完筛选才RETURN的,TABLE的数据量越大效果越明显。如下面的SQL语句:

select * from openquery( OracleSvr ,'select * from kxx_file  ')
where kxx07='2009-10-08'

该语句查询耗时18s;很明显RETURN的数据相当大,再进行筛选;而

select * from openquery( OracleSvr ,
'select * from kxx_file where kxx07={ ts ''2009-10-08 00:00:00.000''} ')

该语句查询耗时3s。

(3)T-SQL 中,INSERT 可以省略 INTO,DELETE 也可以省略 FROM。

(4)我们在对表进行查询时,通常都会有传入的参数。在OpenQuery中使用参数和我们平时写的数据库语句会不会有所不同呢?对于Int类型的参数,没有什么不同。但是,如果是字符类型的参数,比如,你要在Openquery中执行如下的数据库语句:

select * from tbl_emp Where empName = 'leo'

那么我们就必须对这个参数进行转义,单变双实现字符转义。如下:

select * from OpenQuery([linkedServerName],'Select * from table1 where empName = ''leo''')

即我们必须对''进行转义,所以'' 就变成了''''。

T-SQL&&SQL

作者:zoyoto

链接:http://www.jianshu.com/p/6abd69f44463

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

SQLServer LinkServer 链接服务器的更多相关文章

  1. Sqlserver通过链接服务器访问Oracle的那些事儿

    前言: 1.不经历风雨,怎能见彩虹. 2.充分利用BaiDu.google等搜索引擎查找资料并整合分析! 3.世上无难事只怕有心人! 本文由来:笔者在研究SQLSERVER链接服务器到oracle并使 ...

  2. 【转】Sqlserver通过链接服务器访问Oracle的那些事儿!

    原文:http://blog.sina.com.cn/s/blog_614b6f210100t80r.html 前言:1.不经历风雨,怎能见彩虹.2.充分利用BaiDu.google等搜索引擎查找资料 ...

  3. Sqlserver通过链接服务器访问Oracle的解决办法

    转自http://blog.sina.com.cn/s/blog_614b6f210100t80r.html 一.创建sqlserver链接服务(sqlserver链接oracle)  首先sqlse ...

  4. SQLServer通过链接服务器远程删除数据性能问题解决

    原文:SQLServer通过链接服务器远程删除数据性能问题解决 在上一遍文章中介绍了SQLServer通过链接服务器访问Oracle性能问题的解决方法,本文介绍链接服务器下远程删除SQLServer数 ...

  5. SQLServer创建链接服务器

    --SQLServer创建链接服务器----1.访问接口中Oracle接口 属性 选择 允许进程内-- --删除链接服务器EXEC master.dbo.sp_dropserver @server=N ...

  6. 【转】Sqlserver通过链接服务器访问Oracle的解决办法

    一.创建sqlserver链接服务(sqlserver链接oracle)  首先sqlserver 链接oracle可以通过两个访问接口: “MSDAORA” 和“OraOLEDB.Oracle” 1 ...

  7. SQLServer通过链接服务器调用Oracle 存储过程

    语法: declare @输出参数 数据类型; exec(' exec 存储过程(?, ?)', 输入参数, @输出参数 out) at 链接服务器名 参考文章: SQL2008 链接Oracle 调 ...

  8. Sqlserver通过链接服务器访问Oracle

    工作中遇到的情况,win 7 64位操作系统的就安装64位的oracle 客户端,然后重启sql service服务后再创建sql 链接服务器.关于如何创建链接服务器请查看下面的大神的链接: http ...

  9. sqlserver利用链接服务器查询或同步本地数据库和远程数据库

    这个实际上是SQLserver的分布式查询:如果一个项目需要二至多台服务器,而我们又必须从几台服务器中将数据取出来,这就必须用分布式查询!在这里有两个概念:本地数据源.远程数据源!本地数据源指的是单个 ...

随机推荐

  1. 直播二:iOS中硬编码(VideoToolBox)

    硬编码相对于软编码来说,使用非CPU进行编码,如显卡GPU.专用的DSP.FPGA.ASIC芯片等,性能高,对CPU没有压力,但是对其他硬件要求较高(如GPU等). 在iOS8之后,苹果开放了接口,并 ...

  2. Cs Round#54 E Late Edges

    题意:给定一个无向图,你从结点1开始走,每经过一条边需要1的时间,每条边都有一个开放时间,只有当目前所用的时间大于等于开放时间时,这条边才可以被经过.每一单位时间你都必须经过一条边,问最快什么时候可以 ...

  3. MongoDB之建立Windows和本地虚拟机的双向连接

    本文主要分享如何将MongoDB数据库在Windows系统和本地虚拟机系统建立双向连接,我们将借助MongoDB的可视化工具Robomongo来实现.首先,应该确保你的Windows系统和本地虚拟机系 ...

  4. linux系统编程:进程间通信-fifo

    进程间通信-fifo 进程间通信的还有一种方式是fifo. fifo是还有一种管道:有名管道.从名字能够看出.它也是队列. 使用fifo通信前,得先创建fifo $ mkfifo myfifo 随后仅 ...

  5. Android Static分析

    1.static的变量或者方法会放在内存的一个方法区内 2.static变量会在该变量所属的类从内存中释放掉之后. 才会释放掉而类释放的条件是非常苛刻的. 必需要该类相应的全部对象被释放掉. 同一时候 ...

  6. hdu 2209 bfs+状压

    http://acm.hdu.edu.cn/showproblem.php?pid=2209 不知为啥有种直觉.会出状压+搜索的题,刷几道先 简单的BFS.状压表示牌的状态, //#pragma co ...

  7. java多线程编程核心技术——全书总结

    这本书大致上是看完了,不过第七章结束的匆匆忙忙很不好. 不过好在还是看完了,勉强算吧. 回想这一年,挺感慨的,心里一直谋求着进步,却很难行动起来. 仔细想想确实啊,想一直进步肯定要牺牲自己的业余时间, ...

  8. 前端优化之动画为什么要尽量用css3代替js

    导致JavaScript效率低的两大原因:操作DOM和使用页面动画.通常我们会通过频繁的操作 DOM的CSS来实现视觉上的动画效果,导致js效率低的两个因素都包括在内了在频繁的操作DOM和CSS时,浏 ...

  9. 使用Mkdocs构建你的项目文档

    使用Mkdocs构建你的项目文档 环境搭建 安装必需软件 作者是在windows下安装的,如果是linux或mac用户,官网有更详细的安装说明. windows 10 x64 当然还有广大的windo ...

  10. 7.python常用模块

    1.time 常用表示时间方式: 时间戳,格式化的时间字符串,元组(struct_time) UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时 ...