Cursori

di il
9 risposte

Cursori

Ciao,
vi scrivo per sottoporvi una questione di codice/ottimizzazione.
i cursori non brillano per performance. ok.
tuttavia quello che mi è ancora oscuro è come ovviare all'uso dei cursori.
se io ho una tabella e per ogni record di quella tabella devo lanciare, che so, una funzione, e farci dei calcoli sopra, come riesco a farlo senza usare i cursori?

se serve posso fare un esempio.

Grazie mille!
V.

9 Risposte

  • Re: Cursori

    Ciao, i cursori seppur ancora supportati sono da evitare...
    Puoi usare invece le tabelle temporanee e con dei cicli while iterare per i records che ti interessano.
  • Re: Cursori

    Grazie toki per la risposta!
    perdonami, devo "incalzarti" perchè mi è poco chiaro come iterare su una tabella senza usare cicli (e soprattutto quando la chiave non è un intero).

    se posso andrei a copiare ed incollare un esempio.

    questo è l'esempio usando i cursori:

    DECLARE report_crs_grn CURSOR LOCAL STATIC FOR
    select grn_line.grn_num, grn_line.grn_line, qty_rec
    from proj
    inner join projmatl on projmatl.proj_num = proj.proj_num
    inner join grn_line on grn_line.po_num = projmatl.ref_num and grn_line.po_line = projmatl.ref_line_suf
    where proj.Uf_ProjClass BETWEEN @pProjClassStarting AND @pProjClassStarting
    and projmatl.ref_type = 'P'
    and grn_line.qty_rec > 0

    OPEN report_crs_grn

    WHILE 1 = 1
    BEGIN
    FETCH report_crs_grn INTO
    @GrnNum,
    @GrnLine,
    @QtyRec

    IF @@FETCH_STATUS = -1 BREAK

    if not exists(select 1 from vch_item where vch_item.grn_num = @GrnNum and vch_item.grn_line = @GrnLine and vch_item.z380rcvd_date between @FromData and @ToData) begin
    select @Baf = @Baf + isnull((@QtyRec * poitem.item_cost),0)
    from grn_line
    inner join poitem on poitem.po_num = grn_line.grn_num and poitem.po_line = grn_line.grn_line
    end



    END --WHILE 1 = 1

    CLOSE report_crs_grn
    DEALLOCATE report_crs_grn

    ------------------------------------------------------------------
    abbastanza base credo.
    la select iniziale posso inserirla in una tabella temporanea, per esempio, di tipo variabile.
    ma poi, anche usando while, come posso girare sulla tabella ed eseguire l'if not exists, per esempio.

    grazie e perdona il disturbo
    V.
  • Re: Cursori

    vittosss ha scritto:


    Grazie toki per la risposta!
    perdonami, devo "incalzarti" perchè mi è poco chiaro come iterare su una tabella senza usare cicli
    Veramente Toki ha scritto il contrario. Leggi bene.
    A parte questo, il codice va indicate e formattato con i tag CODE, come da Regolamento.
  • Re: Cursori

    Ehm....io ho riletto ma continuo a non capire onestamente...
    sono supportati ma non andrebbero usati...
  • Re: Cursori

    Ciao, al momento sono impegnato, ti posto più tardi un esempio con le tabelle temporanee
  • Re: Cursori

    Figurati! grazie mille per la disponibilità!
  • Re: Cursori

    Ciao,
    come ti suggeriva gibra posta sempre il codice dentro i tag CODE, altrimenti è poco leggibile.

    Ti faccio di seguito un esempio basilare su come usare la tabella temporanea iterando i records.
    declare 
    @prodotto_id int
    
    create table #tmp1
    			(
    			prodotto_id int
    			)
    insert into #tmp1
    select prodotto_id, .... from dbo.catalogo_prodotti where ....
    
    while EXISTS(SELECT TOP 1 prodotto_id FROM #tmp1)
    BEGIN
    	SELECT TOP 1 @prodotto_id = prodotto_id from #tmp1
    	-- Inizio istruzioni custom
    	update catalogo_prodotti set .... where prodotto_id = @prodotto_id --E' solo un esempio, qui ci esegui quello che ti serve
    	-- fine istruzioni custom
    	DELETE #tmp1 WHERE prodotto_id = @prodotto_id
    
    END
    drop table #tmp1
    END
    Se hai dei dubbi fammi sapere
  • Re: Cursori

    Sono perplesso
    sembra essere più performante il cursore....
  • Re: Cursori

    Prova con una variabile tabella:
    
    DECLARE @Tabella table(ID int not null primary key identity(1,1), CpPp nvarchar(30), ImportoRiga money)
    	DECLARE @i integer, @pos integer, @CpPp nvarchar(30), @ImportoRiga money
    	INSERT INTO @Tabella SELECT FRighe.FR_CpPp, SUM(FRighe.FR_ImportoRiga) FROM FRighe
    	WHERE (((FRighe.FR_Num)=@nFatt) AND ((FRighe.FR_Ese)=@Ese) AND ((FRighe.FR_Tipo)=@Tipo)) GROUP BY FRighe.FR_CpPp;
    	SET @i=0
    	---SELECT @pos=COUNT(*) FROM @Tabella
    	SET @pos=@@ROWCOUNT
    	WHILE @i<@pos
    		BEGIN
    			SET @i=@i+1
    			SELECT @CpPp=CpPp, @ImportoRiga=ImportoRiga FROM @Tabella WHERE ID=@i
    			--------------------------------codice da eseguire per ogni record letto.
    		END
    
Devi accedere o registrarti per scrivere nel forum
9 risposte