Pergunta

Vamos dizer que você tem uma mesa para filiais em sua organização. Alguns deles são "principais" ramos, e outros são escritórios satélites que rolam até um ramo principal. Outros que esta distinção, que só afeta algumas coisas no sistema, os ramos são todas iguais e têm os mesmos atributos (endereço, etc.). Uma maneira de modelar isto é, em uma tabela como:

CREATE TABLE Branch (
    branch_id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
    branch_name VARCHAR(80) NOT NULL,
    street VARCHAR(80) NULL,
    city VARCHAR(30) NULL,
    state CHAR(2) NULL,
    zip CHAR(5) NULL,
    is_satellite_office BIT NOT NULL DEFAULT(0),
    satellite_to_branch_id INT NULL REFERENCES Branch(branch_id)
)

Onde is_satellite_office = 1 sse este registro é um satélite para outro ramo, e satellite_to_branch_id refere-se a que ramo você é um satélite de, se houver.

É fácil o suficiente para colocar uma restrição sobre a mesa para que essas duas colunas concordar em qualquer registro:

CONSTRAINT [CK_Branch] CHECK 
  (
    (is_satellite_office = 0 AND satellite_to_branch_id IS NULL) 
    OR (is_satellite_office = 1 AND satellite_to_branch_id IS NOT NULL)
  )

No entanto, o que eu realmente quero é uma maneira de garantir que esta recursão só vai um nível profundo ... isto é, que se eu apontar para um ramo como o meu pai, ele não deve ter a própria mãe, e seu valor para is_satellite_office deve ser 0. em outras palavras, eu realmente não quero uma estrutura de árvore totalmente recursiva, eu só quero limitá-lo a uma única relação pai / filho. É assim que eu vou escrever o código, e se há uma maneira de aplicá-la no banco de dados que não irá executar um lixo total, o que eu gostaria de.

Todas as idéias? Eu estou trabalhando em MSSQL 2005, mas soluções gerais (não específicos de fornecedor) são os preferidos. E há gatilhos precisa de aplicar, a menos que há realmente nenhuma outra maneira de fazê-lo.

EDIT: Para ser claro, satellite_to_branch_id é o ponteiro recursiva para outro registro na mesma tabela Branch. Eu sei que eu poderia remover o is_satellite_office BIT e confiar em IsNull(satellite_to_branch_id) para me dar a mesma informação, mas eu acho que é um pouco mais claro para ser explícito e, além disso, que, isso não é a essência da questão. Estou realmente procurando uma maneira pura SQL-restrição para evitar recursão profundidade superior a 1.

Foi útil?

Solução

Você pode vincular uma restrição de verificação para o valor de retorno de uma UDF. Criar um UDF que leva as colunas envolvidas como parâmetros de entrada e, em seguida, verificar o seu estado desejado usando uma escolha na UDF.

Outras dicas

Parece-me que uma restrição de negócios, difícil de aplicar no nível de definição de dados. Eu não acredito que a álgebra relacional tem qualquer apoio para determinar um limite para auto referências profundidade.

Você não está autorizado a referir-se a um procedimento armazenado no seu constrangimento? Você pode em PostgreSQL, então eu ficaria surpreso se 2005 não permitem isso.

E sobre esta estrutura um pouco diferente?

CREATE TABLE Branch (
    branch_id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
    branch_name VARCHAR(80) NOT NULL,
    street VARCHAR(80) NULL,
    city VARCHAR(30) NULL,
    state CHAR(2) NULL,
    zip CHAR(5) NULL,
    parent_id int NULL
)

PARENT_ID simplesmente apontar para o BRANCH_ID de outro registro na mesma tabela. Se for nulo, então você sabe que não tem pais.

Então, para obter um nível de recursão, você pode simplesmente juntar-se à mesa para si uma vez, como este:

SELECT
  PARENT.BRANCH_NAME AS PARENT_BRANCH
 ,CHILD.BRANCH_NAME AS CHILD_BRANCH
FROM
  BRANCH PARENT
 ,BRANCH CHILD
WHERE CHILD.PARENT_ID PARENT.BRANCH_ID

Se você deseja impor um nível de profundidade em sua árvore, fazer um on-disparador de inserção / atualização que irá levantar uma exceção se esta consulta retorna nada.

SELECT *
FROM
  BRANCH B1
 ,BRANCH B2
 ,BRANCH B3
WHERE B1.PARENT_ID = :NEW.NEW_PARENT_ID
  AND B2.PARENT_ID = B1.BRANCH_ID
  AND B2.PARENT_ID = B3.BRANCH_ID;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top