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;

7
儿子。我很失望
swasheck

5
@swasheck您知道在我单击“提交”按钮之前吞下了多少自尊心吗?
billinkc

我并不反对,你只是挽救了我的夜晚。吓人的nVarChar
RThomas'Mar

Answers:


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字符串。它们以非unicode的形式写入sql_variant类型列,然后在proc中传递以进行验证时炸毁。如果我正确地用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但仍然存在此问题。实际上,我抱怨布尔值和日期时间,但是我的参数都不使用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的和布尔你可以硬编码值,但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的所有功能是
很有意义的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.