0

我有一个包含 13,000 行的临时表。大多数行都有数字价格 (100),但有些行以 32 位报价,即 100-30 = 100 + 30/32 = 100.9375。(有些甚至只有 32 分之一)

我正在打开一个游标 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
4

2 回答 2

2

啊! 我在表中有一个列,与光标同名:

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

这似乎使 Sybase 服务器陷入混乱……

于 2010-09-03T12:41:17.780 回答
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
于 2010-09-02T17:47:12.970 回答