2010-09-02 5 views
0

J'ai une table temporaire avec 13 000 lignes. La plupart des lignes ont un prix numérique (100) mais certaines sont indiquées en 32, c'est-à-dire 100-30 = 100 + 30/32 = 100,9375. (Certains ont même des fractions de 32e)Sybase CURSOR UPDATE extrêmement lent/verrouillage

J'ouvre un curseur POUR UPDATE et itérer sur la table temporaire. Cela prend tellement de temps à s'exécuter, je ne suis même pas sûr que ça fonctionne (mon DBA dit que le plan exec a l'air 'étrange')

Quelqu'un peut-il suggérer pourquoi c'est si ridiculement lent?

Mieux encore, quelqu'un pourrait-il suggérer une meilleure alternative? J'ai le contrôle sur la façon dont la table temporaire est créée, mais je ne cherche pas à compacter la logique pour 100-30 à 100.9375 dans une seule instruction de mise à jour.

Je voudrais écrire une fonction pour ce faire, mais pour autant que je sache, je dois installer Java pour activer les fonctions UDF ?!

Enfin, aucune idée de la raison pour laquelle Sybase est une base de données aussi horrible et primitive, même à la version 12?

Mon proc stocké:

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 

Répondre

2

Ah! J'ai eu une colonne dans la table, avec le même nom que le curseur:

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

Cela semble mettre le serveur Sybase en chute libre ...

+0

Ha Ha. Je présume que c'est pourquoi le DBA a dit que le plan avait l'air «étrange» alors! –

1

dans Sybase Curseurs sont plus lents que les opérations à base de SET. Malgré votre réticence, je doute que vous fassiez mieux que de mettre toute la logique dans une déclaration Update comme ci-dessous.

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