Вы находитесь на странице: 1из 61

Лабораторная работа № 4

Исследование работы SSIS


Цель: освоить инструментарий интеграции данных корпоративных
информационных систем
ПО и инструменты: необходимо установить SSDT (SSQT BI), поддеживающие
следующие версии SQL Server: SQL Server 2014, SQL Server 2012, SQL Server
2008 и 2008 R2.

Задание
1. Реализовать интеграцию 2 источников данных и
импорт данных в БД.
2. Индивидуальное задание. Реализовать
заполнение БД из альтернативного источника
(таблицы Excel или MySQL Server)

Теоретические сведения
Источник: https://habrahabr.ru/post/330840/
SSIS – это инструмент, который позволяет в удобном виде реализовать
интеграцию, т.е. реализовать процесс переноса данных из одного источника в
другой. Этот процесс иногда называют ETL (от англ. Extract, Transform, Load –
дословно «извлечение, преобразование, загрузка»).
Необходимые инструменты для изучения SSIS
SSIS будет рассматриваться на примере SQL Server 2014 Developer Edition.
Службы Integration Services доступны в SQL Server 2014 начиная с редакции
Standard.

Дополнительно необходимо будет скачать и установить инструмент


разработчика SQL Server Data Tools (SSDT).

SSDT – это расширение для Visual Studio, которое позволит создавать проекты
необходимого нам типа.

Для облегчения процесса установки, я воспользуюсь SSDT для Visual Studio 2012
(VS2012), его можно скачать по ссылке (файл «SSDTBI_VS2012_x86_ENU.exe»):
www.microsoft.com/en-US/download/details.aspx?id=36843

Если на вашем компьютере не установлен VS данной версии, то установщик


SSDT установит минимальную версию оболочки, которая позволит
создавать проекты нужного нам типа.
Установка SQL Server и SSDT
Первым делом установим SQL Server со всеми необходимыми компонентами. При
наличие ОС Windows 7 SP 1 (x64), ничего дополнительного кроме указанного ниже
устанавливать не придется.

Т.к. курс предназначен для начинающих, то распишу весь процесс установки


подробно.

Запускаем установочный файл SQL Server 2014:

Для работы SSIS достаточно будет выбрать следующие компоненты:

Т.к. мне в дальнейшем понадобится Analysis Services (SSAS), то я отметил и


его, если он вам не нужен вы можете не выбирать данный компонент.
У меня нет других установленных SQL Server, и я сделаю этот экземпляр
используемым по умолчанию:

Сделаю, чтобы SQL Agent запускался автоматически:

При необходимости можно изменить Collation, который будет использоваться по


умолчанию:

Установлю смешанный режим аутентификации, указав свой пароль для


пользователя sa:
Т.к. я еще выбрал Analysis Services, то делаю настройки для него:

Нажимая Next и Install запускаем установку SQL Server и его компонент.

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

Следующим шагом установим SSDT – это расширение для Visual Studio, которое
даст нам возможность создавать проекты SSIS. Установщик SSDT ставит
минимальную версию оболочки VS, поэтому предварительно устанавливать VS
отдельно нет надобности.

Запускаем «SSDTBI_VS2012_x86_ENU.exe», и добравшись до следующего шага


выбираем следующий пункт:
Нажимая Next запускаем установку.

После завершения установки на всякий случай перезагружаем компьютер.

Это все, что нам понадобится для изучения SSIS.


ХОД РАБОТЫ
3. Создание демонстрационных баз данных
Запустим SQL Server Management Studio (SSMS) и при помощи скрипта
создадим 3 базы данных – первые две (DemoSSIS_SourceA и DemoSSIS_SourceB)
будут выступать в роли источников данных, а третья (DemoSSIS_Target) в роли
получателя данных:

-- первая БД выступающая в роли источника данных


CREATE DATABASE DemoSSIS_SourceA
GO

ALTER DATABASE DemoSSIS_SourceA SET RECOVERY SIMPLE


GO

-- вторая БД выступающая в роли источника данных


CREATE DATABASE DemoSSIS_SourceB
GO

ALTER DATABASE DemoSSIS_SourceB SET RECOVERY SIMPLE


GO

-- БД выступающая в роли получателя данных


CREATE DATABASE DemoSSIS_Target
GO

ALTER DATABASE DemoSSIS_Target SET RECOVERY SIMPLE


GO

В базах источниках создадим тестовые таблицы и наполним их тестовыми


данными:

USE DemoSSIS_SourceA
GO

-- продукты из источника A
CREATE TABLE Products(
ID int NOT NULL IDENTITY,
Title nvarchar(50) NOT NULL,
Price money,
CONSTRAINT PK_Products PRIMARY KEY(ID)
)
GO

-- наполняем таблицу тестовыми данными


SET IDENTITY_INSERT Products ON

INSERT Products(ID,Title,Price)VALUES
(1,N'Клей',20),
(2,N'Корректор',NULL),
(3,N'Скотч',100),
(4,N'Стикеры',80),
(5,N'Скрепки',25)
SET IDENTITY_INSERT Products OFF
GO

USE DemoSSIS_SourceB
GO

-- продукты из источника B
CREATE TABLE Products(
ID int NOT NULL IDENTITY,
Title nvarchar(50) NOT NULL,
Price money,
CONSTRAINT PK_Products PRIMARY KEY(ID)
)
GO

-- наполняем таблицу тестовыми данными


SET IDENTITY_INSERT Products ON

INSERT Products(ID,Title,Price)VALUES
(1,N'Ножницы',200),
(2,N'Нож канцелярский',70),
(3,N'Дырокол',220),
(4,N'Степлер',150),
(5,N'Шариковая ручка',15)

SET IDENTITY_INSERT Products OFF


GO

Создадим таблицу в принимающей базе:

USE DemoSSIS_Target
GO

-- принимающая таблица
CREATE TABLE Products(
ID int NOT NULL IDENTITY,
Title nvarchar(50) NOT NULL,
Price money,
SourceID char(1) NOT NULL, -- используется для идентификации источника
SourceProductID int NOT NULL, -- ID в источнике
CONSTRAINT PK_Products PRIMARY KEY(ID),
CONSTRAINT UK_Products UNIQUE(SourceID,SourceProductID),
CONSTRAINT CK_Products_SourceID CHECK(SourceID IN('A','B'))
)
GO

4. Создание SSIS проекта


Запустим Visual Studio 2012 и выберем один из видов предлагаемой нам
настройки среды, так здесь же я откажусь от локальной документации:
Создадим новый проект (File -> New -> Project…):

Для последующего облегчения развертывания зайдем в свойства проекта и


изменим опцию ProtectionLevel на DontSaveSensitive:
То же самое сделаем в свойствах пакета, который создался по умолчанию:

Для всех новых пакетов данное свойство будет заполняться значением из


свойства проекта.

Создадим соединения:
Заполняем параметры соединение с БД:

Боевые параметры соединения в дальнейшем можно будет настроить при


создании задачи SQL Server Agent.
Для удобства я переименую название соединения на SourceA:

Таким же образом создадим и переименуем соединения для


баз DemoSSIS_SourceB и DemoSSIS_Target:

Переименуем пакет, созданный по умолчанию, в «LoadProducts.dtsx»:

Сначала напишем простую логику, которая будет полностью очищать


таблицу Products в базе DemoSSIS_Target и снова загружать в нее данные из
двух баз данных DemoSSIS_SourceA и DemoSSIS_SourceB.

Для очистки воспользуемся компонентом «Execute SQL Task», который мы при


помощи мыши создадим в области «Control Flow»:
Для наглядности можно переименовать название компонент. Зададим ему имя
«Delete All Products From Target»:

Для этой цели используется свойство Name.

Дважды щелкнем на этом элементе и пропишем следующие свойства:

Т.к. TSQL команда «TRUNCATE TABLE Products» ничего не возвращает оставим


свойства ResultSet равным None.
В дальнейшем мы рассмотрим, как пользоваться параметрами и каким образом
можно воспользоваться результатом выполнения команды, записанной в
SQLStatement, а пока попытаемся увидеть всю картину как это работает в
целом.

Теперь скинем в область «Control Flow» компонент «Data Flow Task» и


переименуем его в «Load Products From Source A», а также протянем к этому
компоненту зеленную стрелку от «Delete All Products From Target»:

Таким образом мы создали цепочку, которая будет выполняться


последовательно.

Щелкнув дважды на «Load Products From Source A» мы попадаем в область «Data


Flow» этого элемента.

Data Flow Task – это сложный компонент, который имеет свою область, в
которой создаются вложенные элементы для работы с потоком данных.

Скинем в эту область компонент «Source Assistant»:


Этот компонент отвечает за получение данных из источника. Дважды щелкнув по
нему, мы сможем настроить его:
Пока воспользуемся режимом «Data access mode» равным «Table or view». Это
приведет к получению всех строк из таблицы Products. Посмотреть данные можно
нажав на «Preview…».

На закладке Columns мы можем выбрать только необходимые нам колонки и при


необходимости переименовать их прописав новое имя в колонке «Output
Columns»:

Для получателя нужна еще одна дополнительная колонка SourceID, добавим ее к


выходному набору при помощи компонента «Derived Column», который
переименуем в «Add SourceID», так же протянем синюю стрелку к данному
элементу от «OLE DB Source»:
Дважды щелкнем по элементу «Add SourceID» и пропишем значение «A» в виде
константы:

Здесь я воспользовался функцией преобразования типа (DT_STR,1,1251) для того


чтобы превратить Unicode строку в ANSI.

Теперь создадим компонент «Destination Assistant»:


Направим в него поток от «Add SourceID»:

Дважды щелкнем по «OLE DB Destination» и произведем настройки:


Здесь мы показываем в какую таблицу будет записываться полученный набор.

«Keep identity» используется в случае если в принимающей таблице есть поле с


флагом IDENTITY и мы хотим, чтобы значения в него тоже записывались из
источника (это аналогично включению опции SET IDENTITY_INSERT Products
ON).

Перейдя на закладку Mappings осуществим привязку полей источника с полями


получателя:
Так как у нас поля источника и приемника именуются одинаково, то привязка
осуществилась автоматически.

Можем протестировать работу пакета и убедиться, что данные залились в


таблицу Products базы DemoSSIS_Target.

Запускаем пакет на выполнение из Visual Studio нажав Start или клавишу F5:

Так же пакет можно выполнить, воспользовавшись командой из контекстного


меню:
При помощи «Set as StartUp Object» можно задать пакет, который будет
запускаться по нажатию на Start (F5).

Какой пакет будет запускаться при нажатии на Start (F5) можно


переопределить в свойствах проекта:

По умолчанию будет запускаться пакет открытый в текущий момент, об этом


говорит значение StartObjectID равное <Active Package>.

Запустив проект мы должны увидеть следующую картину:


Пакет выполнился без ошибок, о чем говорит зеленый значок и текст в нижней
части.

В случае наличия ошибок их можно будет увидеть вкладке Progress.

Нажмем на ссылку «Package execution completed…» или на кнопку «Stop


Debugging» расположенную на панели инструментов для остановки
выполнения пакета.

Выполним запрос:

USE DemoSSIS_Target
GO

SELECT *
FROM Products

И убедимся, что данные были записаны в принимающую таблицу.

Перейдем в область «Control Flow» и создадим еще один компонент «Data Task
Flow», который назовем «Load Products From Source B», протянем на него
зеленную стрелку от «Load Products From Source A»:
Двойным щелчком зайдем в область «Data Flow» этого элемента и создадим
«Source Assistant»:

Дважды щелкнув на этом элементе, настроим его по-другому:


Выберем режим «SQL command» и пропишем следующий запрос:

SELECT
ID SourceProductID,
'B' SourceID,
Title,
Price
FROM Products

Дальше сразу создадим компонент «Destination Assistant» и протянем на него


синюю стрелку от «OLE DB Source»:
Двойным щелчком зайдем в редуктор этого элемента и настроим его:
Запустим проект на выполнение и убедимся, что данные с двух источников
попали в таблицу в базе Target:

USE DemoSSIS_Target
GO

SELECT *
FROM Products

Дополнительно в контекстном меню стрелки можно активизировать «Data


Viewer»:

Теперь при запуске пакета на выполнение в этой точке будет сделана остановка и
нам будут показаны данные этого потока:
Для продолжения выполнения пакета нужно нажать на кнопку со стрелкой
или просто закрыть окно просмотра данных.

Для отключения этой функции в контекстном меню стрелки выбираем «Disable


Date Viewer»:

Для первой части думаю этого будет достаточно.

Создадим сборку:

В результате мы получим файл


«C:\SSIS\SSISDemoProject\bin\Development\SSISDemoProject.ispac».

Рассмотрим каким образом делается развертывание этого проекта на SQL


Server.
5. Развертывание SSIS
Все последующие действия будем делать в SSMS.

Создание каталога SSISDB:

Здесь вводим любой пароль.

Теперь создаем папку, в которой будет располагаться наш проект:


Разворачиваем сам проект:
В завершении мы должны увидеть следующую картину:

После обновления (F5) мы увидим наш проект:


6. Создание задачи в SQL Server Agent
Создадим задачу в SQL Agent, для выполнения пакета по расписанию:

Создаем новый шаг:

На вкладке «Configuration → Parameters» можно задать параметры пакета (их


рассмотрим в следующих частях).

На вкладке «Configuration → Connection Manager» мы можем изменить


параметры подключения для каждого соединения, которое мы создали в проекте:
На закладке Advanced можно изменить логику, которая будет использоваться при
успешном или неуспешном завершении шага:

Шаг создан:

Осталось создать расписание для данной задачи:


Расписание можно задать разнообразным образом. Думаю, здесь все должно
быть интуитивно понятно:

Все, задача создана.

Делаем тестовый запуск:

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

В данном журнале можно увидеть успешность завершения каждого шага, а


также время выполнения и прочие параметры.

Более подробный отчет о выполнении пакета можно посмотреть при


помощи следующего отчета:
В этой части изменим логику загрузки справочника Products:

1. При помощи компонента «Union All» объединим два входящих потока в один;
2. Для новых записей будем делать вставку, а для записей, которые уже были
добавлены ранее будем делать обновление. Для разделения записей на
добавляемые и обновляемые воспользуемся компонентом Lookup;
3. Для обновления записей применим компонент «OLE DB Command».

В завершении этой части рассмотрим компонент Multicast для того чтобы распараллелить
выходящий набор.

Итого в этой части мы познакомимся с четырьмя новыми компонентами: Union All, Lookup,
OLE DB Command и Multicast.

Дальше так же будет очень много картинок.

7. Продолжим знакомство с SSIS


Создадим новый пакет:
И переименуем его в «LoadProducts_ver2.dtsx»:

В области «Control Flow» создадим «Data Flow Task»:

Двойным щелчком по элементу «Data Flow Task» зайдем в его область «Data Flow».
Создадим два элемента «Source Assistant» для соединений SourceA и SourceB.
Переименуем эти элементы в «Source A» и «Source B» соответственно:

«Source A» настроим следующим образом:


Текст запроса:

SELECT
ID SourceProductID,
Title,
Price
FROM Products

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


SourceID.

«Source B» настроим следующим образом:


Текст запроса:

SELECT
ID SourceProductID,
'B' SourceID,
Title,
Price
FROM Products

В результате набор A у нас будет иметь 3 колонки [SourceProductID, Title, Price], а


набор B будет иметь 4 колонки [SourceProductID, SourceID, Title, Price].

Воспользуемся элементом «Union All», чтобы объединить данные из 2-х наборов в один.
Направим в него синие стрелки из «Source A» и «Source B»:
Каким образом делается сопоставление колонок двух входящих наборов, можно увидеть
дважды щелкнув на элементе «Union All»:

Как мы видим, здесь сделалось автоматическое сопоставление колонок имена которых


совпадают. При необходимости мы можем сделать свое сопоставление, для примера
добавим колонку SourceID из второго набора:
В данном случае значения SourceID набора «Source A» будут равны NULL.

Объединение двух наборов в данном случае делается на стороне SSIS. Здесь стоит
обратить внимание на то, что базы источники и принимающая база могут располагаться
на разных серверах/экземплярах SQL Server, по этой причине мы не всегда сможем так
просто написать SQL запрос используя в нем таблицы из разных баз с применением SQL-
операции UNION или JOIN (который можно было использовать вместо Lookup описанного
ниже).

Для того чтобы заменить NULL значения на «A» воспользуемся компонентом «Derived
Column» в который направим поток из «Union All»:

Двойным щелчком зайдем в редактор «Derived Column» и настроим его следующим


образом:
Проделаем следующее (мышь в помощь):

1. Укажем в «Derived Column» значение «Replace 'SourceID'» — это будет означать


что мы на выходе заменяем старую колонку SourceID на новую;
2. Перетащим в область «Expression» функцию REPLACENULL;
3. Перетащим на место первого аргумента функции REPLACENULL колонку
SourceID;
4. В качестве второго аргумента пропишем константу «A».

Для того чтобы понять, что произошло с данными после прохождения «Union All»
сделайте «Enable Data Viewer» для стрелки, идущей от «Union All» к «Derived Column»:

Теперь при запуске пакета на выполнение вы сможете увидеть набор, который получился
в результате:
Здесь видно, что на этом этапе (до Derived Column) в колонке SourceID для строк
первого набора стоят значения NULL.

Для того чтобы определить была ли добавлена ранее запись в базу DemoSSIS_Target
воспользуемся компонентом Lookup:

Дважды щелкнув по нему настроим данный элемент:


Здесь мы скажем, что те строки, для которых не найдено соответствие, мы будем
перенаправлять в поток «no match output». В этом случае на выходе мы получим 2 набора
«Lookup Match Output» и «Lookup No Match Output».

Например, если выставить значение «Ignore failure», то в строках, для которых не


нашлось сопоставления в поле TargetID (см. ниже) будет записано значение NULL и все
строки будут возвращены через один набор «Lookup Match Output».

«Full cache» говорит о том, что набор, который будет использоваться в качестве
справочника одним SQL запросом (см.на следующей вкладке) будет полностью загружен
в память и строки будут сопоставляться уже с кэша без повторных обращений к SQL
Server.

Если же выбрать «Partial cache» или «No cache», то на вкладке Advanced можно будет
прописать запрос с параметрами, который будет выполняться для сопоставления каждой
строки входящего набора. Для интереса можно поиграться с этим свойством и через SQL
Server Profiler посмотреть какие будут формироваться запросы при выполнении пакета.

На следующей вкладке нам нужно определить набор, который будет выступать в роли
справочника:
Я прописал здесь запрос:

SELECT
SourceID,
SourceProductID,
ID TargetID
FROM Products

На следующей вкладке нужно указать по каким полям делается поиск строки в


справочнике и какие колонки из справочника нужно добавить в выходной набор (если это
нужно):
Для определение связи нужно при помощи мыши перетащить поле SourceProductID на
SourceProductID и поле SourceID на SourceID.

Добавим компонент «Destination Assistant» для вставки записей с потока «Lookup No


Match Output»:

Перетащим синюю стрелку с «Lookup» на «OLE DB Destination» и в диалоговом окне


выберем поток «Lookup No Match Output»:
В итоге мы получим следующее:

Дважды щелкнув по «OLE DB Destination» настроим его:


Обработку вставки новых записей мы сделали.

Теперь для обновления ранее вставленных записей воспользуемся компонентом «OLE


DB Command» и перенесем на него синюю стрелку от Lookup:

В этот компонент автоматически будет направлен поток «Lookup Match Output», т.к. поток
«Lookup No Match Output» мы уже выбрали ранее:
Дважды щелкнем на «OLE DB Command» и настроим его:
Пропишем следующий запрос на обновление:

UPDATE Products
SET
Title=?,
Price=?
WHERE ID=?

На следующей вкладке укажем каким образом будут задаваться параметры на основании


данных строк входящего набора «Lookup Match Output»:

Через SSMS добавим новых продуктов в базу DemoSSIS_SourceB:

USE DemoSSIS_SourceB
GO

-- добавим новых товаров


SET IDENTITY_INSERT Products ON

INSERT Products(ID,Title,Price)VALUES
(6,N'Точилка',NULL),
(7,N'Ластик',NULL),
(8,N'Карандаш простой',NULL)
SET IDENTITY_INSERT Products OFF
GO

Для того чтобы отследить как менялись данные, вы можете, перед запуском пакета на
выполнение, в необходимых местах сделать «Enable Data Viewer»:

Запустим пакет на выполнение:


В итоге мы должны увидеть, что 3 строки было вставлено при помощи компонента «OLE
DB Destination» и 10 строк обновлено при помощи компонента «OLE DB Command».

Запрос прописанный в «OLE DB Command» выполнился для каждой строки входящего


набора, т.е. в данном примере 10 раз.

В «OLE DB Command» можно прописать более сложную логику на TSQL, например,


сделать проверку, были ли изменены Title или Price, и делать обновление
соответствующей строки только если какое-то из значений отличается.

Для наглядности добавим новую колонку в таблицу Products в базе DemoSSIS_Target:

USE DemoSSIS_Target
GO

ALTER TABLE Products ADD UpdatedOn datetime


GO

Давайте теперь пропишем следующую команду:


Текст команды:

DECLARE @TargetID int=?


DECLARE @Title nvarchar(50)=?
DECLARE @Price money=?

IF(EXISTS(
SELECT Title,Price
FROM Products
WHERE ID=@TargetID
EXCEPT
SELECT @Title,@Price
)
)
BEGIN
UPDATE Products
SET
Title=@Title,
Price=@Price,
UpdatedOn=GETDATE()
WHERE ID=@TargetID
END

Так же можно было бы все это оформить в виде хранимой процедуры, а здесь прописать
ее через вызов «EXEC ProcName ?,?,?». Здесь, думаю, кому как удобнее, мне порой
удобнее, чтобы все было прописано в одном месте, т.е. в SSIS-проекте. Но если
использовать процедуру, то тоже получаем свои удобства, в этом случае можно, было бы
просто изменить процедуру и избежать переделки и повторного развертывания SSIS-
проекта.

После чего переопределим привязку параметров согласно их очередности в тексте


команды:

Сделаем в базе DemoSSIS_SourceA обновление:

USE DemoSSIS_SourceA
GO

UPDATE Products
SET
Price=30
WHERE ID=2 -- Корректор

И снова запустим проект на выполнение. В результате после очередного запуска пакета


на выполнение, UPDATE должен будет выполниться только 1 раз, только для этой
записи.
После выполнения пакета проверим это при помощи запроса:

USE DemoSSIS_Target
GO

SELECT *
FROM Products
ORDER BY UpdatedOn DESC
В рамках данной части рассмотрим еще компонент «Multicast». Данный компонент
позволяет получить из одного потока несколько. Это может быть полезно, когда одни и те
же данные необходимо записать в два или более разных мест – т.е. входит один набор, а
выходит столько его копий сколько нам нужно, и с каждой копией этого набора мы можем
делать что захотим.

Для примера создадим в базе DemoSSIS_Target еще одну таблицу LastAddedProducts:

USE DemoSSIS_Target
GO

CREATE TABLE LastAddedProducts(


SourceID char(1) NOT NULL, -- используется для идентификации источника
SourceProductID int NOT NULL, -- ID в источнике
Title nvarchar(50) NOT NULL,
Price money,
CONSTRAINT PK_LastAddedProducts PRIMARY KEY(SourceID,SourceProductID),
CONSTRAINT CK_LastAddedProducts_SourceID CHECK(SourceID IN('A','B'))
)
GO

Для очистки этой таблицы добавим в область «Control Flow» компонент «Execute SQL
Task» и пропишем в нем команду «TRUNCATE TABLE LastAddedProducts»:
Перейдем в область «Data Flow» компонента «Data Flow Task» и добавим компонент
следующим образом:
Обратите внимание на желтый восклицательный знак – это произошло из-за того, что мы
добавили колонку UpdatedOn и не привязали ее. Зайдем в элемент «OLE DB Destination»,
перейдем на вкладку Mappings оставим для колонки UpdatedOn в качестве входящего
поля Ignore и нажмем OK:

Создадим еще один элемент «OLE DB Destination» и перетащим на него вторую синюю
стрелку от элемента Multicast:
Переименуем для наглядности:

Настроим «To LastAddedProducts»:


Удалим через SSMS три последние вставленные записи:

USE DemoSSIS_Target
GO

DELETE Products
WHERE SourceID='B'
AND SourceProductID>=6

И запустим пакет на выполнение:

В итоге добавление произошло в 2 таблицы – Products и LastAddedProducts.

SSIS достаточно интересный инструмент, который на мой взгляд не помешает иметь в


своем арсенале, так как в некоторых случаях он может сильно упростить процесс
интеграции. Но конечно бывают ситуации, когда все взвесив, разумнее написать
интеграцию прибегая к другим способам, например, использовать Linked Servers и писать
процедуры на чистом TSQL или писать свою утилиту на каком-то другом языке
программирования с применением всей мощи ООП и т.п.

Задание на самостоятельную работу


https://habrahabr.ru/post/330840/

Вам также может понравиться