2015-10-21 12:03 GMT-02:00 Eduardo Az - EMBRASIS <[email protected]>
:
> -como ID é serial, via select vejo o ultimo registo com o max()
Ok. Muita resposta, posso resumir? Existem, que eu saiba, ao menos 3 opções
confiáveis para isso (duas foram comentadas). Vou mostrar um pseudo-código
baseado em PL/pgSQL...
Solução 1: antes de inserir na tabela de pedidos você chama manualmente a
função nextval e salva o valor gerado:
SELECT nextval(pg_get_serial_sequence('pedidos', 'id')) INTO v_id;
-- use o valor salvo na variável para inserir na pedidos:
INSERT INTO pedidos(id, funcionario, ...) VALUES(v_id, p_funcionario,
...);
-- Na hora de inserir na pedido_itens (para cada item):
INSERT INTO pedido_itens(id_pedido, id_produto, ...) VALUES(v_id,
p_produto, ...);
Solução 2: após inserir em pedidos, use a função currval para recuperar o
valor:
-- Inserir na pedidos normalmente (veja que não referencio o "id", mas
também poderia usar o DEFAULT):
INSERT INTO pedidos(funcionario, ...) VALUES(p_funcionario, ...);
-- Busca o valor gerado usando a função currval
SELECT currval(pg_get_serial_sequence('pedidos', 'id')) INTO v_id;
-- Aqui é igual à anterior:
INSERT INTO pedido_itens(id_pedido, id_produto, ...) VALUES(v_id,
p_produto, ...);
Solução 3: use a cláusula RETURNING do comando INSERT:
-- Inserir na pedidos e já recupera o valor gerado, numa só tacada:
INSERT INTO pedidos(funcionario, ...) VALUES(p_funcionario, ...)
RETURNING id INTO v_id;
-- Aqui é igual à anteriores:
INSERT INTO pedido_itens(id_pedido, id_produto, ...) VALUES(v_id,
p_produto, ...);
Na minha opinião, a solução 3 é sem dúvida a melhor. Por vários motivos:
1. Não precisa duas idas ao servidor, em uma tacada só já faz o INSERT e
recupera o valor gerado;
2. Evita qualquer erro que possa acontecer caso seja gerado um novo id pela
sequence na mesma sessão (só seria possível vai trigger, nesse caso, mas já
vi acontecer);
3. Não precisa se preocupar com o nome da sequence, na verdade nem precisa
se preocupar com sua existência;
4. Funciona mesmo que troque o modelo para gerar "id" (comum acontecer
quando tem-se mais de um servidor de banco);
... deve ter mais ...
OBS: A função pg_get_serial_sequence recupera o nome da sequence que foi
criada usando o tipo serial ou OWNED BY. Acho mais simples e confiável que
usar o nome da sequence. Tudo bem que a solução 3, minha preferida, nem
precisamos de nos preocupar com a sequence.
OBS2: Esse erro é bem comum, infelizmente. Aliás tem vários erros comuns
que são bem simples, veja [1] (nem é merchan... :P )
[1]
http://www.slideshare.net/matheus_de_oliveira/dev-camp2015-top5falsassuposicoesprogramadores
(slide 58 fala sobre esse caso, não é específico de PostgreSQL)
Atenciosamente,
--
Matheus de Oliveira
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral