Usuário com melhor resposta
Ajuda com cursor e insert

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.
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
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.
-
-
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
-