簡體   English   中英

就像在CASE語句中一樣,未按預期評估

[英]Like in CASE statement not evaluating as expected

給定此數據:

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

什么情況會導致SQL Server 2000找不到“ YYY”? 並返回以下內容作為結果集:
XXX
XXX
XXX
XXX
XXX

問題出在“ YYY”之類,我發現了其他編寫方法來使其工作,但我想知道為什么這種精確方法不起作用。 另一個困難是,它在我的大多數SQL Server 2000環境中都有效。 我需要找出它們之間的不同之處。 謝謝你的幫助。

我在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在同一行中有兩個不同的值嗎? 我已經在這里的辦公室請其他人進行快速測試。 對我來說似乎是個蟲子。

檢查您的服務包。 將我的SQL 2000 box升級到SP4之后,我現在可以根據您的情況獲得正確的值。

我仍然得到我在較早的文章中報告的交換數據:(

如果執行SELECT @@version ,則應該獲得8.00.2039。 任何小於該版本的版本號,都應安裝SP4。

fldField = '%YYY%'怎么樣?

它在我的SQL 2005安裝中按預期工作。 如果它可以在其他計算機上運行,​​則聽起來環境有所不同。 嘗試在SQL Server Management Studio中比較您的連接屬性,以了解一個有效的連接和一個無效的連接,以查看是否可以找出區別。

我是一個Oracle人員,而不是一個SQL * Server人員,但是在我看來,您應該是:

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平等中,解決起來要快得多。

當您使用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) + ']%'

真是個可愛的錯誤。 我想我知道原因。 如果我是對的,那么您將獲得以下期望的結果:

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

錯誤在於varchar(10)的行為類似於char(10)的行為。 至於為什么不這樣,您將需要了解一個古老的瑣事問題:兩個沒有元字符的字符串如何可以= =但又不能彼此相似。

問題是char(10)在內部應該用空格填充。 類似操作並不理會那些空間。 對於char,應該使用=運算符。 內存告訴我,Oracle通常會忽略字符串的空格。 Postgres在轉換方面有一些技巧。 我沒有使用過SQL * Server,所以無法告訴您它是如何做到的。

通過將(%)添加到表達式中,它將可以正常工作。

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

您沒有指定要選擇的內容,而是針對CASE進行檢查...

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM