SQL Server 连接服务器示例查询

113

在Management Studio中,我正在尝试在两个链接服务器之间运行查询/执行联接。下面的SQL语句是否正确:

select foo.id 
from databaseserver1.db1.table1 foo, 
     databaseserver2.db1.table1 bar 
where foo.name=bar.name

基本上,您只需要在数据库表名前加上数据库服务器名称吗?

16个回答

221

格式应该是这样的:

<server>.<database>.<schema>.<table>

例如: DatabaseServer1.db1.dbo.table1

更新: 我知道这是一个旧问题,我所提供的答案是正确的;然而,我认为任何碰巧遇到这个问题的人都应该知道一些事情。

特别是,在连接服务器时查询加入操作时,来自链接服务器的整个表格将可能会被下载到执行查询的服务器上以执行加入操作。在OP的情况下,来自DB1table1和来自DB2table1都将完整传输到执行查询的服务器上,假设其名称为DB3

如果您有大型表格,则可能导致操作需要很长时间才能执行。毕竟,它现在受限于网络流量速度,这比内存甚至磁盘传输速度慢几个数量级。

如果可能,执行针对远程服务器的单个查询,而不连接到本地表格,以将所需数据提取到临时表中。然后从那里进行查询。

如果这不可能,那么您需要查看各种会导致SQL服务器必须在本地加载整个表格的原因。例如使用GETDATE()或甚至某些连接。其他性能杀手包括不提供适当的权限。

请参见http://thomaslarock.com/2013/05/top-3-performance-killers-for-linked-server-queries/获取更多信息。


13
如果数据库服务器名称中有连字符,需要用方括号将其括起来。 - bmw0128
5
最好使用双引号:与Microsoft的方括号不同,几乎所有平台都支持它。 - user565869
3
当数据库服务器名称中包含句点时,您还需要使用方括号或双引号。 - David Brunow
6
如果您对任何限定符不确定,可以在SSMS对象资源管理器中深入到链接服务器中的表,右键单击并选择Script Table as、SELECT To和New Query Editor Window。生成的SELECT语句将包括正确的、完全限定的表路径。我在与Sybase一起工作时遇到了一个神秘的数据库限定符,这给了我正确的名称。 - John Mo
1
@JohnMo 这对于一些非 SQL Server 链接服务器是不起作用的 - 表结构不可用;我通过以下方式解决这个问题... SELECT * INTO [MySchema].[MyTable] FROM openquery(MyLinkedServer, 'SELECT * FROM TheSchema.TheTable WHERE 1=0'); - brewmanz
显示剩余5条评论

50
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME..TABLENAME')

这可能会对您有所帮助。


点赞。当您将MySQL连接到MS SQL时,此方法有效。 - Baz Guvenkaya
5
换句话说,这将创建一个透传查询。请记住,查询语句必须使用服务器的本地SQL编写。Oracle的语法与Teradata、SQL Server等不同。 - AxGryndr
据我了解,这是一个“透传查询”,它将SQL传递给其他服务器;虽然可以用于访问其他供应商的数据库,但在两个都是MS-SQL-Server(可能是兼容版本)的情况下,最好使用“本地”查询。首先,可以避免引号转义的复杂性。本地模式是否有性能优势? - FloverOwe

17

对于那些对其他答案感到困惑的人,请尝试使用OPENQUERY

示例:

 SELECT * FROM OPENQUERY([LinkedServer], 'select * from [DBName].[schema].[tablename]') 

适用于SQL Server。 - Tom Stickel
这是唯一对我有效的解决方案。快速翻译(可能对某些人有帮助):SELECT * INTO NEW_DB.dbo.tblCopy FROM OLD_DB.dbo.tblData 形式变为 SELECT * INTO NEW_DB.dbo.tblCopy FROM OPENQUERY([server], 'select * from OLD_DB.dbo.tblData') - baltermia

11
如果您仍然在<server>.<database>.<schema>.<table>方面遇到问题, 请将服务器名称用[]括起来。

注意:我使用[]执行了一个从选择中创建表的操作,但该表并没有在链接服务器上被创建,而是本地创建了一个名为dbo.databaseserver1.db1.dbo.table1的表。 - biscuit314

9
您需要在引用的一部分中指定架构/所有者(默认情况下为dbo)。此外,最好使用更新的(ANSI-92)联接方式。
select foo.id 
    from databaseserver1.db1.dbo.table1 foo
        inner join databaseserver2.db1.dbo.table1 bar 
            on foo.name = bar.name

内连接语法比隐式连接更可取吗? - bmw0128
3
是的,有几个原因。在我看来,最重要的是当你将表和连接放在两个不同的地方时,很容易意外地编写交叉积联接。 - user565869
请注意,对于某些非 SQL Server 链接服务器,四个点的部分可能无法正常工作。它可能会引发错误,例如:“为链接服务器“ MyLinkedServer”指定了无效的架构或目录提供程序“ MSDASQL”。 - brewmanz

7
select * from [Server].[database].[schema].[tablename] 

这是正确的调用方式。 在执行查询之前,请确保验证服务器是否已连接!
要检查已链接的服务器,请调用:
EXEC sys.sp_linkedservers 

1
这对于一些非 SQL Server 链接服务器是无法工作的。它会抛出错误,比如..."为链接服务器"MyLinkedServer"指定了无效的架构或目录提供程序"MSDASQL"。 - brewmanz

7

右键单击表格,然后选择“脚本表格为选择”

在这里输入图片描述


那不是原帖所问的。 - Fandango68
4
这显示了如何获取链接表上选择查询的正确语法。结果类似于Sean的答案。 - Shimon Doodkin
3
@ShimonDoodkin,一个很好的例子,不是给我一条鱼,而是教我如何钓鱼。 - Amro

4
select name from drsql01.test.dbo.employee
  • drslq01是服务器名称--链接的服务器
  • test是数据库名称
  • dbo是模式-默认模式
  • employee是表名

希望这有助于理解如何执行链接服务器的查询


3

通常在使用链接服务器时不应该使用直接查询,因为它会严重使用 SQL Server 的临时数据库。首先将数据检索到临时数据库中,然后进行过滤。这方面有很多讨论。最好使用 OPENQUERY, 因为它可以将 SQL 传递到源链接服务器,然后返回经过过滤的结果,例如:

SELECT *
FROM OPENQUERY(Linked_Server_Name , 'select * from TableName where ID = 500')

此答案不包括数据库名称。 - Chris Nevill
2
我在创建链接服务器时提供了数据库信息。详细信息请参见下面的MSDN链接: https://msdn.microsoft.com/zh-cn/library/ff772782(v=sql.110).aspx - Muhammad Yaseen
如果我的链接服务器需要身份验证,而我只是想使用PDO从我的PHP应用程序进行查询,我该怎么办? - nekiala
1
你会如何使用这种方法,从数据库1连接到联接服务器上的数据库并执行联接操作? - eaglei22

2
在sql-server(local)中,有两种方法可以从链接服务器(remote)查询数据。 分布式查询(四部分表示法)
  1. 可能无法与所有远程服务器一起使用。如果您的远程服务器是MySQL,则分布式查询将无法工作。
  2. 过滤器和连接可能无法有效地工作。如果您有一个带有WHERE子句的简单查询,sql-server(local)可能会先从远程服务器获取整个表,然后在本地应用WHERE子句。对于大型表来说,这非常低效,因为大量的数据将从远程移动到本地。但并非总是如此。如果本地服务器可以访问远程服务器的表统计信息,则可能与使用openquery一样高效。更多详细信息
  3. 积极的一面是T-SQL语法将起作用。
SELECT * FROM [SERVER_NAME].[DATABASE_NAME].[SCHEMA_NAME].[TABLE_NAME] 

OPENQUERY

  1. 这基本上是一个透传。查询在远程服务器上完全处理,因此将利用远程服务器上的索引或任何优化。有效地减少了从远程到本地SQL Server传输的数据量。
  2. 这种方法的小缺点是,如果远程服务器不是SQL Server,则T-SQL语法将无法使用。
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME.SCHEMA_NAME.TABLENAME')

总的来说,OPENQUERY在大多数情况下似乎是更好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接