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

그러나이 스크립트 접근 방식은 작동하지 않습니다. 내가 한 legwork 은이 오류 메시지가 일반적으로 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 2

답변:


10

"내가 한 레거시 (legwork)는이 오류 메시지가 일반적으로 varchar 대신 nvarchar 데이터 형식을 사용하여 해결됨을 나타냅니다. 그러나 그것은 내 물건에는 해당되지 않습니다." 또는 이다 이 경우?

커서를 두 번 변경했습니다. 첫 번째는 CATCH 블록에 있습니다. 나는 SQL_VARIANT 데이터 형식의 기사를 다시 읽어와 함께 다음 SQL_VARIANT_PROPERTY . 나는 catch 블록에 그것에 대한 호출을 추가 nvarchar했지만 lo 를보고 보라 기대 varchar하면서 내 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 문으로 복사했습니다. 내가 망 쳤어 그 값을 재구성 할 때 유니 코드 문자열을 '메르 칸 문자열'로 만들었습니다. 비 유니 코드로 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)

나는이 the firstsql.com/2013/05/28/… 의 변형을 사용하여 내 스크립트 /를 생성했습니다. 올바르게 이해하면 모든 문자열 리터럴로 시작해야 N하지만 여전히이 문제가 있습니다. 사실 부울과 날짜 시간에 대한 불만이 있지만 내 매개 변수는 htese 데이터 형식을 사용하지 않습니다. 통찰력이 있습니까?
Nick.McDermaid 1

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 및 부울 그냥 하드 코드를 값을 수 있지만 위해 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-서버 2000을 사용하는 명시 할 수 있습니다
billinkc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.