SR0014 : Une perte de données peut se produire lors du cast de {Type1} en {Type2}

Id de la règle

SR0014

Catégorie

Microsoft.CSharp

Modification avec rupture

Modification sans rupture

Cause

Le type de données d'une colonne, d'une variable ou d'un paramètre est converti implicitement vers un autre type de données.

Description de la règle

Si les types de données sont assignés de façon inconsistante aux colonnes, variables ou paramètres, ils sont convertis implicitement lorsque le code Transact-SQL qui contient ces objets est exécuté. Ce type de conversion réduit non seulement les performances mais provoque également, dans certains cas, des pertes subtiles de données. Par exemple, une analyse de table peut s'exécuter si chaque colonne dans une clause WHERE doit être convertie. Pire, les données peuvent être perdues si une chaîne Unicode est convertie en une chaîne ASCII qui utilise une page de codes différente.

Cette règle n'exécute pas les opérations suivantes :

  • Vérifiez le type d'une colonne calculée parce que le type n'est pas connu jusqu'à temps d'exécution.

  • Analysez n'importe quoi à l'intérieur d'une instruction CASE. Il n'analyse pas également la valeur de retour d'une instruction CASE.

  • Analyser les paramètres d'entrée ou valeur de retour d'un appel à ISNULL

Objets CLR SQL

Pour les objets SQL CLR SQL Server, les contrôles suivants sont exécutés :

Type d'objet

Vérifie la compatibilité de type

Vérifie la perte de données potentielle

Columns

Oui

Non

Paramètres de procédure stockée et de fonction

Non

Non

Variables

Non

Non

Types XML

Non

Non

Lorsque vous assignez un objet à un autre et les deux sont des types d'objet CLR SQL, ils doivent être du même type ou un avertissement sera généré. Vous pouvez convertir explicitement uniquement les éléments suivants en un type d'objet CLR SQL ou un avertissement apparaît : binary, varbinary, char, nchar, varchar ou nvarchar.

Fonctions système

Le type de retour est vérifié pour les fonctions système suivantes : @@ERROR, @@FETCH_STATUS, @@IDENTITY, @@ROWCOUNT, @@TRANCOUNT, CHECKSUM, CHECKSUM_AGG, COUNT, COUNT_BIG, GROUPING, STDEV, STDEVP, VAR, ARP, RANK, DENSE_RANK, NTILE, ROW_NUMBER, CURSOR_STATUS, SYSDATETIME, SYSDATETIMEOFFSET, SYSUTCDATETIME, DATEDIFF, DATENAME, DATEPART, DAY, MONTH, YEAR, CURRENT_TIMESTAMP, GETDATE, GETUTCDATE, AVG, SUM, MIN, MAX, DATEADD, SWITCHOFFSET, TODATETIMEOFFSET et ISNULL.

Notes

Aucun contrôle n'est effectué pour vérifier que les entrées sont valides dans le contexte de fonction, sauf pour les fonctions LEFT, RIGHT, CONVERT et CAST. Par exemple, aucun avertissement n'apparaît pour SUM(type datetime2) parce que l'analyse du code de base de données ne comprend pas le type d'entrée attendu par la fonction SUM. Un avertissement apparaîtra s'il y a un problème avec l'expression d'entrée elle-même, par exemple si vous avez spécifié SUM(money + real).

Vérifications spécifiques qui sont exécutées

Le tableau suivant décrit des vérifications spécifiques qui sont exécutées, avec un exemple pour chacune d'elles :

Construction de langage

Vérifications

Exemple

Valeur par défaut de paramètres

Type de données de paramètre

CREATE PROCEDURE p1(
@p1 INT = 1)
AS
BEGIN
END

Prédicat CREATE INDEX

Le prédicat est Boolean

CREATE INDEX index1 ON table1 (column1) 
WHERE column1 > 10

Arguments des fonctions LEFT ou RIGHT

Longueur et type d'argument de chaîne

SET @v = LEFT('abc', 2)

Arguments des fonctions CAST et CONVERT

L'expression et les types sont valides

SET @v = CAST('abc' AS CHAR(10))

Instruction SET

Le côté gauche et côté droit ont des types compatibles

SET @v1 = 'xyz'
SELECT @v1 = c1 FROM t1

Prédicat d'instruction IF

Le prédicat est Boolean

IF (@v > 10)

Prédicat d'instruction WHILE

Le prédicat est Boolean

WHILE (@v > 10)

Instruction INSERT

Les valeurs et colonnes sont correctes

INSERT INTO t1(c1, c2) VALUES (99, 'xyz')
INSERT INTO t1 SELECT c1 FROM t2.
RemarqueRemarque
Les caractères génériques ne sont pas vérifiés.Par exemple : INSERT INTO t1 SELECT * FROM t2

Prédicat SELECT WHERE

Le prédicat est Boolean

SELECT * FROM t1 WHERE c1 > 10

Expression SELECT TOP

L'expression est un type Integer ou Float

SELECT TOP 4 * FROM t1 
SELECT TOP 1.5 PERCENT * FROM t1

Instruction UPDATE

L'expression et la colonne ont des types compatibles

UPDATE t1 SET c1 = 100

Prédicat UPDATE

Le prédicat est Boolean

UPDATE t1 SET c1 = 100 
WHERE c1 > 100

Expression UPDATE TOP

L'expression est un type Integer ou Float

UPDATE TOP 4 table1

DELETE PREDICATE

Le prédicat est Boolean

DELETE t1 WHERE c1 > 10

Expression DELETE TOP

L'expression est un type Integer ou Float

DELETE TOP 2 FROM t1

Déclaration de variable DECLARE

La valeur initiale et le type de données sont compatibles

DECLARE @v INT = 10

Arguments d'instruction EXECUTE et type de retour

Paramètres et arguments

CREATE PROCEDURE p1 (@p1 INT) AS
GO
EXECUTE p1 100
EXECUTE @v1 = p1 100

RETURN, instruction

L'expression RETURN a un type de données compatible

CREATE FUNCTION f1() RETURNS INT
AS
BEGIN
  RETURN 100
END

Conditions de l'instruction MERGE

La condition est Boolean

MERGE t1 USING t2
ON t1.c1 = t2.c2
WHEN t1.c1 > 10 THEN DELETE

Comment corriger les violations

Vous pouvez éviter et résoudre ces problèmes en assignant des types de données de façon cohérente et en convertissant des types explicitement où ils sont exigés. Pour plus d'informations sur comment convertir des types de données explicitement, consultez cette page sur le site Web Microsoft : CAST et CONVERT (Transact-SQL).

Quand supprimer les avertissements

Vous ne devez pas supprimer ce type d'avertissement.

Exemple

Cet exemple montre deux procédures stockées qui insèrent des données dans une table. La première procédure, procWithWarning, provoquera une conversion implicite d'un type de données. La deuxième procédure, procFixed, indique comment ajouter une conversion explicite pour optimiser les performances et conserver toutes les données.

CREATE TABLE [dbo].[Table2] 
( 
[ID] INT NOT NULL IDENTITY(0, 1), 
[c1] INT NOT NULL , 
[c2] INT NOT NULL , 
[c3] BIGINT NOT NULL , 
[Comment] VARCHAR (25)
)
ON [PRIMARY]

CREATE PROCEDURE [dbo].[procWithWarning]
(
@Value1 INT,
@Value2 INT,
@Value3 BIGINT,
@Comment CHAR(30)
) 
AS 
BEGIN
INSERT INTO [Table2] ([c1], [c2], [c3], Comment) 
VALUES (@Value1, @Value2, @Value3, @Comment) 

END

CREATE PROCEDURE [dbo].[procFixed]
(
@Value1 INT,
@Value2 INT,
@Value3 BIGINT,
@Comment CHAR(10)
) 
AS 
BEGIN
INSERT INTO [Table2] ([c1], [c2], [c3], Comment) 
VALUES (@Value1, @Value2, @Value3, CAST(@Comment AS VARCHAR(25))) 

END

Voir aussi

Concepts

Analyse du code de base de données pour en améliorer la qualité