Estou trabalhando em um script para portar um ambiente de um servidor para outro. Estou enfrentando um problema ao chamar catalog.create_environment_variable
o erro "O tipo de dados do valor de entrada não é compatível com o tipo de dados da 'String'". saindo do processo "check_data_type_value".
O que é estranho é que, se eu deixar o script da GUI exibir as variáveis, essa consulta funcionará
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
No entanto, adotar essa abordagem de script não está funcionando. O trabalho que fiz indica que essa mensagem de erro geralmente é resolvida usando o tipo de dados nvarchar em vez de varchar. No entanto, esse não é o caso das minhas coisas.
Linha 108 para o seguinte script. Minha suposição é que é instável algo com o sql_variant , mas eu não tenho idéia o que essa coisa é.
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;
fonte
Respostas:
"O trabalho que fiz indica que essa mensagem de erro geralmente é resolvida usando o tipo de dados nvarchar em vez de varchar. No entanto, esse não é o caso das minhas coisas." Ou é o caso?
Eu fiz duas alterações no meu cursor. O primeiro está no meu bloco CATCH. Reli o artigo sobre o tipo de dados sql_variant e segui com a sql_variant_property . Adicionei uma chamada a isso no meu bloco de captura, esperando ver
nvarchar
apenas eis que ele é reportadovarchar
como meu BaseType.Sabendo que e que todos os meus dados de origem são baseados em caracteres, trapacei e adicionei a
@local
variável com uma conversão explícita ao nvarchar e funciona magicamente.Análise de causa raiz
Quando comecei a escrever um resumo das descobertas, descobri a desconexão. Enquanto carregava minha tabela temporária, @EnvironmentVariables, originalmente a originara diretamente de
catalog.environment_variables.
Para torná-la mais portátil, copiei os valores como instruções SELECT. Aqui é onde eu estraguei tudo. Quando reconstituí esses valores, transformei as strings Unicode em 'strings mercan. Eles foram gravados na coluna do tipo sql_variant como não unicode, que explodiu quando foi passada no proc para validação. Se eu prefácio corretamente minhas strings com oN
modificador (?), Elas são armazenadas como nvarchar.fonte
N
mas ainda tenho esse problema. Na verdade, recebo reclamações sobre booleano e datetime, mas nenhum dos meus parâmetros usa tipos de dados htese. Você tem alguma ideia?Só para adicionar uma excelente resposta à @billinkc (certamente você sabia que seria o único a responder a essa pergunta !!) e enriquecer o conhecimento sobre isso ....
Aqui está um exemplo de código, gerado automaticamente aqui https://thefirstsql.com/2013/05/28/ssis-2012-easily-copy-environment-variables-to-new-servers-or-new-environments/ que gera o erro :
Especificamente, o erro é
Eu também tive outros erros para datetime e boolean
Portanto, sem se esforçar muito para entender o problema, a solução era basicamente usar um tipo de dados específico, e não
sql_variant
ao passar um valor para o@value
parâmetro.Para Int64 e Boolean, você pode apenas codificar o valor, mas
datetime
é necessário declarar previamente uma variável do tipodatetime
e usá-la - você não pode simplesmente passar um literal de data da stringEsta é a primeira vez que vi um parâmetro em um procedimento armazenado aparentemente aceitar uma variedade de tipos de dados.
fonte