Выбор данных с двух разных серверов в SQL Server

363

Как выбрать данные в одном запросе из двух разных баз данных, которые находятся на двух разных серверах в SQL Server?

Эрик
источник
6
Ответы от Эрика и Бешеного Быка очень удобны. Я смог использовать это для копирования больших объемов данных из DEV в PROD, сокращая время с 5 до 18 часов, до 17 секунд.
Крис Олдрич
@Eric, спасибо за редактирование незначительно неоднозначного вопроса и превращение его в вопрос с 170 повторениями :)
Eric Wu

Ответы:

345

То, что вы ищете, это связанные серверы. Вы можете получить к ним в SSMS из следующего места в дереве обозревателя объектов:

Server Objects-->Linked Servers

или вы можете использовать sp_addlinkedserver .

Вам нужно только настроить один. После этого вы можете вызвать таблицу на другом сервере следующим образом:

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

Обратите внимание, что владелец не всегда dbo, поэтому не забудьте заменить его на любую схему, которую вы используете.

Эрик
источник
13
мы можем сделать это без связанных серверов?
Steam
5
@Eric, где находятся серверные объекты в SSMS?
Цахи Ашер
9
@TsahiAsher - при подключении к серверу объекты сервера - это папка в дереве проводника объектов.
Эрик
2
Если не известно, вы также можете опустить схему, чтобы использовать по умолчанию. Например [OtherServerName].[OtherDB]..[OtherTable], лучше включить его, если он известен.
Том Бауэрс
92

Вы можете сделать это с помощью Linked Server.

Обычно связанные серверы настраиваются так, чтобы компонент Database Engine мог выполнять инструкцию Transact-SQL, которая включает таблицы в другом экземпляре SQL Server или другом продукте базы данных, таком как Oracle. Многие типы источников данных OLE DB могут быть настроены как связанные серверы, включая Microsoft Access и Excel.

Связанные серверы предлагают следующие преимущества:

  • Возможность доступа к данным извне SQL Server.
  • Возможность выдачи распределенных запросов, обновлений, команд и транзакций для разнородных источников данных по всему предприятию.
  • Способность обращаться к разным источникам данных аналогично.

Узнайте больше о связанных серверах .

Выполните следующие действия, чтобы создать связанный сервер:

  1. Объекты сервера -> Связанные серверы -> Новый связанный сервер

  2. Укажите имя удаленного сервера.

  3. Выберите тип удаленного сервера (SQL Server или другой).

  4. Выберите Security -> Be made с помощью этого контекста безопасности и введите логин и пароль удаленного сервера.

  5. Нажмите ОК, и все готово!

Вот простое руководство по созданию связанного сервера.

ИЛИ

Вы можете добавить связанный сервер, используя запрос.

Синтаксис:

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
Бешеный бык
источник
Примечание. Смотрите здесь, чтобы узнать, как имя сервера может отличаться от имени хоста / порта.
Ричард
1
Небольшой совет, если у вас возникли проблемы с sp_addlinkedserver. Создайте сервер в диалоговом окне - убедитесь, что он работает - затем щелкните правой кнопкой мыши соединение и выберите сценарий [t связанный сервер AS create
Richard Housham
25
SELECT
        *
FROM
        [SERVER2NAME].[THEDB].[THEOWNER].[THETABLE]

Вы также можете посмотреть на использование связанных серверов. Связанные серверы могут быть и другими типами источников данных, такими как платформы DB2. Это один из способов получить доступ к DB2 из вызова SQL Server TSQL или Sproc ...

RSolberg
источник
2
будет ли этот метод работать все время? Какие сценарии, где это может потерпеть неудачу?
Steam
3
Подтверждено, что это не удалось в моем env, ошибка говорит, что мне нужно использовать addlinkedserver
gorlaz
1
Работает ли это на кого-либо, без использования связанного сервера?
Дуг S
проверено и получена ошибка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.
WhatsThePoint
22

Запрос к 2 различным базам данных - это распределенный запрос. Вот список некоторых методов плюс за и против:

  1. Связанные серверы: обеспечивают доступ к более широкому спектру источников данных, чем обеспечивает репликация SQL Server.
  2. Связанные серверы: соединяются с источниками данных, которые репликация не поддерживает или которые требуют специального доступа
  3. Связанные серверы: лучше, чем OPENDATASOURCE или OPENROWSET
  4. Функции OPENDATASOURCE и OPENROWSET : удобны для извлечения данных из источников данных на разовой основе. OPENROWSET имеет также BULK-средства, которые могут / не могут требовать формат файла, который может быть Fiddley
  5. OPENQUERY : не поддерживает переменные
  6. Все это решения T-SQL. Относительно прост в реализации и настройке
  7. Все они зависят от связи между источником и назначением, что может повлиять на производительность и масштабируемость.
super9
источник
OPENQUERY по-прежнему требует связанный сервер, где, как OPENDATASOURCE нет
CJ
16

попробуй это:

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
Анна Карти
источник
16

Это все хорошие ответы, но этот отсутствует, и он имеет свои собственные мощные применения. Возможно, это не соответствует тому, что хотел ОП, но вопрос был расплывчатым, и я чувствую, что другие могут найти свой путь здесь. Как правило, вы можете использовать 1 окно для одновременного выполнения запроса к нескольким серверам, вот как:

В SSMS откройте Зарегистрированные серверы и создайте новую группу серверов в разделе Группы локальных серверов .

В этой группе создайте регистрацию нового сервера для каждого сервера, который вы хотите запросить. Если имена БД отличаются, убедитесь, что для каждого из них задано значение по умолчанию.

Теперь вернитесь к группе, которую вы создали на первом шаге, щелкните правой кнопкой мыши и выберите New Query. Откроется новое окно запроса, и любой выполняемый вами запрос будет выполнен на каждом сервере в группе. Результаты представлены в одном наборе данных с дополнительным именем столбца, указывающим, с какого сервера поступила запись. Если вы используете строку состояния, вы заметите, что имя сервера заменено на несколько .

Павел
источник
2
Кажется, это предполагает, что запрос использует одни и те же таблицы во всех базах данных. (Что хорошо для стандартных таблиц, таких как sys.tables, но маловероятно для пользовательских таблиц, таких как dbo.mycustomers)
Деннис Джаэруддин
Учитывая, что это «один и тот же запрос из двух разных баз данных», он, скорее всего, будет иметь одинаковые таблицы. Но да, я обычно использую этот метод для производственной системы, размещенной на нескольких серверах, и для запроса таблиц MSDB.
Пол
Действительно классная особенность на самом деле. Недостатком является то, что схема набора результатов должна совпадать, поскольку она выполняет запрос дважды и объединяет их все одновременно. Было бы замечательно, если бы вы могли ссылаться на серверы внутри самого SQL, как вы можете ссылаться на связанные серверы, даже если вы не могли присоединиться к результирующему набору результатов, и наборы должны были быть созданы для отдельной оценки.
Кросс
1
@ Кросс, ты вроде как мог. Создайте таблицу #output, сделайте логику на основе @@ SERVERNAME и заполните данные в #output, а затем завершите их выбором. Я сделал аналогичную вещь для запроса информации журнала из набора машин SQL2000 и SQL2008R2, которые имели разные уровни / столбцы информации, но вместо @@ SERVERNAME я использовал переменную версии сервера.
Пол
9

У меня была такая же проблема, чтобы подключить 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.dddIP-адрес удаленного сервера, на котором размещена ваша БД SQLserver.

Шаг 2: Запустите ваши запросы Например:

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

...и это все!

Детали синтаксиса: sp_addlinkedserver и sp_addlinkedsrvlogin

MarcM
источник
4

Создайте определение связанного сервера на одном сервере с другим (для этого вам нужен SA), а затем просто присвойте им 4-элементное именование (см. BOL).

RBarryYoung
источник
4

Server 2008:

Когда в SSMS подключен к server1.DB1 и попробуйте:

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

как отмечали другие, если это не работает, это потому, что сервер не связан.

Я получаю ошибку:

Не удалось найти сервер DB2 в sys.servers. Убедитесь, что указано правильное имя сервера. При необходимости выполните хранимую процедуру sp_addlinkedserver, чтобы добавить сервер в sys.servers.

Чтобы добавить сервер:

ссылка: чтобы добавить сервер с помощью sp_addlinkedserver Ссылка: [1]: чтобы добавить сервер с помощью sp_addlinkedserver

Чтобы увидеть, что находится в вашем sys.servers, просто запросите его:

SELECT * FROM [sys].[servers]
user3586922
источник
3
 select * 
 from [ServerName(IP)].[DatabaseName].[dbo].[TableName]
Masum
источник
2

Как @ Super9 рассказал об OPENDATASOURCE с использованием аутентификации SQL Server с поставщиком данных SQLOLEDB . Я просто публикую здесь фрагмент кода для одной таблицы в текущей базе данных сервера, где выполняется код, а другой на другом сервере '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
Мухаммед Асикуззаман
источник
0
sp_addlinkedserver('servername')

так что это должно идти так -

select * from table1
unionall
select * from [server1].[database].[dbo].[table1]
ugio
источник
0

Я знаю, что это старый вопрос, но я использую синонимы. Предположительно, запрос выполняется на сервере базы данных A и ищет таблицу на сервере базы данных B, которая не существует на сервере A. Добавьте затем синоним в базу данных A, которая вызывает вашу таблицу с сервера B. Ваш запрос не должен включите любые схемы или разные имена баз данных, просто вызовите имя таблицы, как обычно, и это будет работать.

Нет необходимости связывать серверы, так как синонимы, скажем, являются своего рода связью.

Никлас Хенриксон
источник
1
Итак, что же такое «синоним» в этом контексте?
Оскар Берггрен
Это объект базы данных, который ссылается на базовый объект в другой базе данных. Более подробная информация здесь: docs.microsoft.com/en-us/sql/relational-databases/synonyms/…
Никлас Хенриксон,
Круто, я не знал об этой функции. Тем не менее, вы также заявляете, что они избегают необходимости в связанном сервере, но я не понимаю, как. Сами синонимы кажутся просто синонимами и не содержат какой-либо определенной способности удаленного взаимодействия. В примере B на docs.microsoft.com/en-us/sql/t-sql/statements/… они создают связанный сервер, прежде чем ссылаться на него по синониму .
Оскар Берггрен
Правда, я предположил, что базы данных находятся в одной серверной среде. Конечно, вам всегда придется связывать базы данных, если они удалены друг от друга. Нет другого способа получить доступ к базе данных.
Никлас Хенриксон
0

Объекты сервера ---> связанный сервер ---> новый связанный сервер

На связанном сервере введите имя или IP-адрес сервера для другого сервера и выберите SQL Server. В разделе «Безопасность» выберите (сделать это в контексте безопасности). Введите логин и пароль для другого сервера.

Теперь подключен, затем используйте

Select * from [server name or ip addresses ].databasename.dbo.tblname
Sameh
источник
0

Упрощенное решение для добавления связанных серверов

Первый сервер

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]
irfandar
источник