我是一个自学成才的 SQL 用户。对于我正在写的观点,我正在尝试开发一个'条件LEFT
' 字符串分割命令(可能稍后会被 'conditional RIGHT
加入' - 借此:
- 如果一个字符串(我们称之为 'haystack')包含特定的模式(我们称之为 'needle'),它将被修剪到该模式的左侧
- 否则,整个字符串将原封不动地传递。
所以,如果我们的模式是' - ',
- 'A long string - contains the pattern'将输出为'A long string'
- “没有模式的字符串”将按原样返回。
我试图想出一种避免重复任何子句的方法,而不是使用最粗暴的方法(例如 if 0 < CHARINDEX
,然后取 CHARINDEX
- 1 等)和而是利用条件 NULL
。
然而——这就是我尝试创造的结果——我遇到了一个看似非常基本的绊脚石。请注意下面的代码和结果,让我知道你是否可以复制它 - 因此它是一个错误还是我错过了一些特殊的东西。我已经在 SQL Server 2008 R2 和 2014(两个 Express 版本)上对此进行了测试。
select
-- ISNULL: returns 'a big old string'
ISNULL(null, 'a big old string'),
-- NULLIF: returns NULL
left(
'a big old string',
nullif
(
CHARINDEX
(
'needle',
'haystack'
), 0
) - 1
),
-- combined: returns just 'a' (1st character of ISNULL condition)
ISNULL(
left
(
'a big old string', -- the input string. In reality, this would be a column alias, etc.
nullif
(
CHARINDEX -- Search for the splitting pattern
(
'needle',
'haystack'
), 0 -- If it's not found, return NULL instead of the usual 0
) - 1 -- so that this subtraction produces a NULL, not an invalid negative index
),
'a big old string' -- If the pattern was not found, we should return the input unaltered
);
/*
---------------- ---- ----
a big old string NULL a
(1 row(s) affected)
*/
为什么这 2 个子句在孤立的情况下按预期工作,但是 当我将它们组合在一起时,而不是得到它们的效果的总和,我只得到 ISNULL
的第一个字符字符串 - 'a'?
是否有某种隐含的CAST
至varchar(1)
?故意cast
转至 varchar(max)
没有任何区别。这里还能发生什么?
我只是在做一些非常愚蠢的事情吗?因为从这里,我无法弄清楚我做错了什么,所以它看起来真的像一个错误。我希望 2014 年的测试能证明它是旧 2008 R2 中的一个错误,但可惜,它们的行为相同(或者,更确切地说,不一样)。
在此先感谢您,希望能将我从可能是一个令人困惑的生存危机之夜中解救出来。
最佳答案
这是 isnull
和 coalesce
之间的区别——因为 isnull 的第一个参数是 char(1),这将是返回值的类型陈述。使用合并,您将获得正确的结果。
Isnull :
返回与 check_expression 相同的类型。如果提供文字 NULL 作为 check_expression,则返回 replacement_value 的数据类型。如果提供了一个文字 NULL 作为 check_expression 并且没有提供 replacement_value,则返回一个 int。
Coalesce :
返回具有最高数据类型优先级的表达式的数据类型。如果所有表达式都不可为空,则结果类型为不可空。
关于SQL Server : ISNULL(compound NULL condition, 'a string' ) 在某些情况下仅返回第一个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31388813/