SR0014: Data loss might occur when casting from {Type1} to {Type2}
RuleId |
SR0014 |
Category |
Microsoft.Design |
Breaking Change |
Non-breaking |
Cause
The data type for a column, variable, or parameter is being converted implicitly to another data type.
Rule Description
If data types are inconsistently assigned to columns, variables, or parameters, they are implicitly converted when the Transact-SQL code that contains those objects is run. This type of conversion not only reduces performance but also, in some cases, causes subtle loss of data. For example, a table scan might run if every column in a WHERE clause must be converted. Worse, data might be lost if a Unicode string is converted to an ASCII string that uses a different code page.
This rule does NOT:
Check the type of a computed column because the type is not known until run-time.
Analyze anything inside a CASE statement. It also does not analyze the return value of a CASE statement.
Analyze the input parameters or return value of a call to ISNULL
SQL CLR Objects
For SQL Server Common Language Run-time (SQL CLR) objects, the following checks are performed:
Object Type |
Verifies Type Compatibility |
Verifies Potential Data Loss |
---|---|---|
Columns |
Yes |
No |
Stored Procedure and Function Parameters |
No |
No |
Variables |
No |
No |
XML Types |
No |
No |
When you assign one object to another and both are SQL CLR object types, they must be the same type or a warning will be generated. You can explicitly convert only the following to a SQL CLR object type or a warning appears: binary, varbinary, char, nchar, varchar, or nvarchar.
System Functions
Return type is checked for the following system functions: @@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, and ISNULL.
Note
No check is performed to ensure that the inputs are valid in the function context except for the LEFT, RIGHT, CONVERT, and CAST functions. For example, no warning appears for SUM(datetime2 type) because database code analysis does not understand what type of input is expected by the SUM function. A warning will appear is if there is an issue with the input expression itself, for example if you specified SUM(money + real).
Specific Checks that are Performed
The following table describes specific checks that are performed, with an example for each:
Language construct |
What is Checked |
Example |
---|---|---|
Default value of parameters |
Parameter data type |
|
CREATE INDEX predicate |
Predicate is Boolean |
|
Arguments of LEFT or RIGHT functions |
String argument type and length |
|
Arguments of CAST and CONVERT functions |
Expression and types are valid |
|
SET statement |
Left side and right side have compatible types |
|
IF statement predicate |
Predicate is Boolean |
|
WHILE statement predicate |
Predicate is Boolean |
|
INSERT statement |
Values and columns are correct |
Note
Wildcards are not verified. For example: INSERT INTO t1 SELECT * FROM t2
|
SELECT WHERE predicate |
Predicate is Boolean |
|
SELECT TOP expression |
Expression is an Integer or Float type |
|
UPDATE statement |
Expression and column have compatible types |
|
UPDATE predicate |
Predicate is Boolean |
|
UPDATE TOP expression |
Expression is an Integer or Float type |
|
DELETE PREDICATE |
Predicate is Boolean |
|
DELETE TOP expression |
Expression is an Integer or Float type |
|
DECLARE variable declaration |
Initial value and data type are compatible |
|
EXECUTE statement arguments and return type |
Parameters and arguments |
|
RETURN statement |
RETURN expression has a compatible data type |
|
MERGE statement conditions |
Condition is Boolean |
|
How to Fix Violations
You can avoid and resolve these issues by assigning data types consistently and by explicitly converting types where they are needed. For more information about how to explicitly convert data types, see this page on the Microsoft Web site: CAST and CONVERT (Transact-SQL).
When to Suppress Warnings
You should not suppress this kind of warning.
Example
This example shows two stored procedures that insert data into a table. The first procedure, procWithWarning, will cause an implicit conversion of a data type. The second procedure, procFixed, shows how you can add an explicit conversion to maximize performance and retain all data.
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