在 SQL Server 中将空字符串转换为 INT
Posted
技术标签:
【中文标题】在 SQL Server 中将空字符串转换为 INT【英文标题】:CAST/CONVERT empty string to INT in SQL Server 【发布时间】:2016-05-27 08:21:33 【问题描述】:我遇到了一个错误,我使用 CAST(Col1 AS INT) + CAST(Col2 AS INT)
,其中 Col1 和 Col2 都是 VARCHAR
,当 Col1 或 Col2 为空白时,我得到了有效的结果,我没想到会出现这种情况。我检查并 CAST(和 CONVERT)都具有将空白替换为 0 的默认行为:
SELECT CAST('' AS INT)
SELECT CONVERT(INT, '')
我检查了info page,但看不到任何参考资料来解释为什么会出现这种行为(或通过服务器设置进行更改)。我当然可以解决这个问题,但我想问为什么这是这种行为,因为我认为它不直观。
我实际上宁愿这个CAST
失败或给NULL
,是否有某个服务器设置会影响这个?
【问题讨论】:
这不是错误,它就是这样设计的。 这是基础数学。integer
不能是空白,但在 SQL DB 中它可以是 NULL
。
'' to 0, NULL to NULL and 'invalid number' to error
我并没有试图说明 SQL 中的这种行为是一个错误,它是我们产品中的一个错误导致我发现了这种行为,我质疑我是否可以改变它,因为我认为这不是直觉行为
【参考方案1】:
考虑 SQL Server 中的 INT
。它可以是以下三个值之一:
因此,如果您要转换/转换一个空字符串,假设它是一个数字,那么 0 是最合乎逻辑的值。它允许区分 NULL 和 0。
SELECT CAST(NULL AS INT) -- NULL
SELECT CAST('' AS INT) -- 0
SELECT CAST('42' AS INT) -- 42
我会说这是合乎逻辑的。
如果你这样做了:
SELECT CAST('abc' AS INT)
你会得到:
将 varchar 值 'abc' 转换为数据类型 int 时转换失败。
如果您确实希望将空字符串处理为NULL
,请使用NULLIF 作为Bogdan suggests in his answer:
DECLARE @val VARCHAR(2) = ''
SELECT CAST(NULLIF(@val,'') AS INT) -- produces NULL
NULLIF 如果两个表达式不相等,则返回第一个表达式。如果表达式相等,NULLIF 返回第一个表达式类型的空值。
最后,如果您的列存储INT
值,那么请考虑将其数据类型更改为INT
。
【讨论】:
对不起,我不同意。 0 是一个有效数字,所以我不明白为什么应该将其视为特殊情况,我认为 INT 要么是 NULL 要么是整数。我认为强制转换失败并使用空白字符串会更直观,因为空白字符串既不是 NULL 也不是有效数字。如果这是逻辑行为,那么为什么使用 DECIMAL 数据类型的相同操作会产生错误而不是 0? 更有趣:SELECT CAST('true' AS [bit]) -- 1 SELECT CAST('false' AS [bit]) -- 0 SELECT CAST('' AS [bit]) -- 0【参考方案2】:假设您在将空字符串 转换 为 INT 时获得 NULL 的内容,那么我将使用以下解决方案之一:
DECLARE @SourceString VARCHAR(50) = ''
SELECT CONVERT(INT, NULLIF(@SourceString, '')) AS Solution1
SELECT TRY_PARSE(@SourceString AS INT) AS Solution2
【讨论】:
【参考方案3】:您可能知道NULL
是一个指示数据值不存在的标记。而''
是一个值,空但值。
所以默认情况下,MS SQL 将空值转换(或转换)为0
。要克服这个问题并将其显示为NULL
,您可以使用NULLIF
简单示例:
SELECT int_as_varchars as actual,
cast(NULLIF(int_as_varchars,'') as int) as with_nullif,
cast(int_as_varchars as int) as just_cast
FROM (VALUES
('1'),
(''),
(NULL),
('0')
) as t(int_as_varchars)
输出:
actual with_nullif just_cast
1 1 1
NULL 0
NULL NULL NULL
0 0 0
正如您在这种情况下看到的 NULLIF 将帮助您获得 NULL
而不是 0
。
【讨论】:
【参考方案4】:这个呢?
declare @t table(bucket bigint);
INSERT INTO @t VALUES (1);
INSERT INTO @t VALUES (2);
INSERT INTO @t VALUES (-1);
INSERT INTO @t VALUES (5);
INSERT INTO @t VALUES (0);
declare @Bucket bigint = 0 --filter by 0
select * from @t
where 1=1
AND ((@Bucket is Null or cast(@Bucket as nvarchar) = '') or bucket=@Bucket)
【讨论】:
以上是关于在 SQL Server 中将空字符串转换为 INT的主要内容,如果未能解决你的问题,请参考以下文章