2016-12-28 19 views
0

Я застрял в следующей проблеме SSIS. Мне нужно создать сложный параметризованный сценарий для компонента OLE DB Source in Data Flow (SQL Server 2008). В дополнение к этому, мне нужно присоединиться к нему с другим источником OLE DB по параметру script. Цель этого упражнения - установить значение в столбце вывода на основе условий, указанных в скрипте. Сценарий должен выглядеть следующим образом (это упрощенный вариант, это гораздо более сложный с участием нескольких IF заявления & сложные соединения):SSIS - Как создать параметр для параметризованного сложного сценария многозадачности в OLE DB Source и присоединиться к этому параметру с другим источником

declare @ind int 
set @ind=0 
if (select status from contracts where contract_id=?)=1 
    then @ind=1 
if (select year(completion_date) from orders where contract_id=?)>2012 
    then @ind=1 
select @ind 

Вопросы:

  1. Это не позволяет мне отобразить параметр если скрипт содержит что-либо помимо простого SELECT (IF, declare и т. д.), получение ошибки «Параметры не могут быть извлечены из SQL Command». Так оно и должно работать? Тогда, наверное, мне может потребоваться переместить его в Хранимую процедуру ...
  2. Даже с сохраненной процедурой я все еще сталкиваюсь с основным препятствием здесь - мне нужно сопоставить этот исходный компонент OLE DB с другим источником by contract_id поле, которое является параметром в этом запросе. Как я могу это сделать?
+0

Можете ли вы расширить свой второй вопрос? немного непонятно, что вы пытаетесь сделать. Что касается первого вопроса, см. Мой ответ ниже. –

+0

У меня есть существующий пакет SSIS, который возвращает несколько строк. Я пытаюсь добавить столбец в этот набор записей с значениями 0/1, основанными на логике моего скрипта. Но этот скрипт имеет параметр contract_id, поэтому мой новый источник OLE DB должен быть связан с существующим источником этим идентификатором, чтобы получить правильные значения 0/1 для каждой строки. Если бы это был единственный SELECT, мне не нужен параметр, я бы присоединился к этому полю, но мой скрипт имел несколько операторов IF, каждый из которых имеет собственный SELECT, а в конце возвращает только значения 0/1. На данный момент мой единственный вариант - преобразовать его в один SELECT –

+0

... и иметь всю логику в производной формуле столбца, но это звучит для меня слишком сложно, есть ли лучшее решение? –

ответ

1

Лео,

Сначала немного. При использовании SQL-запроса с параметрами в исходном компоненте ole db необходимо выполнить две вещи. Во-первых, необходимо определить тип данных (необъявленных) параметров, а второй - метаданные выходных данных запроса.

Я говорю, что параметры не объявлены, потому что в команде sql , которая отправляется на SQL Server, нет операторов объявления, которые определяют типы данных этих параметров. Таким образом, с точки зрения SQL Server, он не знает тип данных, и поэтому эти параметры не объявлены. Сравните это с тем, как мы будем писать один и тот же запрос в SSMS; где мы сначала объявляем переменные (например: declare @my_var int; выбираем val из таблицы where col = @my_var, здесь мы объявили нашу переменную @my_var upfront.).

Так как параметры «необъявленные», при выполнении запроса с SQL Server сначала необходимо определить типы данных этих параметров. И когда дело доходит до этого, SQL Server 2012 имеет лучшие функциональные возможности, чем предыдущие версии.

В SQL Server 2012 был введен новый процесс под названием sys.sp_describe_undeclared_parameters. Эта процедура помогает вывести типы данных даже для сложных операторов tsql. Это может не всегда давать типы данных, которые вы ожидаете, но вы можете дать достаточно подсказок для получения точных типов данных, которые вам нужны. Однако это доступно только в SQL Server 2012 и далее.

Вы сказали, что используете SQL Server 2008. В 2008 году драйвер (Native Client 10.x) создает специальный оператор select (с столбцами, против которых назначены параметры) и использует fmtonly для вывода типов данных для необъявленные параметры. И в моем тестировании это работает только в более простых случаях и терпит неудачу в более сложных операторах tsql. И таким образом вы получите сообщение об ошибке, в котором говорится, что «поставщик не способен ...». Однако, если вы инкапсулируете логику в хранимую процедуру и имеете параметры для этих хранимых процедур, SQL Server может легко найти тип данных для этих «необъявленных» параметров. Becuase: при создании хранимой процедуры мы объявляем типы данных для параметров, драйвер 2008 использует процесс sys.sp_procedure_params_100_rowset для получения типов данных.

Таким образом, использование хранимой процедуры с предопределенными параметрами может быть для вас здесь (потому что вы находитесь в 2008 году).Однако, если вы перейдете на 2012 год или позже, вы сможете опираться на новые функции.

Что касается второй половины получения метаданных вывода запроса, то наличие временных таблиц вызовет вызов. Если вы находитесь на SQL Server 2008, вы можете использовать какое-то творческое использование fmtonly, чтобы обмениваться присутствием временных файлов в сохраненной proc (поиск в Интернете или go here). И если вы находитесь на SQL Server 2012 и далее, вы можете использовать предложение WITH RESULT SETS для работы со временными таблицами.

Update (на основе первого комментарий Лео ниже):

Короткий ответ да. В 2008 году глобальные сложные команды tsl не могли быть проанализированы для вывода параметров и их типов данных. Похоже, что только простые операторы select или утверждения exec proc являются правильными кандидатами. С помощью операторов SELECT, ПРИСОЕДИНИТЕСЬ в порядке; операторы, такие как UNION/INTERSECT/EXCEPT и т. д., являются нормально (если каждый отдельный оператор является оператором select). Подзапросы были не в порядке. Даже теги комментариев, предшествующие другому простому select/exec, вызывают ошибку.

Это то, что я наблюдал за кулисами с водителем 2008 года. Скажем следующее наше выберите заявление с Params:

select A.col_a, A.col_b from dbo.MyTable A where A.col_c = ? and A.col_d = ? 

Затем, когда выводя типы параметров, либо водитель или СТАВКИ (не уверен, какие) конструкции и посылает следующие SQL команды в базе данных:

set fmtonly on; 
select col_c, col_d from dbo.MyTable where 1 = 2; 
set fmtonly off; 

Обратите внимание, что конструкция этого оператора sql. Он содержит два столбца (col_c и col_d), которым назначаются параметры. Кроме того, существует предложение where, чтобы предотвратить возврат каких-либо фактических строк. После построения этот оператор в основном отправляется на сервер sql, так что он может знать, что представляют собой типы данных этих двух столбцов; и таким образом присваивать эти типы данных нашим необъявленным параметрам.

Таким образом, процесс (драйвер или BIDS), пытающийся вывести эти типы данных, способен создавать эти SQL-операторы только в более простых сценариях и не может сделать это в сложных сценариях; в этот момент он выдает ошибку

Однако, если вы должны были использовать procs с 2008 года, конструкция специальных SQL-запросов не выполняется, и вместо этого процесс sys.sp_procedure_params_100_rowset используется для вывода типов данных.

Наконец, если бы вы использовали 2012 (или вперед), то недавно добавленные параметры proc sys.sp_describe_undeclared_parameters были бы более способными и могли бы обрабатывать и некоторые сложные сценарии. В принципе, здесь оператор sql (независимо от его) из вашего src-компонента oledb отправляется как есть вход для вышеупомянутого proc; и proc возвращает набор данных, описывающий типы данных параметров. Итак, для нашего примера, в 2012 году это произойдет:

exec sys.sp_describe_undeclared_parameters N'select A.col_a, A.col_b from dbo.MyTable A where A.col_c = ? and A.col_d = ?' 
+0

Спасибо Сэм за ваш ответ. На самом деле, у меня было другое препятствие. Когда я написал один оператор select для OLE DB Source и нажал на «Параметры», мои параметры были распознаны, но когда я добавил в объявление переменной скрипта или другие функции сценариев, он прекратил распознавать мои параметры. Разве это все еще связано с тем, что, по вашему мнению, может быть проблемой? –

+0

Спасибо Сэм за ваш тщательный ответ, это отвечает на мой первый вопрос –