【发布时间】:2015-07-13 16:37:56
【问题描述】:
我是一个自学成才的 SQL 用户。对于我正在写的一个观点,我正在尝试开发一个“有条件的LEFT”字符串分割命令(大概稍后会加入一个“有条件的RIGHT” - 借此:
- 如果一个字符串(我们称之为 'haystack')包含一个特定的模式(我们称之为 'needle'),它将被修剪到该模式的左侧
- 否则,整个字符串将原封不动地传递。
所以,如果我们的模式是' - ',
- “长字符串 - 包含模式”将输出为“长字符串”
- “没有模式的字符串”将按原样返回。
而不是使用最粗暴的方法来做到这一点,我试图想出一种避免重复任何子句的方法(例如如果0 < CHARINDEX,然后取CHARINDEX - 1 等)和而是利用条件NULLing。
然而——这就是我尝试创造的结果——我遇到了一个看似非常基本的绊脚石。请注意下面的代码和结果,让我知道你是否可以复制它 - 因此它是一个错误还是我错过了一些特殊的东西。我已经在 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 字符串的第一个字符 - '一个'?
是否有某种隐含的CAST 到varchar(1)?故意casting 到varchar(max) 没有区别。这里还能发生什么?
我只是在做一些非常愚蠢的事情吗?因为从这里,我无法弄清楚我做错了什么,所以它看起来真的像一个错误。我希望 2014 年的测试能证明它是旧 2008 R2 中的一个错误,但可惜,它们的行为相同(或者说不一样)。
在此先感谢您,希望能将我从可能是一个困惑的生存危机之夜中解救出来。
【问题讨论】:
-
不确定“为什么不将这两个子句组合在一起时为什么会起作用”这个问题的答案:
SELECT SUBSTRING(@stringToSearch, 0, ISNULL(NULLIF(CHARINDEX(@searchString, @stringToSearch), 0), LEN(@stringToSearch) + 1))
标签: sql sql-server string isnull nullif