none
Ajuda com cursor e insert RRS feed

  • Pergunta

  • Boa tarde,

    Sou completamente nova nisto e estou a tentar usar um cursor com insert mas tenho me visto algo confusa com os resultados.

    O meu objectivo é calcular o peso médio de artigos numa base de dados. Para isso, selecciono as última entradas de cada artigo até perfazer o stock actual de cada um, para depois me dedicar à média. Ou seja, pretendo criar uma tabela com todas as entradas referentes a um artigo cuja soma "contenha" a quantidade em stock. Tentei de várias formas mas utilizando o if, não consegui fazê-lo de forma nenhuma, sem perceber onde estou a errar.

    No final, acabei por aceitar a query abaixo, mas não percebo bem como ela está a funcionar.  Basicamente crio a tabela com os dados de que necessito. E através do cursor percorro as linhas e insiro-as na tabela #rt. Comparando a coluna runningtotal com o stock actual, decido se apago essa linha da tabela salary1.

    CREATE TABLE Salary1(ID int IDENTITY(1, 1), cod nvarchar(50), sal decimal(12,4), quant int, valuni decimal(12,4), data datetime, tpdoc NVARCHAR(5), numdoc nvarchar(20), serie nvarchar(6), ano nvarchar(4), stock decimal(12,4), media decimal(12,4), fornecedor varchar(20))
    INSERT INTO Salary1 (cod, Sal, quant, valuni, data, tpdoc, numdoc, serie, ano, stock, fornecedor)
    select artigo, valor, quant, Str(valor/quant, 12, 4) as valuni, docgclin.data, tpdocum, docgclin.nnumdoc, docgclin.serie, docgclin.ano, stdisp, terceiro from docgclin inner join docgccab on 
    docgccab.nnumdoc=docgclin.nnumdoc and docgccab.tpdoc=docgclin.tpdocum and docgccab.serie=docgclin.serie and 
    docgccab.ano=docgclin.ano inner join artigos on docgclin.artigo=artigos.codigo where (artigo like'5%' or artigo like'1%') and 
    areag=4 and valor<>0 and docgclin.ano>=Year(getdate()) and nvias<>-1 and [CONVERT]<>'-1' and linanu<>-1 and (tpdocum='fse' or tpdocum='ccf' or tpdocum='cdf' 
    or tpdocum='cim' or tpdocum='com' or tpdocum='gef') group by tpdocum, docgclin.nnumdoc, docgclin.serie, docgclin.ano, docgclin.artigo,
    docgclin.valor, docgclin.quant, docgclin.DATA, artigos.STDISP, docgccab.TERCEIRO
    order by artigo, docgclin.data desc

    CREATE TABLE #rt (id int, cod nvarchar(50), Salary decimal,  quant int, valuni decimal(12,4), data datetime, RunningTotal decimal)
    DECLARE @id int,
    @cod nvarchar(50),
    @actual nvarchar(50),
            @salary decimal,
    @quant int, 
    @valuni decimal(12,4), 
    @data datetime,
            @RunningTotal decimal

    DECLARE rt_cursor CURSOR
    FOR
    SELECT id, cod, sal, quant, valuni, data
    FROM Salary1

    SET @RunningTotal = 0

    OPEN rt_cursor

    FETCH NEXT FROM rt_cursor INTO @id, @cod, @salary, @quant, @valuni, @data

    WHILE @@FETCH_STATUS = 0
     BEGIN
    if (@cod=@actual and @RunningTotal <= (select stdisp from artigos where codigo=@cod)) 
    SET @RunningTotal = @RunningTotal + @quant

    if @cod<>@actual 
    set @RunningTotal = @quant
    set @actual=@cod
    INSERT #rt VALUES (@id,@cod,@salary,@quant,@valuni,@data,@RunningTotal)

    if (@cod=@actual and @RunningTotal >= (select stdisp from artigos where codigo=@cod)) 
    DELETE FROM salary1 WHERE CURRENT OF rt_cursor


    FETCH NEXT FROM rt_cursor INTO @id, @cod, @salary, @quant, @valuni, @data
     
    END

    CLOSE rt_cursor
    DEALLOCATE rt_cursor
    select * from salary1
    select * from #rt

    A minha dúvida prende se com a utilização do if e do ciclo. Pois de várias formas tentei que, de acordo com a condição, ele inserisse ou não a linha na #rt. Mas independentemente de estar contida no if ou não, o sql inseria-me todas as linhas na #rt. Se eu colocar parentesis a query deixa de funcionar: 

    enquanto @@FETCH_STATUS = 0
    começa
    se (@cod=@actual and @RunningTotal <= (select stdisp from artigos where codigo=@cod)) faz

    (SET @RunningTotal = @RunningTotal + @quant

    INSERE os valores em #rt) 


    se (@cod<>@actual) faz
    (set @RunningTotal = @quant
    set @actual=@cod
    INSERE valores em #rt)

    se (@cod=@actual and @RunningTotal >= (select stdisp from artigos where codigo=@cod)) faz
    APAGA FROM salary1 WHERE CURRENT OF rt_cursor


    FETCH NEXT FROM rt_cursor INTO @id, @cod, @salary, @quant, @valuni, @data
     

    fim

    Desde já agradeço a vossa ajuda. As minha dúvidas são muitas mas espero ter me feito entender. 

    Abraço.

    terça-feira, 18 de setembro de 2012 15:24

Respostas

  • Bom dia !

    Acredito que descobri o que esta acontecendo, criei uma estrutura como a que te passei e preenchi alguns dados ficticios nas tabelas, quando rodei realmente não populou nenhuma informação na sua tabela temporaria, porem vi que o problema é na variavel @actual, voce somente esta declarando esta variavel e ela esta ficando como NULL, então quando voce faz uma comparação de igualdade ou diferença com esta variavel não vai funcionar por que NULL não é igual ou diferente de algum valor, tente passar um valor para esta variavel que deve funcionar.


    Alexandre Matayosi Conde Mauricio. Se esta sugestão for útil, por favor, classifique-a como útil. Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    • Sugerido como Resposta Eduardo Priore sábado, 22 de setembro de 2012 03:16
    • Marcado como Resposta anaiflight segunda-feira, 24 de setembro de 2012 11:21
    quarta-feira, 19 de setembro de 2012 13:18

Todas as Respostas

  • Boa tarde ! pelo que entendi voce ja tem todas as informações que voce quer em uma tabela e aplicaria somente uma calculo onde a formula utilizada seria a mesma, partindo disto seria realmente necessario um cursor ? não poderia ser um batch ? de qualquer foram veja se o script abaixo resolve, só fiz algumas alterações no seu cursor nos IFs com begin e end para cada um deles:

    DECLARE @id int,
     @cod nvarchar(50),
     @actual nvarchar(50),
             @salary decimal,
     @quant int, 
     @valuni decimal(12,4), 
     @data datetime,
             @RunningTotal decimal
     
    DECLARE rt_cursor CURSOR
     FOR
     SELECT id, cod, sal, quant, valuni, data
     FROM Salary1
     
    SET @RunningTotal = 0
     
    OPEN rt_cursor
     
    FETCH NEXT FROM rt_cursor INTO @id, @cod, @salary, @quant, @valuni, @data
     
    WHILE @@FETCH_STATUS = 0
      BEGIN
     if (@cod=@actual and @RunningTotal <= (select stdisp from artigos where codigo=@cod)) 
     begin
     SET @RunningTotal = @RunningTotal + @quant
     end
     
    if @cod<>@actual 
    begin
     set @RunningTotal = @quant
     set @actual=@cod
     INSERT #rt VALUES (@id,@cod,@salary,@quant,@valuni,@data,@RunningTotal)
     end
     
    if (@cod=@actual and @RunningTotal >= (select stdisp from artigos where codigo=@cod)) 
     begin
     DELETE FROM salary1 WHERE CURRENT OF rt_cursor
     end
    
    FETCH NEXT FROM rt_cursor INTO @id, @cod, @salary, @quant, @valuni, @data
      
     END
     
    CLOSE rt_cursor
     DEALLOCATE rt_cursor


    Alexandre Matayosi Conde Mauricio. Se esta sugestão for útil, por favor, classifique-a como útil. Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    terça-feira, 18 de setembro de 2012 21:03
  • Olá,

    Antes de mais obrigada pela resposta. Já tentei dessa forma, sem qualquer sucesso. A tabela fica sem linhas. Dai eu não perceber como estão a funcionar os if. 

    Qualquer outra sugestão, eu agradeço. 

    Obrigada.

    Abraço.


    quarta-feira, 19 de setembro de 2012 10:53
  • Bom dia !

    Acredito que descobri o que esta acontecendo, criei uma estrutura como a que te passei e preenchi alguns dados ficticios nas tabelas, quando rodei realmente não populou nenhuma informação na sua tabela temporaria, porem vi que o problema é na variavel @actual, voce somente esta declarando esta variavel e ela esta ficando como NULL, então quando voce faz uma comparação de igualdade ou diferença com esta variavel não vai funcionar por que NULL não é igual ou diferente de algum valor, tente passar um valor para esta variavel que deve funcionar.


    Alexandre Matayosi Conde Mauricio. Se esta sugestão for útil, por favor, classifique-a como útil. Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    • Sugerido como Resposta Eduardo Priore sábado, 22 de setembro de 2012 03:16
    • Marcado como Resposta anaiflight segunda-feira, 24 de setembro de 2012 11:21
    quarta-feira, 19 de setembro de 2012 13:18
  • Bom dia,

    Era isso mesmo. O problema era a comparação com valor nulo. Muito obrigada pela ajuda! 

    Abraço.

    segunda-feira, 24 de setembro de 2012 11:24