SR0014:从 {Type1} 强制转换为 {Type2} 时可能会丢失数据
规则 ID |
SR0014 |
类别 |
Microsoft.Design |
是否重大更改 |
非重大更改 |
原因
列、变量或参数的数据类型正隐式转换到另一个数据类型。
规则说明
如果数据类型未一致地分配到列、变量、或参数,则它们会在包含这些对象的 Transact-SQL 代码运行时被隐式转换。 这种类型的转换不仅会降低性能,而且还在某些情况下导致细微的数据丢失。 例如,如果 WHERE 子句中的每一列都必须进行转换,则表扫描可以运行。 更糟糕的是,如果 Unicode 字符串转换为使用不同代码页的 ASCII 字符串,数据可能会丢失。
此规则不会:
请检查计算所得的列的类型,因为该类型直到运行时才知道。
分析 CASE 语句内的任何内容。 它也不会分析 CASE 语句的返回值。
分析对 ISNULL 调用的输入参数或返回值
SQL CLR 对象
对于 SQL Server 公共语言运行时 (SQL CLR) 对象,应进行以下检查:
对象类型 |
验证类型兼容性 |
验证潜在数据丢失 |
---|---|---|
Columns |
是 |
否 |
存储过程和函数参数 |
否 |
否 |
变量 |
否 |
否 |
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(金钱 + 实际)的问题。
正在执行的特定检查
下表描述了执行的特定的检查,带每个检查的示例:
语言构造 |
检查内容 |
示例 |
---|---|---|
参数的默认值。 |
参数数据类型 |
|
创建索引谓词 |
谓词是布尔值 |
|
LEFT 或 RIGHT 函数的参数 |
字符串参数类型和长度 |
|
CAST 和 CONVERT 函数的参数 |
表达式和类型有效 |
|
SET 语句 |
左侧和右侧具有兼容的类型 |
|
IF 语句谓词 |
谓词是布尔值 |
|
WHILE 语句谓词 |
谓词是布尔值 |
|
INSERT 语句 |
值和列正确 |
注意
不检验通配符。例如:INSERT INTO t1 SELECT * FROM t2
|
SELECT WHERE 谓词 |
谓词是布尔值 |
|
SELECT TOP 表达式 |
表达式为整数类型或 float 类型 |
|
UPDATE 语句 |
表达式和列有兼容的类型 |
|
UPDATE 谓词 |
谓词是布尔值 |
|
UPDATE TOP 表达式 |
表达式为整数类型或 float 类型 |
|
删除谓词 |
谓词是布尔值 |
|
删除 TOP 表达式 |
表达式为整数类型或 float 类型 |
|
DECLARE 变量声明 |
初始值和数据类型是兼容的 |
|
执行声明参数和返回类型 |
形参和实参 |
|
RETURN 语句 |
RETURN 表达式有兼容的数据类型 |
|
MERGE 语句条件 |
条件为布尔值 |
|
如何解决冲突
您可以避免并解决这些问题,方法是不断指定数据类型并明确地在需要类型的地方转换它们。 有关如何指定显式转换数据类型的更多信息,请参见 Microsoft 网站的此页面:CAST and CONVERT (Transact-SQL)(CAST 和 CONVERT (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