AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 9759
Accepted
Manuel Leduc
Manuel Leduc
Asked: 2011-12-28 01:10:21 +0800 CST2011-12-28 01:10:21 +0800 CST 2011-12-28 01:10:21 +0800 CST

Restrição exclusiva de várias colunas do PostgreSQL e valores NULL

  • 772

Tenho uma tabela assim:

create table my_table (
    id   int8 not null,
    id_A int8 not null,
    id_B int8 not null,
    id_C int8 null,
    constraint pk_my_table primary key (id),
    constraint u_constrainte unique (id_A, id_B, id_C)
);

E eu quero (id_A, id_B, id_C)ser distinto em qualquer situação. Portanto, as duas inserções a seguir devem resultar em um erro:

INSERT INTO my_table VALUES (1, 1, 2, NULL);
INSERT INTO my_table VALUES (2, 1, 2, NULL);

Mas não se comporta como esperado pois de acordo com a documentação, dois NULLvalores não são comparados entre si, então ambas as inserções passam sem erro.

Como posso garantir minha restrição exclusiva, mesmo que id_Cpossa ser NULLnesse caso? Na verdade, a verdadeira questão é: posso garantir esse tipo de exclusividade em "sql puro" ou tenho que implementá-lo em um nível superior (java no meu caso)?

postgresql constraint
  • 3 3 respostas
  • 145497 Views

3 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2011-12-28T02:51:07+08:002011-12-28T02:51:07+08:00

    Postgres 15

    Isso funciona fora da caixa com NULLS NOT DISTINCT:

    ALTER TABLE my_table
      DROP CONSTRAINT IF EXISTS u_constrainte
    , ADD CONSTRAINT u_constrainte UNIQUE NULLS NOT DISTINCT (id_A, id_B, id_C);
    

    Ver:

    • Criar restrição exclusiva com colunas nulas

    Postgres 14 ou mais antigo (resposta original)

    Você pode fazer isso em SQL puro . Crie um índice exclusivo parcial além do que você tem:

    CREATE UNIQUE INDEX ab_c_null_idx ON my_table (id_A, id_B) WHERE id_C IS NULL;
    

    Desta forma, você pode inserir (id_A, id_B, id_C)na sua tabela:

    (1, 2, 1)
    (1, 2, 2)
    (1, 2, NULL)
    

    Mas nada disso uma segunda vez.

    Ou use dois índices parciais UNIQUEe nenhum índice completo (ou restrição). A melhor solução depende dos detalhes de suas necessidades. Comparar:

    • Criar restrição exclusiva com colunas nulas

    Embora isso seja elegante e eficiente para uma única coluna anulável no UNIQUEíndice, fica fora de controle rapidamente para mais de uma. Discutindo isso - e como usar o UPSERT com índices parciais:

    • Problema do PostgreSQL UPSERT com valores NULL

    Apartes

    Não há uso de identificadores de maiúsculas e minúsculas sem aspas duplas no PostgreSQL.

    Você pode considerar uma serialcoluna como chave primária ou uma IDENTITYcoluna no Postgres 10 ou posterior. Relacionado:

    • Coluna da tabela de incremento automático

    Então:

    CREATE TABLE my_table (
       my_table_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY  -- for pg 10+
    -- my_table_id bigserial PRIMARY KEY  -- for pg 9.6 or older
     , id_a int8 NOT NULL
     , id_b int8 NOT NULL
     , id_c int8
     , CONSTRAINT u_constraint UNIQUE (id_a, id_b, id_c)
    );
    

    Se você não espera mais de 2 bilhões de linhas (> 2147483647) durante o tempo de vida de sua tabela (incluindo linhas perdidas e excluídas), considere integer(4 bytes) em vez de bigint(8 bytes).

    • 155
  2. Luc M
    2012-05-18T12:57:27+08:002012-05-18T12:57:27+08:00

    Eu tive o mesmo problema e encontrei outra maneira de ter NULL exclusivo na tabela.

    CREATE UNIQUE INDEX index_name ON table_name( COALESCE( foreign_key_field, -1) )
    

    No meu caso, o campo foreign_key_fieldé um inteiro positivo e nunca será -1.

    Então, para responder ao Manual Leduc, outra solução poderia ser

    CREATE UNIQUE INDEX  u_constrainte (COALESCE(id_a, -1), COALESCE(id_b,-1),COALESCE(id_c, -1) )
    

    Presumo que os ids não sejam -1.

    Qual é a vantagem de criar um índice parcial?
    Caso você não tenha a cláusula NOT NULL, id_a, id_be id_cpode ser NULL juntos apenas uma vez.
    Com um índice parcial, os 3 campos podem ser NULL mais de uma vez.

    • 18
  3. ypercubeᵀᴹ
    2011-12-28T16:09:52+08:002011-12-28T16:09:52+08:00

    Um Null pode significar que o valor não é conhecido para essa linha no momento, mas será adicionado, quando conhecido, no futuro (exemplo FinishDatepara um running Project) ou que nenhum valor pode ser aplicado para essa linha (exemplo EscapeVelocitypara um buraco negro Star).

    Na minha opinião, geralmente é melhor normalizar as tabelas eliminando todos os Nulls.

    No seu caso, você deseja permitir NULLsem sua coluna, mas deseja que apenas uma NULLseja permitida. Por quê? Que tipo de relação é essa entre as duas tabelas?

    Talvez você possa simplesmente alterar a coluna NOT NULLe armazenar, em vez de NULL, um valor especial (como -1) que é conhecido por nunca aparecer. Isso resolverá o problema de restrição de exclusividade (mas pode ter outros efeitos colaterais possivelmente indesejados. Por exemplo, usar -1para significar "não conhecido / não se aplica" distorcerá qualquer soma ou cálculo médio na coluna. Ou todos esses cálculos terão que levar em conta o valor especial e ignorá-lo.)

    • 9

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como você mostra o SQL em execução em um banco de dados Oracle?

    • 2 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Posso ver Consultas Históricas executadas em um banco de dados SQL Server?

    • 6 respostas
  • Marko Smith

    Como uso currval() no PostgreSQL para obter o último id inserido?

    • 10 respostas
  • Marko Smith

    Como executar o psql no Mac OS X?

    • 11 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Marko Smith

    Passando parâmetros de array para um procedimento armazenado

    • 12 respostas
  • Martin Hope
    Manuel Leduc Restrição exclusiva de várias colunas do PostgreSQL e valores NULL 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler Quando uma chave primária deve ser declarada sem cluster? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - Qual é melhor como chave primária? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick Como posso otimizar um mysqldump de um banco de dados grande? 2011-01-04 13:13:48 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve