環境をあるサーバーから別のサーバーに移植するスクリプトを作成しています。 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
ただし、このスクリプトアプローチを使用しても機能しません。私が行ったレッグワークは、このエラーメッセージは通常、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;
「私が行ったレッグワークは、このエラーメッセージは通常、varcharではなくnvarcharデータ型を使用することによって解決されることを示しています。しかし、それは私のものには当てはまりません。」またはisケースですか?
カーソルに2つの変更を加えました。最初は私のCATCHブロックです。 sql_variantデータ型に関する記事を読み直し、 sql_variant_property を続けました。 nvarchar
が表示されることを期待して、catchブロックにその呼び出しを追加しましたが、見たところ、varchar
が私のBaseTypeとして報告されます。
それと、すべてのソースデータが文字ベースであることを知っているので、nvarcharへの明示的なキャストを使用して@local
変数をだまして追加しました。
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型の列に書き込まれ、検証のためにプロシージャに渡されたときに爆発しました。文字列の前に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に優れた答えを追加し(確かにあなたがこの質問に答えるのはあなただとわかっていたはずです!!)、これに関する知識を豊かにしてください。
ここからいくつかのサンプルコードが自動生成されます 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とBooleanの場合は、値をハードコーディングできますが、datetime
の場合haveで、タイプ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'