PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Restrição definida DIFERÍVEL INICIALMENTE IMEDIATO ainda é DIFERIDO?


Lembro-me de ter levantado um ponto quase idêntico quando o PG9 estava em estado alfa. Aqui estava a resposta de Tom Lane (desenvolvedor principal do PG de alto perfil):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php

Resumindo:não vai consertar.

Para não dizer que concordo com sua sugestão de que o comportamento atual é um bug. Olhe pelo ângulo oposto:é o comportamento de NOT DEFERRABLE isso está incorreto.

De fato, a violação da restrição neste UPDATE nunca deve acontecer em nenhum caso, pois ao final do UPDATE a restrição é satisfeita. O estado no final do comando é o que importa. Os estados intermediários durante a execução de uma única instrução não devem ser expostos ao usuário.

Parece que o PostgreSQL implementa a restrição não adiável verificando duplicatas após cada linha atualizada e falhando imediatamente após a primeira duplicata, o que é essencialmente falho. Mas este é um problema conhecido, provavelmente tão antigo quanto o PostgreSQL. Atualmente a solução para isso é precisamente usar uma restrição DEFERRABLE. E há alguma ironia em que você está olhando para ele como deficiente porque não falha, enquanto de alguma forma deveria ser a solução para a falha em primeiro lugar!

Resumo do status quo desde o PostgreSQL 9.1


  • NOT DEFERRABLE UNIQUE ou PRIMARY KEY as restrições são verificadas após cada linha .

  • DEFERRABLE restrições definidas como IMMEDIATE (INITIALLY IMMEDIATE ou via SET CONSTRAINTS ) são verificados após cada instrução .

  • DEFERRABLE restrições definidas como DEFERRED (INITIALLY DEFERRED ou via SET CONSTRAINTS ) são verificados após cada transação .

Observe o tratamento especial de UNIQUE / PRIMARY KEY restrições.Citando a página de manual para CREATE TABLE :

Uma restrição que não é adiável será verificada imediatamente após cada comando .

Embora afirme mais abaixo em Compatibilidade seção em Non-deferred uniqueness constraints :

Quando um UNIQUE ou PRIMARY KEY a restrição não é adiável, o PostgreSQL verifica a exclusividade imediatamente sempre que uma linha é inserida ou modificada. O padrão SQL diz que a exclusividade deve ser forçada somente no final da instrução; isso faz diferença quando, por exemplo, um único comando atualiza vários valores de chave. Para obter um comportamento compatível com o padrão, declare a restrição comoDEFERRABLE mas não adiado (ou seja, INITIALLY IMMEDIATE ). Esteja ciente de que isso pode ser significativamente mais lento do que a verificação imediata de exclusividade.

Minha ênfase em negrito.

Se você precisar de alguma FOREIGN KEY restrições para referenciar a(s) coluna(s), DEFERRABLE não é uma opção porque (por documentação):

As colunas referenciadas devem ser as colunas de uma restrição de chave primária ou exclusiva não adiável na tabela referenciada.