SSIS 2012 Не вдалося створити змінну середовища


12

Я працюю сценарієм для порту середовища з одного сервера на інший. Я зіткнувся з проблемою виклику, в catalog.create_environment_variableякій я отримую помилку "Тип даних вхідного значення не сумісний з типом даних" Рядок "." що виходить із закупівлі "check_data_type_value".

Що дивно, що якщо я випущу сценарій GUI із змінних, цей запит спрацював би

DECLARE @var sql_variant = N'\\myserver\ssisdata'
EXEC [catalog].[create_environment_variable]
    @variable_name = N'FolderBase'
,   @sensitive = False
,   @description = N''
,   @environment_name = N'Development'
,   @folder_name = N'POC'
,   @value = @var
,   @data_type = N'String'
GO

Однак використовувати цей підхід до сценарію не працює. Зроблений вами закон вказує, що це повідомлення про помилку зазвичай вирішується за допомогою типу даних nvarchar замість varchar. Однак це не стосується моїх речей.

Рядок 108 для наступного сценарію. Моє припущення полягає в тому , що це що - то хиткий з sql_variant , але я поняття не маю , що ця річ.

USE SSISDB;
GO

DECLARE
    @folder_id bigint
,   @folder_name nvarchar(128) = N'POC'
,   @environment_name nvarchar(128) = N'Development'
,   @environment_description nvarchar(1024)
,   @reference_id bigint
,   @variable_name nvarchar(128)
,   @data_type nvarchar(128)
,   @sensitive bit
,   @value sql_variant
,   @description nvarchar(1024);

IF NOT EXISTS
(
    SELECT * FROM catalog.folders AS F WHERE F.name = @folder_name
)
BEGIN
    EXECUTE catalog.create_folder
        @folder_name = @folder_name
    ,   @folder_id = @folder_id OUTPUT;

    PRINT CONCAT('Folder "', @folder_name, '" has been created with a folder_id of ', @folder_id)
END

IF NOT EXISTS
(
    SELECT * FROM catalog.environments AS E WHERE E.name = @environment_name 
    AND E.folder_id = (SELECT F.folder_id FROM catalog.folders AS F WHERE F.name = @folder_name)
)
BEGIN
    PRINT CONCAT('Creating environment ',  @environment_name);

    EXECUTE catalog.create_environment
        @folder_name = @folder_name
    ,   @environment_name = @environment_name
    ,   @environment_description = @environment_description;
END

DECLARE
    @EnvironmentVariables TABLE
(
    folder_name nvarchar(128)
,   environment_name nvarchar(128)
,   variable_name nvarchar(128)
,   description nvarchar(1024)
,   data_type nvarchar(128)
,   sensitive bit
,   value sql_variant
);

INSERT INTO
    @EnvironmentVariables
SELECT
    E.folder_name
,   E.environment_name
,   S.name
,   S.description
,   S.type
,   S.sensitive
,   S.value
FROM
(
    SELECT 'FolderBase','Root for ssis processing','String',CAST(0 AS bit),'\\myserver\ssisdata'
    UNION ALL SELECT 'AuditConnectionString','Conn to audit db','String',CAST(0 AS bit),'Data Source=SQLETL01;Initial Catalog=Audit;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;'
) AS S (name, description, type, sensitive, value)
CROSS APPLY
(
    SELECT
        E.name AS environment_name
    ,   F.name AS folder_name
    FROM
        catalog.folders AS F
        INNER JOIN
            catalog.environments AS E
            ON E.folder_id = F.folder_id
    WHERE
        F.name = @folder_name
        AND E.name = @environment_name
) E;


DECLARE Csr CURSOR FORWARD_ONLY STATIC FOR
SELECT
    EV.variable_name
,   EV.description
,   EV.data_type
,   EV.sensitive
,   EV.value
FROM
    @Environmentvariables AS EV;

OPEN Csr;
FETCH NEXT FROM Csr INTO
    @variable_name
,   @description
,   @data_type
,   @sensitive
,   @value;

WHILE @@FETCH_STATUS = 0
BEGIN

    BEGIN TRY
            -- THERE BE MONSTERS AHEAD
        -- The data type of the input value is not compatible with the data type of the 'String'. 
        EXECUTE catalog.create_environment_variable
            @variable_name = @variable_name
        ,   @sensitive = @sensitive
        ,   @description = @description
        ,   @environment_name = @environment_name
        ,   @folder_name = @folder_name
        ,   @value = @value
        ,   @data_type = @data_type
    END TRY
    BEGIN CATCH
        SELECT 
            @folder_name        AS folder_name
        ,   @environment_name   AS environment_name
        ,   @variable_name      AS variable_name
        ,   @data_type          AS data_type
        ,   @sensitive          AS sensitive
        ,   @value              AS value
        ,   @description        AS description
        ,   ERROR_NUMBER()AS error_number --returns the number of the error.
        ,   ERROR_SEVERITY() AS error_severity --returns the severity.
        ,   ERROR_STATE()AS error_state  --returns the error state number.
        ,   ERROR_PROCEDURE() AS error_procedure --returns the name of the stored procedure or trigger where the error occurred.
        ,   ERROR_LINE() AS error_line --returns the line number inside the routine that caused the error.
        ,   ERROR_MESSAGE() AS error_message; --returns the complete text of the error message. The text includes the values supplied for any substitutable parameters, such as lengths, object names, or times.

    END CATCH  

    FETCH NEXT FROM Csr INTO
        @variable_name
    ,   @description
    ,   @data_type
    ,   @sensitive
    ,   @value;
END

CLOSE Csr;
DEALLOCATE Csr;

7
Сину. Я розчарований.
swasheck

5
@swasheck Ви розумієте, скільки гордості проковтнулося, перш ніж я зміг натиснути кнопку "Надіслати"?
billinkc

Я не розчаровуюсь, ви просто врятували мені ніч. Freaking nVarChar
RThomas

Відповіді:


10

"Завершена робота вказує на те, що повідомлення про помилку зазвичай вирішується за допомогою типу даних nvarchar замість varchar. Однак, це не стосується моїх речей." Або це він так?

Я вніс дві зміни в курсор. Перший - у моєму блоці CATCH. Я перечитав статтю про тип даних sql_variant і перейшов із властивістю sql_variant_property . Я додав дзвінок до цього у своєму блоці улову, очікуючи побачити, nvarcharале ось, ось він звітує varcharяк мій BaseType.

Знаючи, що і що всі мої вихідні дані базуються на характерах, я обдурив і додав @localзмінну з явним перекладом на nvarchar, і це магічно працює.

WHILE @@FETCH_STATUS = 0
BEGIN

    BEGIN TRY
        -- THERE BE MONSTERS AHEAD
        -- The data type of the input value is not compatible with the data type of the 'String'. 
        DECLARE
            @local nvarchar(4000) = CONVERT(nvarchar(4000), @value);
        EXECUTE catalog.create_environment_variable
            @variable_name = @variable_name
        ,   @sensitive = @sensitive
        ,   @description = @description
        ,   @environment_name = @environment_name
        ,   @folder_name = @folder_name
        ,   @value = @local
        ,   @data_type = @data_type
    END TRY
    BEGIN CATCH
        SELECT 
            @folder_name        AS folder_name
        ,   @environment_name   AS environment_name
        ,   @variable_name      AS variable_name
        ,   @data_type          AS data_type
        ,   @sensitive          AS sensitive
        ,   @value              AS value
        ,   SQL_VARIANT_PROPERTY(@value, 'BaseType') As BaseType
        ,   @description        AS description
        ,   ERROR_NUMBER()AS error_number --returns the number of the error.
        ,   ERROR_SEVERITY() AS error_severity --returns the severity.
        ,   ERROR_STATE()AS error_state  --returns the error state number.
        ,   ERROR_PROCEDURE() AS error_procedure --returns the name of the stored procedure or trigger where the error occurred.
        ,   ERROR_LINE() AS error_line --returns the line number inside the routine that caused the error.
        ,   ERROR_MESSAGE() AS error_message; --returns the complete text of the error message. The text includes the values supplied for any substitutable parameters, such as lengths, object names, or times.

    END CATCH  

    FETCH NEXT FROM Csr INTO
        @variable_name
    ,   @description
    ,   @data_type
    ,   @sensitive
    ,   @value;
END

CLOSE Csr;
DEALLOCATE Csr;

Аналіз причин

Коли я почав писати резюме висновків, я виявив відключення. Коли я завантажував свою тимчасову таблицю, @EnvironmentVariables, я спочатку catalog.environment_variables.отримував це безпосередньо з, щоб зробити її більш портативною, я скопіював значення у вигляді SELECT заяви. Ось де я накрутив. Коли я відновив ці значення, я перетворив рядки Unicode у «меркантські струни». Вони були записані в стовпчик sql_variant типу як не-унікод, який потім підірвався, коли він був переданий у процедуру для перевірки. Якщо я правильно передрукую свої рядки з Nмодифікатором (?), Вони зберігаються як nvarchar.

FROM
(
    SELECT 'FolderBase','Root for ssis processing','String',CAST(0 AS bit),N'\\myserver\ssisdata'
    UNION ALL SELECT 'AuditConnectionString','Conn to audit db','String',CAST(0 AS bit),N'Data Source=SQLETL01;Initial Catalog=Audit;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;'
) AS S (name, description, type, sensitive, value)

Я використовував варіант цього thefirstsql.com/2013/05/28/… для створення мого сценарію /. Якщо я правильно розумію, мені потрібно переконатися, що всі мої рядкові рядки починаються з Nцього пункту, але у мене все ще є ця проблема. Насправді я отримую скарги на булеві та датові дати, але жоден з моїх параметрів не використовує типи даних htens. Чи маєте ви якесь розуміння?
Nick.McDermaid

1

Просто додати до @billinkc відмінну відповідь (напевно, ви знали, що ви будете одним із них, щоб відповісти на це питання !!) та збагатити знання навколо цього ....

Ось зразок коду, автоматично створений звідси https://thefirstsql.com/2013/05/28/ssis-2012-easily-copy-environment-variables-to-new-servers-or-new-environments/, який видаляє помилку :

DECLARE @var sql_variant

SET @var = '2'
IF NOT EXISTS (
    SELECT 1 FROM [catalog].[environment_variables] 
    WHERE environment_id = @environment_id 
    AND name = N'MyVariable')
EXEC [catalog].[create_environment_variable] 
    @variable_name=N'SystemCd', 
    @sensitive=0, @description=N'', 
    @environment_name=@env_name, 
    @folder_name=@folder, 
    @value=@var, 
    @data_type=N'Int64'

Конкретно помилка

Повідомлення 27147, Рівень 16, Стан 1, Процедура Internal.check_data_type_value, Рядок 22 [Рядок початкового пакету 0] Тип даних вхідного значення не сумісний з типом даних 'Int64'.

У мене були й інші помилки для datetime та boolean

Таким чином, не намагаючись зрозуміти проблему, рішення було в основному використовувати конкретний тип даних, а не sql_variantпередавати значення @valueпараметру.

Для Int64 і Boolean ви можете просто жорстко закодувати значення , але для datetimeвас є попередньо оголосити змінну типу datetimeі використовувати його - ви не можете просто передати в рядок дати литерала

Це перший раз, коли я бачив параметр у збереженій процедурі, мабуть, приймає різні типи даних.

DECLARE @var sql_variant
DECLARE @var_int int

SET @var = '2'
IF NOT EXISTS (
    SELECT 1 FROM [catalog].[environment_variables] 
    WHERE environment_id = @environment_id 
    AND name = N'MyVariable')
EXEC [catalog].[create_environment_variable] 
    @variable_name=N'SystemCd', 
    @sensitive=0, @description=N'', 
    @environment_name=@env_name, 
    @folder_name=@folder, 
    @value=@var_int, 
    @data_type=N'Int64'

Має великий сенс бути явним замість того, щоб використовувати один-розмір-підходить-все-від-SQL-Server-2000
billinkc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.