ETL-процесс с использованием веб-сервисов в Integration Services 2012

в 20:13, , рубрики: big data, BigData, Business Intelligence, c#.net, data mining, datamining, etl, MS Sql Server, SSIS, XML, метки: , , , , , , ,

Запасаем впрок

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

ETL-процесс (Extract — Transform — Load) это термин из Business Intelligence и описывает процесс сбора и трансформации данных для создания аналитической базы данных (например хранилища данных).

SOAP протокол обмена данных и веб-сервисы описываемые WSDL — распространенные окна в мир практически всех ERP систем, многих онлайн порталов и финансовых организаций.

Попробую описать пошагово ETL процесс с помощью одного из мощнейших инструментов в классе — MS Integration Services.

Итак, рассмотрим тестовую задачу.

Задача

Необходимо собрать данные о курсах валют по отношению к рублю на каждую дату прошлого года и загрузить их в таблицу для последующего анализа. Центробанк России предоставляет историчекие данные — в виде веб сервисов с неплохим описанием.
Похоже это и есть решение.

Создаем проект

Для начала создадим проект в Business Intelligence Development Studio (А с недавних пор — SQL Server Data Tools)

Во тулбоксе есть элемент Web-service-task, его мы и перенесем на рабочую область.
ETL процесс с использованием веб сервисов в Integration Services 2012

В строке HttpConnection создадим новое соединение — выбрав NewConnection
и поставим URL http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx
К слову, можете зайти туда — не стесняйтесь.

WSDL — файл доступен там-же, вот он www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL
Скачайте и выберете его в диалоге настройки.

Все, переходим во вкладку Input

image

Тут можно выбрать среди сервисов и их методов — поставляемых провайдером.
Нам нужен GetCourseOnDate — выдающий DataSet на запрашиваемую дату.
Проставим значение даты вручную — в поле Value, чуть позже вернемся и автоматизируем это.
Output cделаем просто в файл создав новое соединение output — в файл output.xml

image

Запустим процесс — дело пошло. Файл создается — курсы валют выгялядят как курсы валют.
Формат странноват: diffgr аттрибуты, инлайн-схема. Это XML выдача объекта Dataset.

В BI-студии есть XML-Source коннектор — он выдает нулевой результат при попытке натравить его на такой файл. (Схему считывает).

Поставим после Web Service Task — Skript Task.

Workaround

Скрытый текст

   object rawConnection = Dts.Connections["output"].AcquireConnection(Dts.Transaction);
            DataSet CoursesFile = new DataSet();
           string filePath = (string)rawConnection;
           object rawConnection2 = Dts.Connections["output2"].AcquireConnection(Dts.Transaction);
           string filePath_Out = (string)rawConnection2;
            object rawConnection3 = Dts.Connections["output.xsd"].AcquireConnection(Dts.Transaction);
           string filePath_Schema = (string)rawConnection3;
            CoursesFile.ReadXml(@filePath);
            CoursesFile.AcceptChanges();
            CoursesFile.WriteXmlSchema(@filePath_Schema);
            CoursesFile.WriteXml(@filePath2);

Скрипт на C#, можно использовать весь инструментарий .net платформы и 2012 VisualStudio.
Я добавил в начало using System.Xml;
Обращаемся к коллекции соединений — я создал еще 2, для сохранения схемы и для вывода.

На выходе чистый XML — благодаря acceptChanges();

Reconsidering the Beginning

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

Для начала создадим временное измерение, оно пригодится и еще не раз — в каждом хранилище данных.

Я создаю своей вариацией подсмотенного в сети скрипта, вот он.

Скрытый текст

-- Delete time dimension if it already exists.
IF Exists(Select Name from sysobjects where name = 'Dim_Time')
BEGIN
    Drop Table Dim_Time
END
GO
 
-- Standard options for creating tables
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
-- Create your dimension table
-- Adjust to your own needs
Create Table dbo.Dim_Time
(
    Dateid int IDENTITY (1,1) PRIMARY KEY CLUSTERED,
    Date date,
    DateString varchar(10),
    Day int,
    DayofYear int,
    DayofWeek int,
    DayofWeekName varchar(10),
    Week int,
    Month int,
    MonthName varchar(10),
    Quarter int,
    Year int,
    IsWeekend bit,
    IsLeapYear bit
)
 
-- Declare and set variables for loop
Declare
@StartDate datetime,
@EndDate datetime,
@Date datetime
 
Set @StartDate = '2000/01/01'
Set @EndDate = '2020/12/31'
Set @Date = @StartDate
 
-- Loop through dates
WHILE @Date <=@EndDate
BEGIN
    -- Check for leap year
    DECLARE @IsLeapYear BIT
    IF ((Year(@Date) % 4 = 0) AND (Year(@Date) % 100 != 0 OR Year(@Date) % 400 = 0))
    BEGIN
        SELECT @IsLeapYear = 1
    END
    ELSE
    BEGIN
        SELECT @IsLeapYear = 0
    END
 
    -- Check for weekend
    DECLARE @IsWeekend BIT
    IF (DATEPART(dw, @Date) = 1 OR DATEPART(dw, @Date) = 7)
    BEGIN
        SELECT @IsWeekend = 1
    END
    ELSE
    BEGIN
        SELECT @IsWeekend = 0
    END
 
    -- Insert record in dimension table
    INSERT Into Dim_Time
    (
    [Date],
    [DateString],
    [Day],
    [DayofYear],
    [DayofWeek],
    [Dayofweekname],
    [Week],
    [Month],
    [MonthName],
    [Quarter],
    [Year],
    [IsWeekend],
    [IsLeapYear]
    )
    Values
    (
    @Date,
    CONVERT(varchar(10), @Date, 105), -- See links for 105 explanation
    Day(@Date),
    DATEPART(dy, @Date),
    DATEPART(dw, @Date),
    DATENAME(dw, @Date),
    DATEPART(wk, @Date),
    DATEPART(mm, @Date),
    DATENAME(mm, @Date),
    DATENAME(qq, @Date),
    Year(@Date),
    @IsWeekend,
    @IsLeapYear
    )
 
    -- Goto next day
    Set @Date = @Date + 1
END
GO

Перенесем на рабочую область новый элемент

image

image

Базу TEST и OLE DB соединение localhost.TEST создали попутно.

Как заставить процесс брать каждую дату из результата и передавать ее на WebServiceTask.

С помощью переменных.

Переменные

Правый щелчок на рабочей области — Variables. Или меню View — Other Windows — Variables. Это очень мощный инструмент, но мы упомянем его лишь вскользь, без него SSIS не могут и половины заявленного.
Создим переменную UDate типа System.Object, т.к. будем выводить результат запроса.
Соединим ее с нашим SQL Task

image

Теперь добавим последовательно к SQL-Task Foreach Loop Container.
Это контейнер (туда можно засунуть любую последовательность действий), он выполняет foreach рутину.
В нашем случае он будет выполнять соединение с веб-сервисами и запись курсов валют для каждой даты из набора UDate.

Вот так он настраивается

image
image

Созданая нами переменная Date типа Date — будет доступна внутри контейнера — так мы передадим актуальную для записи дату.

Вот что мы положим в контейнер

image

Посмотрим что за DataFlow следует за нашим скриптом — там все просто. Читаем XML с помощью XML — Source,
добавляем колонку Date — записываем в таблицу.
И так для каждой даты.

image

В элементе Derived Column — вставляем нашу переменную Date — для записи в базу.

Вот такой результат получается
image

Автор: Alex509

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js