Mais uma dúvida no Oracle

Existe como selecionar um conjunto de N registros de uma tabela em uma determinada ordem e então atribuir um número seqüencial de 1 a N para cada registro selecionado, na ordem determinada, tudo isto em um unico update (por motivos de atomicidade)?

algo tipo (sei lá):

update (select from tabela where condicao ORDER BY campoQualquer) set campo = 1..N

valew!

Dá sim.

 update (select * from tabela 
 where condicao 
 ORDER BY campoQualquer)
 set campo = (SELECT ROWNUM FROM tabela where condicao ORDER BY campoQualquer)

[quote=kmagnani]Existe como selecionar um conjunto de N registros de uma tabela em uma determinada ordem e então atribuir um número seqüencial de 1 a N para cada registro selecionado, na ordem determinada, tudo isto em um unico update (por motivos de atomicidade)?

algo tipo (sei lá):

update (select from tabela where condicao ORDER BY campoQualquer) set campo = 1..N

valew![/quote]
Apagado, gostei da solução anterior, não tinha visto… :lol: :lol: :lol:

Obrigado pela resposta, boaglio!

Sem querer ser chato, eu gostaria de fazer ainda algo um pouco mais complicado. Eu gostaria de agrupar segundo um campo no select e reiniciar o número atribuído a cada mudança de grupo. (!)

Algo tipo isto, onde eu não sei o que poderia ser o XXX:

update (select * from tabela where condicao order by campoQualquer GROUP BY campoQualquer) set campo = (select XXX from tabela where condicao order by campoQualquer GROUP BY campoQualquer)

Isso não dá pra fazer, a partir do momento q vc agrupa as linhas, vc perde a referência de onde está o registro para alterar.

Parece que mesmo a primeira sintaxe não funciona!

Olha só:

UPDATE ( SELECT * FROM pessoa p INNER JOIN classe c ON p.cod_classe = c.seq_classe WHERE cod_grupo = 98 ORDER BY num_ordem_pessoa_grupo ) SET num_ordem_pessoa_grupo = ( SELECT ROWNUM FROM pessoa p INNER JOIN classe c ON p.cod_classe = c.seq_classe WHERE cod_grupo = 98 ) ;

Erro: ORA-01427: single-row subquery returns more than one row

Pra funcionar, tive que mudar a query assim:

UPDATE ( SELECT * FROM pessoa p INNER JOIN classe c ON p.cod_classe = c.seq_classe WHERE cod_grupo = 98 ORDER BY num_ordem_pessoa_grupo ) t1 SET num_ordem_pessoa_grupo = ( SELECT rnum FROM ( SELECT ROWNUM rnum, seq_pessoa FROM pessoa p INNER JOIN classe c ON p.cod_classe = c.seq_classe WHERE cod_grupo = 98 ORDER BY num_ordem_pessoa_grupo) t2 WHERE t1.seq_pessoa = t2.seq_pessoa )

Ok, isso funcionou pq vc não usou o agrupamento (GROUP BY), conforme eu havia dito.

Quando o agrupamento é feito, perde-se o ROWID de cada linha.

Isto é verdade… Tive de remover o group by. Mas ainda é a solução da primeira questão.

Estou tentando adaptar esta solução para a segunda questão. Ou seja, a cada novo “grupo” (definida em cod_grupo), gostaria de reiniciar o contador. Tentei o seguinte código:

UPDATE ( SELECT * FROM pessoa p1 INNER JOIN classe c1 ON p1.cod_classe = c1.seq_classe ORDER BY cod_grupo, num_ordem_pessoa_grupo ) t1 SET num_ordem_pessoa_grupo = ( SELECT rnum FROM ( SELECT ROWNUM rnum, seq_pessoa FROM pessoa p2 INNER JOIN classe c2 ON p2.cod_classe = c2.seq_classe WHERE c2.cod_grupo = t1.cod_grupo ORDER BY num_ordem_pessoa_grupo) t2 WHERE t1.seq_pessoa = t2.seq_pessoa ) ;

mas o Oracle reclama do t1.cod_grupo na linha 12. Se eu troco o t1 por c1 ele continua reclamando. Se eu coloco apenas c2.cod_grupo = cod_grupo, ele aceita, mas não creio que ele esteja fazendo o que eu quero.

Acho mais fácil vc dar uma estudada em PL/SQL e fazer isso em um bloco.

Dá pra manter a atomicidade e a sua tarefa será bem mais simples.