2010-09-02 78 views
0

我有一個臨時表,有13,000行。大多數行具有數字價格(100),但是一些以32數引用,即100-30 = 100 + 30/32 = 100.9375。 (有些甚至有小數32)Sybase CURSOR UPDATE extremeley慢/鎖定

我打開遊標FOR UPDATE並遍歷臨時表。執行需要很長時間,我甚至不確定它是否工作(我的DBA說執行計劃看起來很奇怪)

任何人都可以提出爲什麼這是如此荒謬的慢?

更好的是,任何人都可以提出一個更好的選擇?我可以控制如何創建臨時表,但我不喜歡試圖將100-30至100.9375的邏輯壓縮爲單個更新語句。

我想寫一個函數來做到這一點,但據我所知,我必須安裝Java來啓用UDF ?!

最後,任何想到爲什麼Sybase是甚至在版本12都是這樣一個可怕的原始數據庫?

我的存儲過程:

DECLARE cur CURSOR FOR SELECT ticket_no, price_st, price, cur FROM #t FOR UPDATE OF price 
DECLARE 
    @ticket_no INT, 
    @price_st VARCHAR(20), 
    @price FLOAT, 
    @int FLOAT, 
    @32s FLOAT, 
    @frac VARCHAR(6), 
    @num FLOAT, 
    @denom FLOAT 

    OPEN cur 
    FETCH cur INTO @ticket_no, @price_st 

    WHILE (@@SQLSTATUS != 2) 
    BEGIN 

     IF isnumeric(@price_st) = 1 
      BEGIN 
       SELECT @price = convert(FLOAT, @price_st) 
      END 
     ELSE 
      BEGIN 
       -- Convert a price like '99-22 3/4' to 
       -- 99 + (22/32) + (3/4 * 1/32) 
       SELECT @int = convert(FLOAT, substring(@price_st, 1, charindex('-', @price_st)-1)) 
       SELECT @32s = convert(FLOAT, substring(@price_st, charindex('-', @price_st)+1, 2)) 
       SELECT @frac = substring(@price_st, charindex(' ', @price_st)+1, 10) 
       SELECT @num = convert(FLOAT, substring(@frac, 1, charindex('/', @frac)-1)) 
       SELECT @denom = convert(FLOAT, substring(@frac, charindex('/', @frac)+1, 3)) 
       SELECT @price = @int + (@32s/32) + (@num/(@denom * 32)) 

      END 


     UPDATE #t SET price = @price WHERE CURRENT OF cur 

     FETCH cur INTO @ticket_no, @price_st 

    END 

    CLOSE cur 
    DEALLOCATE cur 

回答

2

啊!我曾在表中的列,具有相同名稱的光標:

DECLARE cur CURSOR FOR SELECT ticket_no, price_st, price, cur FROM #t FOR UPDATE OF price 
     ^            ^

這似乎把Sybase服務器陷入一片混亂......

+0

哈哈。我想這就是爲什麼DBA說這個計劃看起來很奇怪的原因! – 2010-09-03 12:44:53

1

光標在Sybase比基於SET運算慢。儘管你不願意,但我懷疑你會把所有的邏輯放在一個Update聲明如下。

UPDATE #t 
SET price = 
     CASE 
       WHEN isnumeric(price_st) = 1 
       THEN CONVERT(FLOAT, price_st) 
       ELSE 
        CONVERT(FLOAT, substring(price_st, 1, charindex('-', price_st)-1)) + 
        (CONVERT(FLOAT, substring(price_st, charindex('-', price_st)+1, 2))/32) + 
        (CONVERT(FLOAT, substring(substring(price_st, charindex(' ', price_st)+1, 10), 1, charindex('/', substring(price_st, charindex(' ', price_st)+1, 10))-1))/
        (CONVERT(FLOAT, substring(substring(price_st, charindex(' ', price_st)+1, 10), charindex('/', substring(price_st, charindex(' ', price_st)+1, 10))+1, 3)) * 32)) 
     END