views:

84

answers:

2

I have a temp table with 13,000 rows. Most of the rows have a numeric price (100) but some are quoted in 32nds, i.e. 100-30 = 100 + 30/32 = 100.9375. (Some even have fractions of a 32th)

I am opening a cursor FOR UPDATE and iterating over the temp table. It takes so long to execute, I am not even sure it is working (my DBA says the exec plan looks 'strange')

Can anyone suggest why this is so ridiculously slow?

Better still, could anyone suggest a better alternative? I have control over how the temp table is created, but I don't fancy trying to compact the logic for 100-30 to 100.9375 into a single update statement.

I'd like to write a function to do this, but as far as I can tell, I have to install Java to enable UDFs?!

Lastly, any idea why Sybase is such an awful, primitive database even at version 12?

My stored proc:

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
+1  A: 

Cursors in Sybase are slower than SET based operations. Despite your reluctance I doubt you will do better than putting all the logic into one Update statement as below.

 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
Martin Smith
+1  A: 

Ah! I had a column in the table, with the same name as the cursor:

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

This seems to put the Sybase server into a tailspin...

Ryan
Ha Ha. I presume that's why the DBA said the plan looked 'strange' then!
Martin Smith