Dependendo da tua situação podes, usar uma união de SEQUENCES e INSERT
RETURNING.

2011/3/3 Flavio Henrique Araque Gurgel <fha...@gmail.com>

> > Bem, não fiz algo muito bem feito, mas pode ilustrar bem o
> > funcionamento do SELECT FOR UPDATE:
> >
> > CREATE TABLE CONTADOR(
> >        ID INTEGER NOT NULL,
> >        DESCRICAO VARCHAR(30) NOT NULL,
> >        VALOR INTEGER NOT NULL
> > );
> >
> > ALTER TABLE CONTADOR ADD PRIMARY KEY( id );
> >
> > -- Função que retorna o último contador gravado e incrementa 1 ao final
> > CREATE OR REPLACE FUNCTION UF_ADD_CONTADOR( ai_id INTEGER )
> > RETURNS INTEGER AS
> > $BODY$
> > DECLARE
> >        li_id INTEGER;
> > BEGIN
> >        -- Pega o valor. A cláusula FOR UPDATE faz um ROW LOCK EXCLUSIVE
> >        -- apenas sobre o registro especificado. Somente após um COMMIT ou
> >        -- ROLLBACK o LOCK será liberado.
> >        -- NOTA: o registro deve existir na tabela. Você pode fazer o
> tratamento
> >        -- para criá-lo caso não exista ou então deixar pré-cadastrado
> >        SELECT
> >                valor
> >        INTO
> >                li_id
> >        FROM
> >                contador
> >        WHERE
> >                id = ai_id
> >        FOR UPDATE;
> >
> >        -- Incrementa o valor do contador
> >        UPDATE
> >                contador
> >        SET
> >                valor = valor +1
> >        WHERE
> >                id = ai_id;
> >
> >        -- Retorna o valor
> >        RETURN li_id;
> > END
> > $BODY$
> > LANGUAGE 'plpgsql' VOLATILE;
> >
> >
> > -- Insere o registro na tabela de contador para que possa ser
> incrementado
> > INSERT INTO contador ( id, descricao, valor ) VALUES( 1, 'Contador
> Teste', 1 );
> >
> > -- Para recuperar o valor dentro de uma transação...
> > -- NOTA: se outra transação estiver executando o mesmo comando, ela irá
> aguardar
> > -- até que a primeira transação realize um ROLLBACK ou COMMIT.
> > -- Caso um ROLLBACK seja executado, o valor não é incrementado.
> > SELECT uf_add_contador( 1 ) as valor
>
> Sinto muito, mas essa implementação pode ter um efeito colateral. Duas
> transações concorrentes podem "catar" o mesmo valor. O SELECT... FOR
> UPDATE não impede a leitura do registro.
> Pode ocorrer um ROLLBACK automático na transação que chegar por último
> na hora fizer o UPDATE da sua função. Se a aplicação não tratar esse
> ROLLBACK (e tentar novamente até conseguir sucesso no COMMIT) isso
> pode se tornar uma bola de neve e um catastrófico "lock geral" numa
> aplicação com muita concorrência.
>
> A implementação de sequências foi inventada exatamente pra isso, sem
> dor de cabeça. Não acho legal tentar contornar por fora algo que um
> banco de dados sério sabe fazer com maestria.
>
> []s
> Flavio Gurgel
> _______________________________________________
> pgbr-geral mailing list
> pgbr-geral@listas.postgresql.org.br
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>



-- 
Fernando Brombatti
email-msn-gtalk-skype:
bromba...@gmail.com
work: +55 54 3218-6060
home: +55 54 3028-7217
mobile: +55 54 9189-7970
_______________________________________________
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a