2008-10-30 60 views
2

我有以下用於轉換數據的sql查詢,但可以將int的值保存在某個變量中以避免多次轉換?如何在sql查詢中避免多個CAST?

update prospekts set sni_kod = case 

when 
    cast(sni_kod as int) >= 1000 and cast(sni_kod as int) <= 1499 
    or cast(sni_kod as int) >= 1600 and cast(sni_kod as int) <= 2439 
then '1' 
when 
    cast(sni_kod as int) >= 7000 and cast(sni_kod as int) <= 7499 
then 'W' 
else 
    sni_kod 
end 

腳本中還有很多情況,只顯示第一個。除了簡單的文本腳本之外,我無法使用其他任何東西。

更新 使用SQL Server 2000

感謝

安德斯

+0

您在評論中說sni_kod中的值可以是'Q'或'T'。因此CAST無法正常工作。它只會給你一個演員例外。 「將varchar值」Q「轉換爲數據類型int時轉換失敗。」 – 2008-10-30 12:38:17

回答

3

好吧......這是我的代碼重寫......

UPDATE prospekts SET sni_kod = 
    CASE 
     WHEN ISNUMERIC(@sni_kod)=1 THEN 
      CASE 
       WHEN cast(@sni_kod as int) BETWEEN 1000 AND 1499 OR cast(@sni_kod as int) BETWEEN 1600 AND 2439 THEN '1' 
       WHEN cast(@sni_kod as int) BETWEEN 7000 AND 7499 THEN 'W' 
       ELSE @sni_kod 
      END 
     ELSE @sni_kod 
    END 

通過這種方式,它只會嘗試做一個CAST,如果它是一個數值,這樣你就不會得到轉換異常,就像其他人在評論中提到的一樣。

既然你說有更多的陳述參與,我猜你有更多的數字範圍,得到不同的值......如果是這樣的話,你可能能夠使用第二個表(可以如果像你的問題所說的那樣,只是一種臨時的,你僅限於SQL代碼)加入其上有最小值,最大值以及基於此值顯示的內容。當需要評估非數字值時,獲得更多的技巧,但這不是不可能的。

雖然沒有看到完整的聲明,但這是我能提供的最好的。

1

,你可以使用子查詢或CTE:

With xxx AS (
    i_sni_kod = cast(sni_kod as int) 
    ...) 
UPDATE prospekts set sni_kod = case 
    when i_sni_kod >= 100 ... 
+0

我真的不明白如何使用這個功能..你能詳細說明一下嗎? – loraderon 2008-10-30 11:54:05

+0

WITH語句中的查詢就像一個視圖,稱爲CTE。這隻適用於SQL 2005/2008,順便說一句。通過將它投射到CTE中,您不再需要將它投射到別處。 – 2008-10-30 12:01:05

+0

啊,我已經更新了這個問題。我正在使用SQL Server 2000. – loraderon 2008-10-30 12:03:07

0

是否在你的DBMS這個工作呢?

update (select prospekts.*, cast(sni_kod as int) sni_kod_int from prospekts) 
set sni_kod = case 
when 
    sni_kod_int >= 1000 and sni_kod_int <= 1499 
    or sni_kod_int >= 1600 and sni_kod_int <= 2439 
then 1 
else 
    sni_kod 
end 
+0

不,這不起作用。我正在使用SQL Server 2000 – loraderon 2008-10-30 11:53:23

+0

在UPDATE語句中執行CAST會更改正在保存的數據類型。如果sni_kod應該是數據庫中的文本,而不是整數? – DOK 2008-10-30 12:18:23

+0

DOK:這是正確的,它應該是文本 – loraderon 2008-10-30 12:25:00

0

這看起來像是你的模型的問題,而不是你的查詢。爲什麼該列不是簡單的int?

這似乎是一個shoe or glass bottle問題。您看到的多重投射問題只是早期不良做法的結果。修復這些問題,你的問題就會消失。

0

事情是這樣的威力作品:

update prospekts set sni_kod = 1 
from prospekts 
    join (select prospekts.primarykey, cast(prospekts.sni_kod as int) as sni_kod_int from prospekts) p2 on prospekts.primarykey = p2.primarykey 
WHERE (p2.sni_kod_int >=1000 and p2.sni_kod_int <= 1499) 
    or (p2.sni_kod_int >=1600 and p2.sni_kod_int <= 2439) 
0

的,你告訴UPDATE語句;我認爲它只會運行一次?如果它再次運行,那麼當它發現在上一次運行中添加的'W'時,轉換爲int將失敗。 這裏最好的選擇是更改sni_kod列的數據類型。也許你可以解釋一下這個列保存着什麼,爲什麼它需要保存int和varchar數據? 最後,SQL服務器幾乎肯定只做一次演員。它非常擅長在查詢中查找重複的表達式和子查詢,並且只運行一次。如果您不確定,請查看執行計劃。

2

這只是一次性腳本,因爲它顯示?如果是這樣,你只是想節省打字然後寫爲:

update prospekts set sni_kod = case 
when 
    xxx >= 1000 and xxx <= 1499 
    or xxx >= 1600 and xxx <= 2439 
then '1' 
when 
    xxx >= 7000 and xxx <= 7499 
then 'W' 
else 
    sni_kod 
end 

...然後做一個全局搜索並用文本編輯器進行更換。

或者您可能曾經擔心過每次鑄造多次的性能?但是,如果這個腳本是一次性的,它真的很重要嗎?

2

在你的問題中,你提到你想「避免多次投射」。如果您擔心性能問題,那麼不要這樣做。 SQL不會多次轉換該字段(即使您不止一次在腳本中包含該字段)。

實施例:

SELECT CONVERT(INT, '123'), CONVERT(INT, '123') 

T-SQL只會一次運行方法(無性能損失)。

有了這個說法,那麼你唯一的擔心就是打字一堆......如果是這樣的話,Tony Andrews提到的「xxx/find and replace」評論就足夠了。

0

我看到有人發佈了一個解決方案,它在from子句中加入了一個子查詢。這裏有一個解決方案,在from子句中使用-just-子查詢。

DECLARE @MyTable TABLE 
(
    theKey int identity(1,1) PRIMARY KEY, 
    theValue varchar(30) 
) 
------  
INSERT INTO @MyTable SELECT '1' 
INSERT INTO @MyTable SELECT '2' 
INSERT INTO @MyTable SELECT '3' 
------ 

UPDATE sub 
SET theValue = 
    CASE 
    WHEN convertedvalue % 2 = 0 THEN 'even' 
    ELSE theValue 
    END 
FROM 
(
    SELECT 
    CASE 
     WHEN Isnumeric(theValue) = 1 
     THEN convert(int, theValue) 
     ELSE null 
    END as convertedValue, * 
    FROM @MyTable mt 
) as sub 
------ 
SELECT * 
FROM @MyTable