SSIS 2012 Создать переменную среды не удалось

12

Я работаю сценарий для переноса среды с одного сервера на другой. Я сталкиваюсь с проблемой вызова, в catalog.create_environment_variableкоторой я получаю сообщение об ошибке «Тип данных входного значения не совместим с типом данных« String ».» выход из процесса "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;
billinkc
источник
7
Сын. Я разочарован.
swasheck
5
@swasheck Вы понимаете, сколько гордости было поглощено, прежде чем я смог нажать кнопку Отправить?
billinkc
Я не разочарован, ты только что спас мою ночь. Freaking nVarChar
RThomas

Ответы:

10

«Работа, которую я сделал, показывает, что это сообщение об ошибке обычно разрешается с использованием типа данных nvarchar вместо varchar. Однако, это не относится к моим вещам». Или это он так?

Я сделал два изменения в моем курсоре. Первый находится в моем блоке CATCH. Я перечитал статью о типе данных sql_variant и добавил sql_variant_property . Я добавил вызов к этому в моем блоке catch, ожидая увидеть, 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 в строки Mercan. Они были записаны в столбец типа sql_variant как non-unicode, который затем взорвался, когда он был передан в процесс для проверки. Если я правильно ввел свои строки с 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)
billinkc
источник
Я использовал вариант этого thefirstsql.com/2013/05/28/… для генерации моего скрипта /. Если я правильно понимаю, мне нужно убедиться, что все мои строковые литералы начинаются с, Nно у меня все еще есть эта проблема. На самом деле я получаю жалобы на логические значения и дату, но ни один из моих параметров не использует типы данных htese. Есть ли у вас понимание?
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 [Batch Start Line 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'
Nick.McDermaid
источник
Имеет большой смысл, чтобы быть явным, вместо того чтобы использовать один размер подходит всем от SQL-Server-2000
billinkc