2008-09-22 45 views
1

鉴于这样的数据:就像CASE语句时,没有评估预期

CREATE TABLE tmpTable(
fldField varchar(10) null); 

INSERT INTO tmpTable 
SELECT 'XXX' 
UNION ALL 
SELECT 'XXX' 
UNION ALL 
SELECT 'ZZZ' 
UNION ALL 
SELECT 'ZZZ' 
UNION ALL 
SELECT 'YYY' 

SELECT 
CASE WHEN fldField like 'YYY' THEN 'OTH' ELSE 'XXX' END AS newField 
FROM tmpTable 

预期的结果集是:
XXX
XXX
XXX
XXX
OTH

会casue什么情况SQL服务器2000找不到'YYY'?并返回以下的结果集:
XXX
XXX
XXX
XXX
XXX

的问题是与像“YYY”,我已经找到其他方法来写这让它开始工作,但我想知道为什么这个确切的方法不起作用。另一个困难是它在我的大多数SQL Server 2000环境中都能正常工作。我需要找出导致这种情况的不同之处。谢谢你的帮助。

回答

1

检查您的服务包。将我的SQL 2000框升级到SP4后,我现在可以为您的情况获得正确的值。

我仍然收到这个我在先前的帖子报道的交换数据虽然:(

如果你这样做SELECT @@version你应该得到8.00.2039。不足的是任何版本号,你应该安装SP4。

+0

You ar e绝对正确。我刚刚在Mocrosoft的网站http://support.microsoft.com/kb/279293/en-us上发现了关于几乎相同问题的bug修复。我证实,给我的问题的版本没有修补。 SP1修复了这个问题。 – 2008-09-23 14:55:44

-1

你没有指定你所选择和检查对CASE ...

SELECT CASE fldField WHEN 'YYY' 
THEN 'OTH' ELSE 'XXX' END AS newField FROM tmpTable 
0

如何fldField = '%YYY%'

+0

权,加上通配符使得它的工作。我试图找出为什么它不工作作为编写的。它不应该。如果'YYY'发现'YYY'的值应该是true。 – 2008-09-22 19:38:22

0

它在我的SQL 2005安装上按预期工作。如果它在其他机器上工作,这听起来像你有一个环境差异。尝试在SQL Server Management Studio中比较连接属性,以确定可用的连接,并且不会查看是否可以找出差异。

0

我是一个Oracle的人,而不是一个SQL *服务器的人,但在我看来,你应该是: -

SELECT 
    CASE WHEN fldField like '%YYY%' THEN 
      'OTH' 
     ELSE 'XXX' 
    END AS newField 
FROM 
    tmpTable 

或...

SELECT 
    CASE WHEN fldField = 'YYY' THEN 
      'OTH' 
     ELSE 'XXX' 
    END AS newField 
FROM 
    tmpTable 

二是我会介入的方向,至少在Oracle中,平等决定比类似的更快。

0

当您使用LIKE而没有指定任何搜索条件时,它的行为就像是=比较。在你的例子中,我希望它能正常工作。在你的真实数据中,你的数据可能有一个隐藏的(不可打印的)字符(想想回车,换行,制表符等等......)。

看看这个例子...

Declare @tmpTable TABLE(
fldField varchar(10) null); 

INSERT INTO @tmpTable 
SELECT 'XXX' 
UNION ALL 
SELECT 'XXX' 
UNION ALL 
SELECT 'ZZZ' 
UNION ALL 
SELECT 'ZZZ' 
UNION ALL 
SELECT 'YYY' 
UNION ALL 
SELECT 'YYY' + Char(10) 

SELECT CASE WHEN fldField like 'YYY' THEN 'OTH' ELSE 'XXX' END AS YourOriginalTest, 
     CASE WHEN fldField like 'YYY%' THEN 'OTH' ELSE 'XXX' END AS newField 
FROM @tmpTable 

你会发现,我添加数据的最后一块是YYY和换行。如果选择此数据,则不会注意到数据中的换行符,但它在那里,因此您的LIKE条件(表现为相同条件)不匹配。

常见的“隐藏”字符是制表符,回车符和换行符。要确定这是否导致您的问题...

Select * 
From Table 
Where Column Like '%[' + Char(10) + Char(9) + Char(13) + ']%' 
1

我在SQL 2000框上运行的代码,并得到相同的结果。不仅如此,但是当我跑了一些额外的代码来测试我得到了一些非常奇怪的结果:

CREATE TABLE dbo.TestLike (my_field varchar(10) null); 
GO 
CREATE CLUSTERED INDEX IDX_TestLike ON dbo.TestLike (my_field) 
GO 
INSERT INTO dbo.TestLike (my_field) VALUES ('XXX') 
INSERT INTO dbo.TestLike (my_field) VALUES ('XXX') 
INSERT INTO dbo.TestLike (my_field) VALUES ('ZZZ') 
INSERT INTO dbo.TestLike (my_field) VALUES ('ZZZ') 
INSERT INTO dbo.TestLike (my_field) VALUES ('YYY') 
GO 

SELECT 
     my_field, 
     case my_field when 'YYY' THEN 'Y' ELSE 'N' END AS C2, 
     case when my_field like 'YYY' THEN 'Y' ELSE 'N' END AS C3, 
     my_field 
FROM dbo.TestLike 
GO 

我的结果:

my_field C2 C3 my_field 
---------- ---- ---- ---------- 
N   XXX N XXX 
N   XXX N XXX 
Y   YYY N YYY 
N   ZZZ N ZZZ 
N   ZZZ N ZZZ 

通知my_field同一行中怎么有两个不同的值?我已经在这里的办公室要求其他人给它一个快速测试。对我来说看起来像一个bug。

0

多么可爱的bug。我想我知道原因。如果我是正确的,那么你会得到你所期望的结果:

SELECT 
    CASE 
    WHEN fldField like 'YYY  ' -- 7 spaces 
    THEN 'OTH' 
    ELSE 'XXX' 
    END as newField 
from tmpTable 

的错误是,VARCHAR(10)的行为就像CHAR(10)应该。至于它为什么不这样做,你需要了解两个没有元字符的字符串如何可以彼此不同的老问题。

问题是char(10)在内部被假定为空间填充。类似运算符而不是忽略这些空格。 =运算符应该用于字符的情况。内存告诉我Oracle通常忽略字符串的空间。 Postgres使用一些技巧来铸造。我没有使用SQL * Server,所以我不能告诉你它是如何做到的。

0

通过增加(%)来表达,它会正常工作。

SELECT 
CASE 
    WHEN fldField like '%YYY%' THEN 'OTH' 
    ELSE 'XXX' END AS newField 
END