SR0014:從 {Type1} 轉型為 {Type2} 時可能會發生資料遺失

RuleId

SR0014

分類

Microsoft.Design

中斷變更

中斷

原因

將資料行、變數或參數的資料型別隱含地轉換成另一個資料型別。

規則描述

如果將資料型別不一致地指派給資料行、變數或參數,當包含這些物件的 Transact-SQL 程式碼執行時,就會隱含地轉換這些物件。 這種類型的轉換不僅會降低效能,在某些情況下還會導致遺漏部分資料。 例如,如果必須轉換 WHERE 子句中的每一個資料行,可能會執行資料表掃描。 更糟的是,如果將 Unicode 字串轉換成使用不同字碼頁的 ASCII 字串,資料可能會遺失。

此規則不會:

  • 檢查計算資料行的型別,因為型別須等到執行階段才知道。

  • 分析 CASE 陳述式內的任何項目。 它也不會分析 CASE 陳述式的傳回值。

  • 分析 ISNULL 呼叫的輸入參數或傳回值

SQL CLR 物件

若為 SQL Server Common Language Run-time (SQL CLR) 物件,會執行下列檢查:

Object 型別

驗證型別相容性

確認潛在的資料遺漏

資料行

預存程序和函式參數

變數

XML 型別

當您將物件指派給另一個物件,且兩者都是 SQL CLR 物件型別時,它們必須是相同的型別,否則會產生警告。 您只能明確地將下列項目轉換為 SQL CLR 物件型別,否則會出現警告:binary varbinary、 char、 nchar、 varchar或 nvarchar。

系統函式

針對下列系統函式檢查傳回型別:@@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 和 ISNULL。

注意事項注意事項

不會執行任何檢查,以確保輸入在 LEFT、 RIGHT、 CONVERT,和 CAST 函式以外的函式內容是有效的。 例如,沒有出現 SUM(datetime2 類型) 的警告,因為資料庫程式碼分析不了解 SUM 函式所預期的輸入類型。 如果輸入運算式本身有問題,會出現警告,例如如果您指定了 SUM (money + real)。

指定所執行的檢查

下表描述所執行的特定檢查,並且各附一個範例:

語言建構

檢查項目

範例

參數的預設值

參數資料型別

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

CREATE INDEX 述詞

述詞是布林

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

LEFT 或 RIGHT 函式的引數

字串引數型別和長度

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

CAST 與 CONVERT 函式的引數

運算式和型別都有效

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

SET 陳述式

左側和右側有相容的型別

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

IF 陳述式述詞

述詞是布林

IF (@v > 10)

WHILE 陳述式的述詞

述詞是布林

WHILE (@v > 10)

INSERT 陳述式

值和資料行正確

INSERT INTO t1(c1, c2) VALUES (99, 'xyz')
INSERT INTO t1 SELECT c1 FROM t2.
注意事項注意事項
不會驗證萬用字元。例如:INSERT INTO t1 SELECT * FROM t2

SELECT WHERE 述詞

述詞是布林

SELECT * FROM t1 WHERE c1 > 10

SELECT TOP 運算式

運算式是整數或浮點數型別

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

UPDATE 陳述式

運算式和資料行具有相容的型別

UPDATE t1 SET c1 = 100

UPDATE 述詞

述詞是布林

UPDATE t1 SET c1 = 100 
WHERE c1 > 100

UPDATE TOP 運算式

運算式是整數或浮點數型別

UPDATE TOP 4 table1

DELETE PREDICATE

述詞是布林

DELETE t1 WHERE c1 > 10

DELETE TOP 運算式

運算式是整數或浮點數型別

DELETE TOP 2 FROM t1

DECLARE 變數宣告

初始的值和資料型別可相容

DECLARE @v INT = 10

EXECUTE 陳述式引數和傳回型別

參數和引數

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

RETURN 陳述式

RETURN 運算式具有相容的資料型別

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

MERGE 陳述式條件

條件是布林

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

如何修正違規

您可以指派一致的資料型別,並且視需要明確地轉換型別,以避免及解決這些問題。 如需如何明確轉換資料型別的詳細資訊,請參閱 Microsoft 網站:轉型與轉換 (Transact-SQL) (英文)。

隱藏警告的時機

您不應該隱藏這類警告。

範例

這個範例會顯示兩個將資料插入資料表中的預存程序。 第一個程序 (procWithWarning) 會造成資料型別的隱含轉換。 第二個程序 (procFixed) 示範如何加入明確的轉換以達到最佳效能,同時保留所有資料。

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

請參閱

概念

分析資料庫程式碼以改善程式碼品質