在 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 不是 0

因此,如果您要转换/转换一个空字符串,假设它是一个数字,那么 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的主要内容,如果未能解决你的问题,请参考以下文章

Sql Server 中将由逗号“,”分割的一个字符串转换为一个表集,并应用到 in 条件中

在 SQL Server 中将字符串转换为日期

如何在 SQL Server 中将字符串转换为日期时间?

在函数 SQL Server 中将字符串转换为日期时间

在 MS SQL Server 中将字符串转换为日期时间

SQL Server:在 case 语句中将 UniqueIdentifier 转换为字符串