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


363

Як я можу вибрати дані в одному запиті з двох різних баз даних, які є на двох різних серверах у SQL Server?


6
Відповіді від Еріка та Raging Bull дуже зручні. Мені вдалося скористатися цим способом, щоб скопіювати масовий обсяг даних від DEV до PROD скорочення часу від 5 годин до 18 годин до 17 секунд.
Кріс Олдріч

@Eric, kudos для редагування неоднозначного питання та перетворення його на 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

Це можна зробити за допомогою пов'язаного сервера.

Як правило, пов'язані сервери налаштовані так, щоб увімкнути Database Engine для виконання оператора Transact-SQL, який включає таблиці в іншому екземплярі SQL Server або іншому продукті бази даних, такому як Oracle. Багато типів джерел даних OLE DB можуть бути налаштовані як пов'язані сервери, включаючи Microsoft Access та Excel.

Пов'язані сервери пропонують такі переваги:

  • Можливість доступу до даних за межами SQL Server.
  • Можливість видавати розподілені запити, оновлення, команди та транзакції з неоднорідних джерел даних по всьому підприємству.
  • Можливість аналогічно вирішувати різні джерела даних.

Детальніше про пов'язані сервери .

Для створення пов'язаного сервера виконайте наступні дії:

  1. Об'єкти сервера -> Пов'язані сервери -> Новий пов'язаний сервер

  2. Укажіть віддалене ім’я сервера.

  3. Виберіть тип віддаленого сервера (SQL Server або інше).

  4. Виберіть Захист -> Будьте зроблені за допомогою цього контексту безпеки та введіть логін та пароль віддаленого сервера.

  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 пов'язаний сервер як створити
Річард Хоушам

25
SELECT
        *
FROM
        [SERVER2NAME].[THEDB].[THEOWNER].[THETABLE]

Ви також можете переглянути використання пов'язаних серверів. Пов'язані сервери також можуть бути іншими типами джерел даних, наприклад, платформи DB2. Це один із способів спроби отримати доступ до DB2 з виклику TSQL SQL або Sproc ...


2
чи буде цей метод працювати весь час? які сценарії, де це може вийти з ладу?
Пар

3
Підтверджено, що це не вдається в моєму оточенні, помилка говорить про те, що мені потрібно було використовувати addlinkedserver
gorlaz

1
Чи працює це для когось, не використовуючи пов'язаний сервер?
Doug 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

Запит у двох різних базах даних - це розподілений запит. Ось перелік деяких методів плюс плюси і мінуси:

  1. Пов'язані сервери: надають доступ до більш широкого спектру джерел даних, ніж надає реплікація SQL Server
  2. Пов'язані сервери. Підключіться до джерел даних, які не підтримують реплікацію або потребують спеціального доступу
  3. Пов'язані сервери: Діють краще, ніж OPENDATASOURCE або OPENROWSET
  4. Функції OPENDATASOURCE та OPENROWSET : Зручні для отримання даних із спеціальних джерел даних на спеціальній основі. OPENROWSET також має засоби BULK, які можуть / не потребуватимуть файлу формату, який може бути загадковим
  5. OPENQUERY : Не підтримує змінні
  6. Всі це рішення T-SQL. Порівняно простий у виконанні та налаштуванні
  7. Всі вони залежать від зв'язку між джерелом та розбиванням, що може вплинути на продуктивність та масштабованість

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 відкрийте Зареєстровані сервери та створіть нову групу серверів у розділі Локальні серверні групи .

Під цією групою створіть нову реєстрацію сервера для кожного сервера, який ви хочете запитувати. Якщо імена БД відрізняються, переконайтеся, що встановіть значення за замовчуванням для кожного з властивостей.

Тепер поверніться до групи, яку ви створили на першому кроці, клацніть правою кнопкою миші та виберіть Новий запит. Відкриється нове вікно запитів, і будь-який запущений запит буде виконуватися на кожному сервері в групі. Результати представлені в одному наборі даних із додатковою назвою стовпця із зазначенням того, з якого сервера прийшов запис. Якщо ви використовуєте рядок стану, ви помітите, що ім'я сервера замінено на кілька .


2
Це, мабуть, передбачає, що запит використовує однакові таблиці у всіх базах даних. (Що нормально для стандартних таблиць, таких як sys.tables, але мало ймовірно для таблиць, виготовлених на замовлення, таких як dbo.mycustomers)
Dennis Jaheruddin

Враховуючи, що це "один і той же запит з двох різних баз даних", велика ймовірність мати однакові таблиці. Але так, я зазвичай використовую цей метод для виробничої системи, розміщеної на декількох серверах, і для запитів таблиць MSDB.
Павло

Дійсно класна функція насправді. Недолік - схема набору результатів повинна відповідати, оскільки вона виконує запит двічі і об'єднує їх усі одночасно. Було б чудово, якби ви могли посилатися на сервери всередині самого SQL, як ви можете на пов'язаних серверах, навіть якщо ви не змогли ПРИЄДНАТИ набір результатів і набори повинні бути побудовані для оцінки окремо.
Кросс

1
@Kross ви начебто могли. Створіть таблицю #output, виконайте логіку на основі @@ SERVERNAME і заповніть дані в #output, а потім закінчіть її вибором на цьому. Я зробив аналогічну справу для запиту інформації журналу із суміші машин SQL2000 та SQL2008R2, які мали різні рівні / стовпці інформації, але замість @@ SERVERNAME я використовував змінну версії сервера.
Павло

9

У мене виникла проблема з підключенням SQL_server 2008 до SQL_server 2016, розміщеного на віддаленому сервері. Інші відповіді не спрацювали для мене прямо. Я пишу тут своє перероблене рішення, оскільки думаю, що воно може бути корисним для когось іншого.

Розширена відповідь для віддалених IP-з'єднань db:

Крок 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- ip-адреса віддаленого сервера, на якому розміщується ваша база даних SQLserver.

Крок 2. Запустіть запити, наприклад:

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

...і це все!

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


4

Створено визначення пов'язаного сервера на одному сервері на іншому (для цього вам потрібен SA), а потім просто посилайте їх на 4-частинне іменування (див. BOL).


4

Сервер 2008:

Коли в SSMS підключено до сервера1.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]


2

Як @ Super9 розповів про OPENDATASOURCE за допомогою аутентифікації SQL Server із постачальником даних SQLOLEDB . Я просто розміщую тут фрагмент коду для однієї таблиці знаходиться в поточній базі даних sever, де працює код, а інший на іншому сервері '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]

0

Я знаю, що це старе питання, але я використовую синоніми. Нібито запит виконується на сервері баз даних A і шукає таблицю на сервері баз даних B, якої не існує на сервері А. Додайте потім синонім до бази даних, яка викликає вашу таблицю з сервера B. Ваш запит не повинен включіть будь-які схеми чи різні імена бази даних, просто зателефонуйте до імені таблиці, як це звичайно, і це спрацює.

Немає необхідності пов'язувати сервери, оскільки синоніми за словом є своєрідними посиланнями.


1
Тепер, що таке "синонім" у цьому контексті?
Оскар Берггрен

Це об'єкт бази даних, який посилається на базовий об'єкт в іншій базі даних. Більше інформації тут: docs.microsoft.com/en-us/sql/relational-databases/synonyms/…
Niklas Henricson

Класно, я не знав про цю особливість. Однак ви також заявляєте, що вони уникають потреби в пов'язаному сервері, але я не розумію як. Самі синоніми, здається, є саме цим синонімом, а самі по собі не містять певної здатності до видалення. У прикладі B на docs.microsoft.com/en-us/sql/t-sql/statements/… вони створюють зв'язаний сервер перед посиланням на нього із синоніма.
Оскар Берггрен

Правда, я припускав, що бази даних знаходяться в одному серверному середовищі. Звичайно, вам завжди доведеться зв’язувати бази даних, якщо вони віддалені одна від одної. Немає іншого способу доступу із співвідношенням база даних до бази даних.
Ніклас Генрісон

0

Об'єкти сервера ---> пов'язаний сервер ---> новий пов'язаний сервер

На пов'язаному сервері записуйте ім'я сервера або IP-адресу для іншого сервера та виберіть SQL Server In Security, виберіть (робиться з використанням цього контексту безпеки) Напишіть логін та пароль для іншого сервера

Тепер підключено, тоді використовуйте

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

0

Спрощене рішення для додавання пов'язаних серверів

Перший сервер

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

Другий Логін

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

Виконати запити з посилання на локальний db

INSERT INTO Tbl (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM [ip,port\instancename].[linkedDBName].[linkedTblSchema].[linkedTblName]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.