SR0014: Se pueden perder datos cuando se convierte de {Tipo1} a {Tipo2}

Identificador de regla

SR0014

Categoría

Microsoft.Design

Cambio problemático

Poco problemático

Causa

El tipo de datos de una columna, variable o parámetro se convierte implícitamente en otro tipo de datos.

Descripción de la regla

Si los tipos de datos están asignados incoherentemente a columnas, variables o parámetros, implícitamente se convierten cuando se ejecuta el código de Transact-SQL que contiene esos objetos. Este tipo de conversión no solo reduce el rendimiento, si no que también, en algunos casos, produce una leve pérdida de datos. Por ejemplo, un examen de la tabla se podría ejecutar si se debe convertir cada columna de una cláusula WHERE. Lo que es peor, se podrían perder los datos si una cadena Unicode se convierte en una cadena ASCII que utiliza una página de código diferente.

Esta regla NO lo hace:

  • Compruebe el tipo de una columna calculada porque el tipo no se conoce hasta el tiempo de ejecución.

  • Analiza nada dentro de una instrucción CASE. Tampoco analiza el valor devuelto de una instrucción CASE.

  • Analiza los parámetros de entrada o el valor devuelto de una llamada a ISNULL

Objetos CLR de SQL

Para los objetos de Common Language Run-time (SQL CLR) de SQL Server, se realizan las comprobaciones siguientes:

Object (Tipo)

Comprueba la compatibilidad de tipos

Comprueba la pérdida de datos potencial

Columnas

No

Procedimiento almacenado y parámetros de función

No

No

Variables

No

No

Tipos XML

No

No

Si asigna un objeto a otro y ambos son tipos de objeto CLR de SQL, deben ser del mismo tipo o se generará una advertencia. Solo puede convertir explícitamente lo siguiente a un tipo de objeto CLR de SQL o aparecerá una advertencia: binary, varbinary, char, nchar, varchar o nvarchar.

Funciones del sistema

Se comprueba el tipo de valor devuelto para las siguientes funciones del sistema: @@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 e ISNULL.

Nota

No se realiza ninguna comprobación para asegurarse de que las entradas son válidas en el contexto de función salvo para las funciones LEFT, RIGHT, CAST y CONVERT. Por ejemplo, no aparece ninguna advertencia para SUM (tipo datetime2) porque el análisis del código de base de datos no entiende qué tipo de entrada espera la función SUM. Una advertencia aparecerá es si hay un problema con la propia expresión de entrada, por ejemplo si especificara SUM (dinero + real).

Comprobaciones concretas que se realizan

En la tabla siguiente se describen las comprobaciones concretas que se realizan, con un ejemplo de cada una:

Construcción de lenguaje

Qué se comprueba

Ejemplo

Valor predeterminado de parámetros

Tipo de datos de parámetro

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

Predicado CREATE INDEX

El predicado es booleano

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

Argumentos de las funciones LEFT o RIGHT

Tipo y longitud del argumento de cadena

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

Argumentos de las funciones CONVERT y CAST

La expresión y los tipos son válidos

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

SET (instrucción)

El lado izquierdo y el derecho tienen tipos compatibles

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

Predicado de la instrucción IF

El predicado es booleano

IF (@v > 10)

Predicado de la instrucción WHILE

El predicado es booleano

WHILE (@v > 10)

Instrucción INSERT

Los valores y columnas son correctos

INSERT INTO t1(c1, c2) VALUES (99, 'xyz')
INSERT INTO t1 SELECT c1 FROM t2.
NotaNota
No se comprueban los caracteres comodín.Por ejemplo: INSERT INTO t1 SELECT * FROM t2

SELECT WHERE (predicado)

El predicado es booleano

SELECT * FROM t1 WHERE c1 > 10

SELECT TOP (expresión)

La expresión es de un tipo Float o Integer

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

Instrucción UPDATE

La expresión y la columna tienen tipos compatibles

UPDATE t1 SET c1 = 100

Predicado UPDATE

El predicado es booleano

UPDATE t1 SET c1 = 100 
WHERE c1 > 100

Expresión UPDATE TOP

La expresión es de un tipo Float o Integer

UPDATE TOP 4 table1

PREDICADO DELETE

El predicado es booleano

DELETE t1 WHERE c1 > 10

Expresión DELETE TOP

La expresión es de un tipo Float o Integer

DELETE TOP 2 FROM t1

Declaración de la variable DECLARE

El valor inicial y el tipo de datos son compatibles

DECLARE @v INT = 10

Argumentos de la instrucción EXECUTE y tipo de valor devuelto

Parámetros y argumentos

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

RETURN (instrucción)

La expresión RETURN tiene un tipo de datos compatible

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

Condiciones de la instrucción MERGE

La condición es booleana

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

Cómo corregir infracciones

Puede evitar y resolver estos problemas asignando los tipos de datos de forma coherente y convirtiendo los tipos explícitamente donde se necesitan. Para obtener más información sobre cómo convertir explícitamente tipos de datos, vea esta página en el sitio web de Microsoft: CAST and CONVERT (Transact-SQL).

Cuándo suprimir advertencias

No debería suprimir este tipo de advertencia.

Ejemplo

En este ejemplo se muestran dos procedimientos almacenado que insertan datos en una tabla. El primer procedimiento, procWithWarning, producirá una conversión implícita de un tipo de datos. El segundo procedimiento, procFixed, muestra cómo puede agregar una conversión explícita para maximizar el rendimiento y retener todos los datos.

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

Vea también

Conceptos

Analizar el código de base de datos para mejorar la calidad del código