SR0014: Potrebbe verificarsi una perdita di dati durante l'esecuzione del cast da {Tipo1} a {Tipo2}.

RuleId

SR0014

Category

Microsoft.Design

Breaking Change

Non sostanziale

Causa

Il tipo di dati per una colonna, variabile o parametro viene convertito in modo implicito in un altro tipo di dati.

Descrizione della regola

Se ai tipi di dati vengono assegnati in modo incoerente alle colonne, variabili o parametri, vengono implicitamente convertiti quando il codice Transact-SQL che contiene quegli oggetti viene eseguito. Questo tipo di conversione non solo riduce la prestazione ma, in alcuni casi, causa anche una perdita minima di dati. Ad esempio, un'analisi della tabella potrebbe essere in esecuzione se è necessario convertire ogni colonna in una clausola WHERE. Peggio, i dati potrebbero essere persi se una stringa Unicode viene convertita in una stringa ASCII che utilizza una tabella di codici diversa.

Questa regola fa NOT:

  • Controllare il tipo di una colonna calcolata perché il tipo non è conosciuto fino alla fase di esecuzione.

  • Analizzare qualsiasi cosa in un'istruzione CASE. Non analizza inoltre il valore restituito di un'istruzione CASE.

  • Analizzare i parametri di input o il valore restituito di una chiamata a ISNULL

Oggetti CLR SQL

Per gli oggetti Common Language Run-time (SQL CLR) SQL Server, vengono eseguiti i seguenti controlli:

Tipo Object

Verifica compatibilità dei tipi

Verifica potenziale perdita di dati

Colonne

Sì

No

Parametri di funzioni e procedure archiviate

No

No

Variabili.

No

No

Tipi XML

No

No

Quando si assegna un oggetto a un altro ed entrambi sono tipi di oggetti CLR SQL, devono essere dello stesso tipo o un avviso sarà generato. È possibile convertire in modo esplicito solo il seguente a un tipo di oggetto CLR SQL o viene visualizzato un avviso: binary, varbinary, char, nchar, varchar o nvarchar.

Funzioni di sistema

Il tipo restituito viene verificato per le seguenti funzioni di 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

Nessun controllo viene eseguito per assicurarsi che gli input sono validi nel contesto della funzione ad eccezione di LEFT, RIGHT, CONVERTe delle funzioni CAST. Ad esempio, non viene visualizzato alcun avviso per SUM(tipo datetime2) in quanto l'analisi del codice del database non comprende che tipo di input è previsto dalla funzione SUM. Sarà visualizzato un avviso è se c'è un problema con l'espressione di input stessa, ad esempio se è stato specificato SUM(money + real).

Controlli specifici che vengono eseguiti

Nella tabella seguente vengono descritti gli specifici controlli, con un esempio per ognuno:

Costrutto di linguaggio

Ciò che viene controllato

Esempio

Valore predefinito dei parametri

Tipo di dati dei parametri

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

Predicato CREATE INDEX

Il predicato è Boolean

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

Argomenti di funzioni LEFT o RIGHT

Lunghezza e tipo di argomento di tipo stringa

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

Argomenti di funzioni CAST e CONVERT

Espressione e tipi sono validi

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

Istruzione SET

Lato sinistro e lato destro dispongono di tipi compatibili

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

Predicato istruzione IF

Il predicato è Boolean

IF (@v > 10)

Predicato istruzione WHILE

Il predicato è Boolean

WHILE (@v > 10)

Istruzione INSERT

Valori e colonne sono corretti

INSERT INTO t1(c1, c2) VALUES (99, 'xyz')
INSERT INTO t1 SELECT c1 FROM t2.
NotaNota
I caratteri jolly non vengono verificati.Ad esempio: INSERT INTO t1 SELECT * FROM t2

Predicato SELECT WHERE

Il predicato è Boolean

SELECT * FROM t1 WHERE c1 > 10

Espressione SELECT TOP

L'espressione è un Integer o un tipo float

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

Istruzione UPDATE

Espressione e colonna dispongono di tipi compatibili

UPDATE t1 SET c1 = 100

Predicato UPDATE

Il predicato è Boolean

UPDATE t1 SET c1 = 100 
WHERE c1 > 100

Espressione UPDATE TOP

L'espressione è un Integer o un tipo float

UPDATE TOP 4 table1

DELETE PREDICATE

Il predicato è Boolean

DELETE t1 WHERE c1 > 10

Espressione DELETE TOP

L'espressione è un Integer o un tipo float

DELETE TOP 2 FROM t1

Dichiarazione variabile DECLARE.

Valore iniziale e tipo di dati sono compatibili

DECLARE @v INT = 10

Tipi restituiti e argomenti dell'istruzione EXECUTE

Parametri e argomenti

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

Istruzione RETURN

L'espressione RETURN dispone di un tipo di dati compatibile

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

L'istruzione MERGE condiziona

La condizione è Boolean.

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

Come correggere le violazioni

È possibile evitare e risolvere questi problemi assegnando costantemente tipi di dati e convertendo in modo esplicito tipi dove sono necessari. Per ulteriori informazioni su come convertire esplicitamente i tipi di dati, vedere la pagina sul sito Web Microsoft CAST e CONVERT (Transact-SQL).

Esclusione di avvisi

Non escludere questo tipo di avviso.

Esempio

In questo esempio vengono mostrate due stored procedure che inseriscono dati in una tabella. La prima routine, procWithWarning, causerà una conversione implicita di un tipo di dati. La seconda procedura, procFixed, mostra come è possibile aggiungere una conversione esplicita per ottimizzare le prestazioni e mantenere tutti i dati.

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

Vedere anche

Concetti

Analisi del codice di database per migliorare la qualità del codice