Como faço para criar uma restrição de tabela para evitar valores duplicados em duas colunas?

StackOverflow https://stackoverflow.com/questions/626609

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu tenho a seguinte tabela:

CREATE TABLE [dbo].[EntityAttributeRelship](
    [IdNmb] [int] IDENTITY(1,1) NOT NULL,
    [EntityIdNmb] [int] NOT NULL,
    [AttributeIdNmb] [int] NOT NULL,
    [IsActive] [bit] NOT NULL CONSTRAINT [DF_EntityAttributeRelship_IsActive]  DEFAULT ((0)),
CONSTRAINT [PK_EntityAttributeRelship] PRIMARY KEY CLUSTERED 
([IdNmb] ASC) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]

Uma parte dos dados nos olhares de mesa como algo com isto:

IdNmb    EntityIdNmb    AttributeIdNmb  IsActive
1        22             7               0
2        22             8               0
3        22             9               0
4        22             10              1

Eu quero adicionar uma restrição para se certificar de que ninguém adiciona ou atualiza um registro para ter IsActive = 1, se já existe um registro para o EntityIdNmb onde IsActive = 1.

Como posso fazer isso?

Foi útil?

Solução

Se você estiver usando SQLServer você pode criar uma exibição indexada em cluster.

CREATE VIEW dbo.VIEW_EntityAttributeRelship WITH SCHEMABINDING AS
SELECT EntityIdNmb 
FROM dbo.EntityAttributeRelship
WHERE IsActive = 1
GO

CREATE UNIQUE CLUSTERED INDEX UIX_VIEW_ENTITYATTRIBUTERELSHIP 
  ON dbo.VIEW_EntityAttributeRelship (EntityIdNmb)

Isso garante só há uma EntityIdNmb em sua mesa com IsActive = 1.

Outras dicas

Parece que você precisa para implementar um trigger (assumindo que seus apoios produtos db-lo). Se você só deseja uma activa e uma entrada inativa, um índice exclusivo vai funcionar. Caso contrário, você precisa escrever algum tipo de restrição personalizado ou um gatilho (provavelmente 2 - um para inserções, um para atualizações). Que garante que você não tem 2 registros com a mesma ID de onde ambos são ativos

Se você estiver usando MSSQL (acho que é isso que sua sintaxe se parece com), criar uma visão incluindo apenas as linhas com IsActive = 1, em seguida, colocar um índice exclusivo na EntityIdNmb na vista.

Em PostgreSQL, que eu trabalhei mais com recentemente, você pode criar um índice parcial: http://www.postgresql.org/docs/8.3/interactive/ índices de partial.html

A coisa com a escrita o gatilho é decidir se pretende rejeitar o registro, altere o valor para 0 em vez de um ou atualizar o registro velho para zero e deixar essa posição como um. Se você estiver excluindo o registro com o valor de 1, você precisa mudar um recorde de ser o único ativo, como você escolhe qual deles? Uma vez que você pode definir waht que você quer fazer dentro do disparador, podemos ajudá-lo melhor para projetar o processo.

Nós os dois últimos passos para fazer qualquer endereço o principal endereço em nosso banco de dados. A nossa regra de negócio é um e somente um endereço pode ser o principal e se existem endereços deve ser marcado como o principal. A chave para este tipo de gatilho é lembrar que inserções / atualizações / exclusões pode ocorrer em lotes (mesmo se este é o não a norma) e para certificar-se as obras de gatilho de uma forma baseada em conjunto. Quando cheguei aqui, o nosso implementado processamento multi-linha por meio de um cursor que se tornou uma coisa ruim quando eu tive que atualizar 200.000 addresss em uma importação. (Nota para os inexperientes - não nunca usar um cursor em um trigger)

O que os registros inativos pode ser utilizado? eles não são usados ??e lá simplesmente para manter o controle de registros anteriormente ativos? Se assim for, seria possível dividir os dados para várias tabelas? Algo como ...

EntityAttributeRelship (IDNmb, EntityIDNmb, AttributeIDNmb)

EntityAttributeRelshipHistory (IDNmb, EntityIDNmb, AttributeIDNmb)

Se é na tabela de EntityAttributeRelship, é ativo. Se é na tabela de histórico, em seguida, ele foi ativado em algum momento e, desde então, desactivada?

Se você precisa fazer tudo em uma mesa que eu iria com a sugestão de todd.run de usar um gatilho.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top