Estoy trabajando un script para portar un entorno de un servidor a otro. Me encuentro con un problema de llamada catalog.create_environment_variable
en el que aparece el error "El tipo de datos del valor de entrada no es compatible con el tipo de datos de la 'Cadena'". saliendo del proceso "check_data_type_value".
Lo que es extraño es que si dejo que la secuencia de comandos GUI elimine las variables, esa consulta funcionaría
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
Sin embargo, adoptar este enfoque de script no funciona. El trabajo preliminar que he hecho indica que este mensaje de error generalmente se resuelve usando el tipo de datos nvarchar en lugar de varchar. Sin embargo, ese no es el caso de mis cosas.
Línea 108 para el siguiente guión. Mi suposición es que es algo inestable con la variante sql_ pero no tengo idea de qué es esa cosa.
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;
fuente
Respuestas:
"El trabajo preliminar que hice indica que este mensaje de error generalmente se resuelve usando el tipo de datos nvarchar en lugar de varchar. Sin embargo, ese no es el caso para mis cosas". ¿O es el caso?
Hice dos cambios en mi cursor. El primero está en mi bloque CATCH. Volví a leer el artículo sobre el tipo de datos sql_variant y seguí con la propiedad sql_variant_property . Agregué una llamada a eso en mi bloque catch, esperando ver
nvarchar
pero he aquí, informavarchar
como mi BaseType.Sabiendo eso y que todos mis datos fuente están basados en caracteres, hice trampa y agregué la
@local
variable con un reparto explícito a nvarchar y funciona mágicamente.Análisis de raíz de la causa
Cuando comencé a escribir un resumen de hallazgos, descubrí la desconexión. Cuando estaba cargando mi tabla temporal, @EnvironmentVariables, originalmente la obtuve directamente de
catalog.environment_variables.
Para hacerla más portátil, copié los valores como sentencias SELECT. Aquí es donde lo arruiné. Cuando reconstituí esos valores, convertí las cadenas Unicode en 'cadenas mercan. Se escribieron en la columna de tipo sql_variant como no unicode que luego explotó cuando se pasó en el proceso para la validación. Si presento correctamente mis cadenas con elN
modificador (?), Se almacenan como nvarchar.fuente
N
pero todavía tengo este problema. De hecho, recibo quejas sobre boolean y datetime, pero ninguno de mis parámetros usa tipos de datos htese. ¿Tienes alguna idea?Solo para agregar a @billinkc una excelente respuesta (¡seguramente sabías que serías el que respondería esta pregunta!) Y enriquecerás el conocimiento sobre esto ...
Aquí hay un código de muestra, generado automáticamente desde aquí https://thefirstsql.com/2013/05/28/ssis-2012-easily-copy-environment-variables-to-new-servers-or-new-environments/ que arroja el error :
Específicamente el error es
También tuve otros errores para datetime y boolean
Entonces, sin hacer un gran esfuerzo para comprender el problema, la solución fue básicamente usar un tipo de datos específico en lugar de
sql_variant
pasar un valor al@value
parámetro.Para Int64 y booleano que puede codificar sólo difícil, pero el valor para el
datetime
que tiene de comprobar la validez declarar una variable de tipodatetime
y usarlo - no se puede simplemente pasar en un literal de cadena fechaEsta es la primera vez que veo un parámetro en un procedimiento almacenado que aparentemente acepta una variedad de tipos de datos.
fuente