Je travaille un script pour porter un environnement d'un serveur à un autre. Je rencontre un problème d'appel catalog.create_environment_variable
dans lequel j'obtiens l'erreur "Le type de données de la valeur d'entrée n'est pas compatible avec le type de données de la" chaîne "." sortant du proc "check_data_type_value".
Ce qui est étrange, c'est que si je laisse le script GUI sortir les variables, cette requête fonctionnera
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
Cependant, adopter cette approche de script ne fonctionne pas. Le travail que j'ai fait indique que ce message d'erreur est généralement résolu en utilisant le type de données nvarchar au lieu de varchar. Cependant, ce n'est pas le cas pour mes affaires.
Ligne 108 pour le script suivant. Mon hypothèse est que c'est quelque chose de loufoque avec la sql_variant mais je n'ai aucune idée de ce qu'est cette chose.
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;
la source
Réponses:
"Le travail que j'ai fait indique que ce message d'erreur est généralement résolu en utilisant le type de données nvarchar au lieu de varchar. Cependant, ce n'est pas le cas pour mes affaires." Ou est- ce le cas?
J'ai apporté deux modifications à mon curseur. Le premier est dans mon bloc CATCH. J'ai relu l'article sur le type de données sql_variant et j'ai suivi avec sql_variant_property . J'ai ajouté un appel à cela dans mon bloc catch, en m'attendant à voir
nvarchar
mais voilà, il rapportevarchar
comme mon BaseType.Sachant cela et que toutes mes données sources sont basées sur des caractères, j'ai triché et ajouté la
@local
variable avec un cast explicite à nvarchar et cela fonctionne comme par magie.Analyse de la cause originelle
Alors que je commençais à rédiger un résumé des résultats, j'ai découvert la déconnexion. Pendant que je chargeais ma table temporaire, @EnvironmentVariables, je l'avais initialement fournie directement
catalog.environment_variables.
pour la rendre plus portable, j'ai copié les valeurs sous forme d'instructions SELECT. C'est là que j'ai foiré. Lorsque j'ai reconstitué ces valeurs, j'ai transformé les chaînes Unicode en 'chaînes mercan. Ils ont été écrits dans la colonne de type sql_variant en tant que non-unicode qui a ensuite explosé quand il a été passé dans le proc pour validation. Si je fais correctement précéder mes chaînes duN
modificateur (?), Elles sont stockées sous nvarchar.la source
N
mais j'ai toujours ce problème. En fait, je reçois des plaintes concernant booléen et datetime mais aucun de mes paramètres n'utilise ces types de données. Avez-vous une idée?Juste pour ajouter à @billinkc une excellente réponse (vous saviez sûrement que vous seriez le seul à répondre à cette question !!) et enrichir les connaissances autour de cela ....
Voici un exemple de code, généré automatiquement à partir d'ici https://thefirstsql.com/2013/05/28/ssis-2012-easily-copy-environment-variables-to-new-servers-or-new-environments/ qui génère l'erreur :
Plus précisément, l'erreur est
J'ai également eu d'autres erreurs pour datetime et booléen
Donc, sans aller trop loin dans la compréhension du problème, la solution était essentiellement d'utiliser un type de données spécifique plutôt que de
sql_variant
passer une valeur dans le@value
paramètre.Pour Int64 et Boolean, vous pouvez simplement coder en dur la valeur, mais pour
datetime
vous devez pré-déclarer une variable de typedatetime
et l'utiliser - vous ne pouvez pas simplement passer un littéral de date de chaîneC'est la première fois que je vois un paramètre dans une procédure stockée accepter apparemment une variété de types de données.
la source