【问题标题】:Selecting data from two different servers in SQL Server从 SQL Server 中的两个不同服务器中选择数据
【发布时间】:2010-11-11 18:11:08
【问题描述】:

如何从 SQL Server 中两个不同服务器上的两个不同数据库中选择同一查询中的数据?

【问题讨论】:

  • Eric 和 Raging Bull 的答案非常方便。我能够使用它来将大量数据从 DEV 复制到 PROD,从而将时间从 5 小时到 18 小时缩短到 17 秒。
  • @Eric,感谢您编辑了一个有点模棱两可的问题并将其变成一个 170 次重复的问题 :)

标签: sql sql-server tsql


【解决方案1】:

您正在寻找的是链接服务器。您可以从对象资源管理器树中的以下位置在 SSMS 中找到它们:

Server Objects-->Linked Servers

或者你可以使用sp_addlinkedserver

您只需设置一个。一旦你有了它,你就可以像这样调用另一个服务器上的表:

select
    *
from
    LocalTable,
    [OtherServerName].[OtherDB].[dbo].[OtherTable]

请注意,所有者并不总是dbo,因此请确保将其替换为您使用的任何架构。

【讨论】:

  • 没有链接服务器可以吗?
  • @Eric,SSMS 中的服务器对象在哪里?
  • @TsahiAsher - 当您连接到服务器时,服务器对象是对象资源管理器树中的一个文件夹。
  • 如果不知道,也可以省略模式以使用默认值。例如。 [OtherServerName].[OtherDB]..[OtherTable] 但是,如果知道,最好包含它。
【解决方案2】:

您可以使用链接服务器来做到这一点。

通常将链接服务器配置为使数据库引擎能够执行 Transact-SQL 语句,该语句包括另一个 SQL Server 实例或另一个数据库产品(如 Oracle)中的表。许多类型的 OLE DB 数据源都可以配置为链接服务器,包括 Microsoft Access 和 Excel。

链接服务器具有以下优势:

  • 能够从 SQL Server 外部访问数据。
  • 能够针对整个企业的异构数据源发布分布式查询、更新、命令和事务。
  • 以类似方式处理不同数据源的能力。

阅读更多关于Linked Servers的信息。

按照以下步骤创建链接服务器:

  1. 服务器对象 -> 链接服务器 -> 新链接服务器

  2. 提供远程服务器名称。

  3. 选择远程服务器类型(SQL Server 或其他)。

  4. 选择安全 -> 使用此安全上下文并提供远程服务器的登录名和密码。

  5. 点击确定就完成了!!

Here 是一个创建链接服务器的简单教程。

您可以使用查询添加链接服务器。

语法:

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

阅读更多关于sp_addlinkedserver的信息。

您必须只创建一次链接服务器。创建链接服务器后,我们可以如下查询:

select * from LinkedServerName.DatabaseName.OwnerName.TableName

【讨论】:

  • 注意:请参阅here,了解如何将服务器名称设为主机名/端口以外的名称。
  • 一点提示,如果您在使用 sp_addlinkedserver 时遇到问题,请在此处。在对话框中创建服务器 - 确保它正常工作 - 然后右键单击连接并选择脚本 [t 链接服务器 AS 创建
【解决方案3】:
SELECT
        *
FROM
        [SERVER2NAME].[THEDB].[THEOWNER].[THETABLE]

您还可以查看使用链接服务器。链接服务器也可以是其他类型的数据源,例如 DB2 平台。这是尝试从 SQL Server TSQL 或 Sproc 调用访问 DB2 的一种方法...

【讨论】:

  • 这种方法会一直有效吗?在哪些情况下它可能会失败?
  • 确认这在我的环境中失败,错误说我需要使用 addlinkedserver
  • 这是否适用于任何人,无需使用链接服务器?
  • 经过测试,收到的错误是Could not find server '88.208.229.164' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
【解决方案4】:

跨 2 个不同数据库的查询是分布式查询。以下是一些技术以及优缺点的列表:

  1. 链接服务器:提供对比 SQL Server 复制提供的更广泛的数据源的访问
  2. 链接服务器:连接不支持复制或需要临时访问的数据源
  3. 链接服务器:性能优于 OPENDATASOURCE 或 OPENROWSET
  4. OPENDATASOURCEOPENROWSET 函数: 便于从数据源中临时检索数据。 OPENROWSET 也有 BULK 功能,可能/可能不需要格式文件,格式文件可能很繁琐
  5. OPENQUERY:不支持变量
  6. 所有都是 T-SQL 解决方案。相对容易实施和设置
  7. 所有都依赖于源和目标之间的连接,这可能会影响性能和可扩展性

【讨论】:

  • OPENQUERY 仍然需要链接服务器,而 OPENDATASOURCE 不需要
【解决方案5】:

这些都是很好的答案,但是缺少了这个,它有自己强大的用途。可能它不符合 OP 的要求,但问题很模糊,我觉得其他人可能会在这里找到自己的方式。基本上您可以使用 1 个窗口同时对多个服务器运行查询,方法如下:

在 SSMS 中打开 Registered Servers 并在 Local Server Groups 下创建一个New Server Group

在此组下为您要查询的每个服务器创建新服务器注册。如果数据库名称不同,请确保在属性中为每个数据库设置一个默认值。

现在回到您在第一步中创建的组,右键单击并选择新建查询。将打开一个新的查询窗口,您运行的任何查询都将在组中的每台服务器上执行。结果显示在单个数据集中,带有一个额外的列名,指示记录来自哪个服务器。如果您使用状态栏,您会注意到服务器名称已替换为 multiple

【讨论】:

  • 这似乎假设查询在所有数据库上使用相同的表。 (这对于像 sys.tables 这样的标准表格很好,但对于像 dbo.mycustomers 这样的定制表格不太可能)
  • 鉴于它是“来自两个不同数据库的相同查询”,它很可能具有相同的表。但是,是的,我经常将此方法用于安装在多台服务器上的生产系统并用于查询 MSDB 表。
  • 真的很酷的功能。缺点是结果集的模式必须匹配,因为它执行两次查询并同时合并它们。如果您可以在 SQL 本身中引用服务器,就像您可以使用链接服务器一样,那将是很棒的,即使您无法 JOIN 结果集并且必须构建这些集以单独评估。
  • @Kross 你可以。创建一个#output 表,根据@@SERVERNAME 执行逻辑并将数据填充到#output 中,然后以选择结束它。我做了类似的事情来从具有不同级别/信息列的 SQL2000 和 SQL2008R2 机器的混合中查询日志信息,但我使用的是服务器版本变量而不是 @@SERVERNAME。
  • 这是一个可爱的答案,一年后有人正在寻找这个。谢谢
【解决方案6】:

试试这个:

SELECT * FROM OPENROWSET('SQLNCLI', 'Server=YOUR SERVER;Trusted_Connection=yes;','SELECT * FROM Table1') AS a
UNION
SELECT * FROM OPENROWSET('SQLNCLI', 'Server=ANOTHER SERVER;Trusted_Connection=yes;','SELECT * FROM Table1') AS a

【讨论】:

    【解决方案7】:

    在将 SQL_server 2008 连接到远程服务器中托管的 SQL_server 2016 时,我遇到了同样的问题。其他答案对我来说并不简单。我在这里写下我的调整解决方案,因为我认为它可能对其他人有用。

    远程 IP 数据库连接的扩展答案:

    第 1 步:链接服务器

    EXEC sp_addlinkedserver @server='SRV_NAME',
       @srvproduct=N'',
       @provider=N'SQLNCLI',   
       @datasrc=N'aaa.bbb.ccc.ddd';
       
    EXEC sp_addlinkedsrvlogin 'SRV_NAME', 'false', NULL, 'your_remote_db_login_user', 'your_remote_db_login_password'
    

    ...SRV_NAME 是一个虚构的名称。我们将使用它来从我们的查询中引用远程服务器。 aaa.bbb.ccc.ddd 是托管 SQLserver 数据库的远程服务器的 IP 地址。

    第 2 步:运行查询 例如:

    SELECT * FROM [SRV_NAME].your_remote_db_name.dbo.your_table
    

    ...就是这样!

    语法详细信息:sp_addlinkedserversp_addlinkedsrvlogin

    【讨论】:

      【解决方案8】:

      在一个服务器中创建了一个到另一个服务器的链接服务器定义(您需要 SA 来执行此操作),然后只需使用 4 部分命名来引用它们(请参阅 BOL)。

      【讨论】:

        【解决方案9】:

        服务器 2008:

        当在 SSMS 中连接到 server1.DB1 并尝试:

        SELECT  * FROM
        [server2].[DB2].[dbo].[table1]
        

        正如其他人所说,如果它不起作用,那是因为服务器没有链接。

        我得到错误:

        在 sys.servers 中找不到服务器 DB2。验证是否正确 服务器名称已指定。如有必要,执行存储过程 sp_addlinkedserver 将服务器添加到 sys.servers。

        添加服务器:

        参考:使用 sp_addlinkedserver 添加服务器 链接:[1]:To add server using sp_addlinkedserver

        要查看 sys.servers 中的内容,只需查询它:

        SELECT * FROM [sys].[servers]
        

        【讨论】:

          【解决方案10】:

          添加链接服务器的简化解决方案

          第一台服务器

          EXEC sp_addlinkedserver @server='ip,port\instancename'
          

          第二次登录

          EXEC sp_addlinkedsrvlogin 'ip,port\instancename', 'false', NULL, 'remote_db_loginname', 'remote_db_pass'
          

          从链接到本地​​数据库执行查询

          INSERT INTO Tbl (Col1, Col2, Col3)
          SELECT Col1, Col2, Col3
          FROM [ip,port\instancename].[linkedDBName].[linkedTblSchema].[linkedTblName]
          

          【讨论】:

            【解决方案11】:
             select * 
             from [ServerName(IP)].[DatabaseName].[dbo].[TableName]
            

            【讨论】:

              【解决方案12】:

              正如@Super9 所说,OPENDATASOURCE 使用 SQL Server 身份验证和数据提供程序 SQLOLEDB .我只是在这里发布一个表的代码 sn-p 在当前运行代码的服务器数据库中,另一个在其他服务器 '192.166.41.123'

              SELECT top 2 * from dbo.tblHamdoonSoft  tbl1 inner JOIN  
              OpenDataSource('SQLOLEDB','Data Source=192.166.41.123;User ID=sa;Password=hamdoonsoft')
              .[TestDatabase].[dbo].[tblHamdoonSoft1] tbl2 on tbl1.id = tbl2.id
              

              【讨论】:

                【解决方案13】:

                我知道这是一个老问题,但我使用同义词。假设查询在数据库服务器 A 中执行,并在数据库服务器 B 中查找服务器 A 上不存在的表。然后在 A 数据库上添加一个同义词,从服务器 B 调用您的表。您的查询不必包括任何架构或不同的数据库名称,只需按照通常的方式调用表名即可。

                没有必要链接服务器,因为同义词就是某种链接。

                【讨论】:

                • 那么,在这种情况下,什么是“同义词”?
                • 它是一个数据库对象,它引用另一个数据库中的基础对象。更多信息:docs.microsoft.com/en-us/sql/relational-databases/synonyms/…
                • 酷,我不知道那个功能。但是,您还说他们避免了对链接服务器的需要,但我看不出如何。同义词本身似乎只是一个同义词,并且本身不包含任何特定的远程处理能力。在docs.microsoft.com/en-us/sql/t-sql/statements/… 的示例 B 中,他们在从同义词中引用它之前创建了一个链接服务器。
                • 没错,我假设数据库在同一个服务器环境中。当然,如果数据库彼此相距很远,您将始终必须链接它们。没有其他方法可以通过数据库到数据库的关系进行访问。
                【解决方案14】:
                sp_addlinkedserver('servername')
                

                所以它应该是这样的 -

                select * from table1
                unionall
                select * from [server1].[database].[dbo].[table1]
                

                【讨论】:

                  【解决方案15】:

                  服务器对象--->链接服务器--->新的链接服务器

                  在链接服务器中写入其他服务器的服务器名称或 IP 地址并选择 SQL Server 在安全选择中(使用此安全上下文进行) 写入其他服务器的登录名和密码

                  现在连接然后使用

                  Select * from [server name or ip addresses ].databasename.dbo.tblname
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-05-15
                    • 1970-01-01
                    • 2012-12-28
                    • 2022-06-14
                    相关资源
                    最近更新 更多