Pergunta

Em um banco de dados que eu estou tendo que projetar para MS Access, eu tenho uma tabela chamada "medidas", que armazena certos parâmetros de medição (valores medidos, Desvio padrão, etc.) - cada linha tem um id inteiro como seu principal chave.

Outras tabelas, em seguida, conectar-se a esta tabela de medição usando relações de chave estrangeira. Algumas tabelas contêm dois campos diferentes "measurementID", que tanto link para esta tabela uma medição. No entanto, cada medição só deve ser ligado a pelo um desses campos.

Como posso impor uma restrição de exclusividade ao longo de vários campos em várias tabelas? Seja Existe uma maneira?

Foi útil?

Solução

Essas restrições podem realmente ser implementada no ACE / Jet usando restrições CHECK.

A pessoa que disse que eles normalmente usaria gatilhos para este tipo de coisa possível não está ciente da diferença entre restrições CHECK em ACE / Jet e SQL Server, respectivamente: em SQL Server não podem incluir subconsultas, o que significa que não pode se referir a valores em outras linhas da mesma tabela ou com outras tabelas, enquanto na ACE / Jet não pode.

Em um ideal (mas ainda AFAIK inexistente) SQL-92 do produto, a singularidade descrito seria implementado utilizando um ASSETION, sendo no nível de esquema. Porque restrições CHECK são tabela de nível e só são verificadas quando a tabela na qual são definidas são UPDATEd ou INSERTed, você precisa colocar restrições CHECK adequada sobre todos os tabela de referência (o mesmo se aplica aos disparadores do SQL Server). Aqui está um exemplo rápido:

CREATE TABLE Parent 
(
   parent_ID INTEGER NOT NULL IDENTITY UNIQUE, 
   data_col INTEGER NOT NULL
)
;
CREATE TABLE Child1
(
   parent_ID INTEGER NOT NULL
      REFERENCES parent (parent_ID), 
   data_col INTEGER NOT NULL
)
;
CREATE TABLE Child2
(
   parent_ID INTEGER NOT NULL
      REFERENCES parent (parent_ID), 
   data_col INTEGER NOT NULL
)
;
ALTER TABLE Child1 ADD
   CONSTRAINT child1__no_dups_in_child2
   CHECK (NOT EXISTS (
                      SELECT * 
                        FROM Child1 AS C1
                             INNER JOIN Child2 AS C2
                                ON C1.parent_ID = C2.parent_ID
                     ))
;
ALTER TABLE Child2 ADD
   CONSTRAINT child2__no_dups_in_child1
   CHECK (NOT EXISTS (
                      SELECT * 
                        FROM Child1 AS C1
                             INNER JOIN Child2 AS C2
                                ON C1.parent_ID = C2.parent_ID
                     ))
;

No entanto, eu estou querendo saber se você tem subclasses (ou seja, cada entidade representada por uma ID pode ser digitado), caso em que você deve ser capaz de usar FOREIGN KEYs e restrições em nível de linha CHECK (ou regras de validação se você é mais confortáveis ??com a interface do MS Access que SQL DLL que é necessário para limitações CHECK). A lógica vai ser mais fácil de implementar do que as restrições CHECK no nível de tabela, basta ver para ciclos em ações referenciais CASCADE. Aqui está outro exemplo simples:

CREATE TABLE Parent 
(
   parent_ID INTEGER NOT NULL IDENTITY, 
   child_type VARCHAR(4) NOT NULL, 
   CONSTRAINT child_type__values 
      CHECK (child_type IN ('Boy', 'Girl')), 
   UNIQUE (child_type, parent_ID)
)
;
CREATE TABLE Girls
(
   parent_ID INTEGER NOT NULL, 
   child_type VARCHAR(4) DEFAULT 'girl' NOT NULL, 
   CONSTRAINT girl_child_type__must_be_girl
      CHECK (child_type = 'girl'),
   FOREIGN KEY (child_type, parent_ID)
      REFERENCES Parent (child_type, parent_ID), 
   data_col INTEGER NOT NULL
)
;
CREATE TABLE Boys
(
   parent_ID INTEGER NOT NULL, 
   child_type VARCHAR(4) DEFAULT 'boy' NOT NULL, 
   CONSTRAINT boy_child_type__must_be_boy
      CHECK (child_type = 'boy'),
   FOREIGN KEY (child_type, parent_ID)
      REFERENCES Parent (child_type, parent_ID), 
   data_col INTEGER NOT NULL
)
;

Outras dicas

motor

Microsoft ACE / Jet não suporta gatilhos, que é como você normalmente implementar este tipo de funcionalidade.

EDIT: Como apontado por @onedaywhen, JET 4.0 em diante faz restrições de verificação de apoio, mas não é simples de implementar um tipo de xor restrição através de duas colunas

.

Se você estiver usando formulários do Access, você poderia implementar o antes evento de atualização do formulário e verificar os seus critérios de restrição.

Mitch está certo sobre o que é possível no Access. No entanto, supondo que você tem um lugar BL, este está afiando para o que é legítimo, como uma regra de negócio. Isso é o que eu mais provável fazer.

Uma vez que você está projetando esse banco de dados. Tem certeza de suas estruturas de tabelas estão seguindo as regras de normalização padrão.

Parece uma estrutura incomum para uma linha na tabela A para ser capaz de referenciar duas linhas em medidas da tabela, dependendo de qual campo A.row que você está olhando. Tenho a sensação de que os dados em Measurments mesa realmente precisa ser dividido em dois ou mais tabelas.

Eu mesmo sou cauteloso com gatilhos e restrições de verificação, principalmente porque eu desenvolvi a maioria dos meus aplicativos sem eles (Acesso / Jet e MySQL / MyISAM). Concordo com BobClegg que isso soa como uma situação supertipo / subtipo. Nesse caso, você usaria uma junção tabela com um índice exclusivo na chave estrangeira e uma coluna indicando que tipo de medida que era. O índice único na FK impediria a adição de um segundo tipo. Também significaria que você não teria campos vazios em seu registro principal. Certamente um campo numérico vazio não é um problema de armazenamento, mas dois campos que são exclusivos sempre parece um erro de projeto para mim.

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