Eu apenas fico preocupado com um tipo de campo integer que precisa ser
sequencial, sem furos na sequencia e nao podendo serem duplicados e um
sistema deste implantado em um cliente com mais de 200 estações que ficam
povoando as tabelas todo o tempo...

Em 4 de março de 2011 00:46, Fernando Brombatti <[email protected]>escreveu:

> Dependendo da tua situação podes, usar uma união de SEQUENCES e INSERT
> RETURNING.
>
> 2011/3/3 Flavio Henrique Araque Gurgel <[email protected]>
>
> > 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
>> [email protected]
>> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>>
>
>
>
> --
> Fernando Brombatti
> email-msn-gtalk-skype:
> [email protected]
> work: +55 54 3218-6060
> home: +55 54 3028-7217
> mobile: +55 54 9189-7970
>
> _______________________________________________
> pgbr-geral mailing list
> [email protected]
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
>


-- 
Fernando Wobeto
Desenvolvedor Web
[email protected]
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a