SR0014: Bei der Umwandlung von {Type1} in {Type2} kann es zu einem Datenverlust kommen

Regel-ID

SR0014

Kategorie

Microsoft.Design

Unterbrechende Änderung

Nicht unterbrechend

Ursache

Der Datentyp für eine Spalte, Variable oder einen Parameter wird implizit in einen anderen Datentyp konvertiert.

Regelbeschreibung

Wenn Spalten, Variablen oder Parametern Datentypen inkonsequent zugewiesen werden, werden sie implizit konvertiert, sobald der Transact-SQL-Code, der diese Objekte enthält, ausgeführt wird. Dieser Typ der Konvertierung verringert nicht nur die Leistung, sondern sorgt in einigen Fällen auch für leichten Datenverlust. Beispiel: Ein Tabellenscan kann ausgeführt werden, wenn jede Spalte in einer WHERE-Klausel konvertiert werden muss. Schwer wiegender ist, dass Daten verloren gehen können, wenn eine Unicode-Zeichenfolge in eine ASCII-Zeichenfolge konvertiert wird, die eine andere Codepage verwendet.

Folgende Vorgänge werden von dieser Regel NICHT ausgeführt:

  • Überprüfen Sie den Typ einer berechneten Spalte, da der Typ nicht bis zur Laufzeit bekannt ist.

  • Beliebiges in einer CASE-Anweisung analysieren. Es analysiert auch nicht den Rückgabewert einer CASE-Anweisung.

  • Analysieren der Eingabeparameter oder des Rückgabewerts eines Aufrufs von ISNULL

SQL-CLR-Objekte

Für SQL Server-Common Language Runtime (SQL CLR)-Objekte, werden die folgenden Überprüfungen ausgeführt:

Object-Datentyp

Überprüft Typkompatibilität.

Überprüft potenziellen Datenverlust.

Columns

Yes

nein

Gespeicherte Prozedur- und Funktionsparameter

nein

nein

Variablen

nein

nein

XML-Typen

nein

nein

Wenn Sie einem anderen Objekt ein Objekt zuweisen, und wenn beide Objekte SQL-CLR-Objekttypen sind, müssen sie dem gleichen Typ angehören, da andernfalls eine Warnung generiert wird. Sie können nur die folgenden Elemente explizit in einen SQL CLR-Objekttyp konvertieren, oder eine Warnung wird angezeigt: binary, varbinary, char, nchar, varchar oder nvarchar.

Systemfunktionen

Rückgabetyp wird auf die folgenden Systemfunktionen überprüft: @@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 und ISNULL.

Tipp

Keine Überprüfung wird ausgeführt, um sicherzustellen, dass die Eingaben im Funktionskontext außer den LEFT-, RIGHT-, CONVERT- und CAST-Funktionen gültig sind. Keine Warnung wird z. B. für SUM(datetime2-Typ) angezeigt, da die Datenbankcodeanalyse nicht versteht, welche Eingabe von der SUM-Funktion erwartet wird. Eine Warnung wird angezeigt, wenn es ein Problem mit dem Eingabeausdruck selbst gibt, z. B. wenn SUM(money + real) angegeben wurde.

Bestimmte Überprüfungen, die ausgeführt werden

In der folgenden Tabelle werden bestimmte Überprüfungen mit jeweils einem Beispiel beschrieben:

Sprachkonstrukt

Überprüft wird Folgendes:

Beispiel

Der Standardwert der Parameter

Parameterdatentyp

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

CREATE INDEX-Prädikat

Prädikat ist boolesch

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

Argumente von LEFT- oder RIGHT-Funktionen

Zeichenfolgenargumenttyp und -länge

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

Argumente von CAST- und CONVERT-Funktionen

Ausdruck und Typen sind gültig

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

SET-Anweisung

Linke und rechte Seite haben kompatible Typen

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

IF-Anweisungsprädikat

Prädikat ist boolesch

IF (@v > 10)

WHILE-Anweisungsprädikat

Prädikat ist boolesch

WHILE (@v > 10)

INSERT-Anweisung

Werte und Spalten sind korrekt.

INSERT INTO t1(c1, c2) VALUES (99, 'xyz')
INSERT INTO t1 SELECT c1 FROM t2.
HinweisHinweis
Platzhalter werden nicht überprüft.Zum Beispiel: INSERT INTO t1 SELECT * FROM t2

SELECT WHERE-Prädikat

Prädikat ist boolesch

SELECT * FROM t1 WHERE c1 > 10

SELECT TOP-Ausdruck

Ausdruck ist eine ganze Zahl oder ein Gleitkommatyp

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

UPDATE-Anweisung

Ausdruck und Spalte haben kompatible Typen

UPDATE t1 SET c1 = 100

UPDATE-Prädikat

Prädikat ist boolesch

UPDATE t1 SET c1 = 100 
WHERE c1 > 100

UPDATE TOP-Ausdruck

Ausdruck ist eine ganze Zahl oder ein Gleitkommatyp

UPDATE TOP 4 table1

DELETE-PRÄDIKAT

Prädikat ist boolesch

DELETE t1 WHERE c1 > 10

DELETE TOP-Ausdruck

Ausdruck ist eine ganze Zahl oder ein Gleitkommatyp

DELETE TOP 2 FROM t1

DECLARE-Variablendeklaration

Anfangswert und Datentyp sind kompatibel

DECLARE @v INT = 10

EXECUTE-Anweisungsargumente und -Rückgabetyp

Parameter und Argumente

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

RETURN-Anweisung

RETURN-Ausdruck hat einen kompatiblen Datentyp

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

MERGE-Anweisungsbedingungen

Bedingung ist boolesch

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

Behandeln von Verstößen

Sie können diese Probleme vermeiden und beheben, indem Sie Datentypen konsistent zuweisen und Typen explizit dort konvertieren, wo sie benötigt werden. Weitere Informationen zum expliziten Konvertieren von Datentypen finden Sie auf der Microsoft-Website unter CAST and CONVERT (Transact-SQL).

Wann sollten Warnungen unterdrückt werden?

Diese Art von Warnung sollte nicht unterdrückt werden.

Beispiel

In diesem Beispiel werden zwei gespeicherte Prozeduren gezeigt, in denen Daten in eine Tabelle eingefügt werden. Die erste Prozedur, "procWithWarning", verursacht eine implizite Konvertierung von einem Datentyp. Die zweite Prozedur, procFixed, zeigt, wie Sie eine explizite Konvertierung hinzufügen können, um die Leistung zu maximieren und alle Daten beizubehalten.

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

Siehe auch

Konzepte

Analysieren von Datenbankcode zum Verbessern der Codequalität