SSIS 2012環境変数の作成が失敗する


12

環境をあるサーバーから別のサーバーに移植するスクリプトを作成しています。私はcatalog.create_environment_variable「入力値のデータ型が「文字列」のデータ型と互換性がありません」というエラーを受け取る問題の呼び出しに直面しています。proc "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

ただし、このスクリプトアプローチを使用しても機能しません。私が行ったレッグワークでは、このエラーメッセージは通常、varcharではなくnvarcharデータ型を使用して解決されることを示しています。しかし、それは私のものには当てはまりません。

次のスクリプトの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

回答:


10

「私がやった仕事は、このエラーメッセージは通常varcharではなくnvarcharデータ型を使用することで解決されることを示しています。しかし、私の場合はそうではありません。」それともあるそれはケース?

カーソルに2つの変更を加えました。1つはCATCHブロックにあります。I sql_variant型のデータ型についての記事を再読み込み、と続いsql_variant_property。catchブロックにそれへの呼び出しを追加しました。見た目は期待しますnvarcharvarchar、見た目はBaseTypeとして報告します。

それと、すべてのソースデータが文字ベースであることを知って、@localnvarcharへの明示的なキャストで変数をごまかして追加しました。

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型の列に非ユニコードとして書き込まれ、検証のために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/…のバリアントを使用して、script /を生成しました。正しく理解したら、すべての文字列リテラルが最初から始まることを確認する必要がありますが、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 [バッチ開始行0]入力値のデータ型は、 'Int64'のデータ型と互換性がありません。

日時とブール値には他のエラーもありました

したがって、問題を深く理解することなく、ソリューションは基本的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'

one-size-fits-all-from-SQL-Server-2000を使用する代わりに明示的にするのは非常に理にかなっています
billinkc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.