none
Relacionamento Circular RRS feed

  • Pergunta

  • Bom dia e bom tempo a todos que poderem me ajudar estou desenvolvendo uma aplicação que deve permite o envio de um documento de uma área para outra, o que no ato da normalização do banco de dado estou a me deparar com  uma relação circular. gostaria de saber o que faço para evitar este tipo de relação.  estou um pouco inquieto  porque alguém me disse que não pode existir uma relação circulas.

    envio em anexo a imagem 

    sexta-feira, 26 de abril de 2019 18:59

Respostas

  • Simão,

    Na verdade, quando se refere a relacionamento circular, estamos falando de autorelacionamento, sim é um cenário, que temos que tomar cuidado, mas ele pode se aplicado, o que temos que nos atentar é justamente a ordem de manipulação dos dados.

    Por exemplo em uma tabela de Funcionarios que temos definida uma coluna que identifica o CodigoDoGestor, para este cenário, temos que ter em mente que para definir o gestor de um determinado funcionário, este gestor já deve estar cadastrado, isso se chamada dependência funcional e existencial a nível de dados e não de tabelas.

    Veja o exemplo abaixo, o mesmo apresenta como estabelecer um autorelacionamento lógico, ou seja, não foi definida uma chave estrangeira, pois justamente a ordem de inserção dos dados não esta respeitando as regras hierárquicas.

    Mas nada impede de se estabelecer propriamente o relacionamento físico, criando a chave estrangeira na mesma tabela utilizada para se informar o funcionário e seu respectivo Gestor.

    -- Acessando o Banco de Dados --
    Use BDJuncao
    Go
    
    -- Criando a Tabela Funcao --
    Create Table Funcao
    (CodigoFuncao Char(2) Primary Key Not Null,
      DescricaoFuncao Varchar(50) Not Null,
      ValorSalario Numeric(6,2) Not Null)
    Go
    
    -- Criando a Tabela Areas --
    Create Table Areas
    (CodigoArea Char(2) Primary Key Not Null,
     DescricaoArea Varchar(30) Not Null,
     RamalTelefone SmallInt Not Null)
    Go
    
    -- Criando a Tabela Funcionarios --
    Create Table Funcionarios 
    (NumeroRegistro Int Primary Key Not Null,
     NomeFuncionario Varchar(80) Not Null,
     DtAdmissao Date Default GetDate(),
     Sexo Char(1) Not Null Default 'M',
     CodigoFuncao Char(2) Not Null,
     CodigoArea Char(2) Not Null,
     CodigoDoGestor Int Not Null)
    Go
    
    -- Criando os relacionamentos --
    Alter Table Funcionarios
     Add Constraint [FK_Funcionarios_Funcaos] Foreign Key (CodigoFuncao)
      References Funcao(CodigoFuncao)
    Go
    
    
    Alter Table Funcionarios
     Add Constraint [FK_Funcionarios_Areas] Foreign Key (CodigoArea)
      References Areas(CodigoArea)
    Go
    
    -- Inserindo os Dados --
    Insert Into Funcao (CodigoFuncao, DescricaoFuncao, ValorSalario)
    Values ('F1', 'Aux.Vendas', 350.00), 
    	('F2', 'Vigia', 400.00),
    	('F3', 'Vendedor', 800.00),
    	('F4', 'Aux.Cobrança', 250.00), 
    	('F5', 'Gerente', 1000.00), 
    	('F6', 'Diretor', 2500.00),
    	('F7', 'Presidente', 2500.00)
    Go
    
    Insert Into Areas (CodigoArea,DescricaoArea,RamalTelefone)
    Values ('A1', 'Assist.Técnica', 2246),
    	('A2', 'Estoque', 2589),
    	('A3', 'Administração', 2772),
    	('A4', 'Segurança', 1810),
    	('A5', 'Vendas', 2599),
    	('A6', 'Cobrança', 2688)
    Go
    
    Insert Into Funcionarios (NumeroRegistro, NomeFuncionario, DtAdmissao, Sexo, CodigoArea, CodigoFuncao, CodigoDoGestor)
    Values (101, 'Juca Sampaio', '2003-08-10', 'M', 'A3', 'F5',22),
    	(104, 'Fernando Pereira', '2004-03-02', 'M', 'A4', 'F6',101),
    	(134, 'João Alves', '2002-05-03', 'M', 'A5', 'F1',123),
    	(121, 'Paulo Souza', '2001-12-10', 'M', 'A6', 'F5',115),
    	(195, 'Maria Silveira', '2002-01-05', 'F','A3', 'F5',139),
    	(139, 'Ana Laura', '2003-01-12', 'F', 'A4', 'F6',123),
    	(123, 'Silvio Rocha', '2003-06-29', 'M', 'A6', 'F3',148),
    	(148, 'Iolanda Aguiar', '2002-06-01', 'F', 'A5', 'F3',195),
    	(115, 'Roberto Fernandes', '2003-10-15', 'M', 'A2', 'F2',22),
    	(22, 'Sergio Noriega', '2000-02-10', 'M', 'A6', 'F6',22)
    Go
    
    -- Realizando um AutoRelacionamento (Self Join) --
    Select  F.NumeroRegistro, 
    			F.NomeFuncionario, 
    			A.DescricaoArea 'Descricação da Área de Trabalho',
    			F1.DescricaoFuncao 'Descricação da Função',
    			Year(F.DtAdmissao) As Ano,
    			Month(F.DtAdmissao) As Mês,
    			Day(F.DtAdmissao) as Dia,
    			Convert(Varchar(3),F.CodigoDoGestor) + ' - ' + F2.NomeFuncionario As 'Gestor ou Responsável'
    From Funcionarios F Inner Join Areas A
    								  On F.CodigoArea = A.CodigoArea
    								 Inner Join Funcao F1
    								  On F.CodigoFuncao = F1.CodigoFuncao
    								 Inner Join Funcionarios F2
    								  On F2.NumeroRegistro = F.CodigoDoGestor
    Order By F.CodigoDoGestor Asc
    Go
    
    -- Realizando uma Junção Cruzada (Cross Join) --
    Select F.NomeFuncionario, Fu.DescricaoFuncao 
    From Funcionarios F Cross Join Funcao Fu
    Go


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Simão Cândido quarta-feira, 15 de maio de 2019 13:18
    terça-feira, 30 de abril de 2019 13:21

Todas as Respostas

  • Simão,

    A imagem acabou ficando cortada, você poderia destacar em algum das entidades estaria ocorrendo o relacionamento circular?

    Como assim não pode existir relacionamento circular? 

    Olha este tipo de cenário é comum de acontecer, normalmente chamamos de autorelacionamento, o que pode ocorrer, a grande questão neste caso, é entender a hierarquia dos dados.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Simão Cândido quarta-feira, 15 de maio de 2019 13:18
    • Não Marcado como Resposta Simão Cândido quarta-feira, 15 de maio de 2019 13:18
    sábado, 27 de abril de 2019 13:49
  • Boa irmã e muito obrigado por estar a me ajudar  na analise deste caso, o que esta a me dar dor de cabeça e as relações que existe entre: a  (Tb_Area) , (Tb_enviar_menssagem) e (Tb_itens_messagem).

    O que no meu ponto de vista, na Logica e na vida real é mesmo um circulo que este processo  faz, só que eu estou a receber chamadas de atenção dos meus colegas de trabalho porque eles defendem que um banco de dado não pode ter tabelas com relacionamento circular, alegam que no momento da consultas podem surgir alguns erros, só que também não conseguem me dizer qual seria a forma correta de fazer este relacionamento.

    Já procurei bastante na internet mas não encontro nada que possa usar de base para lhes mostrar que e funcional. 

     

    sábado, 27 de abril de 2019 18:49
  • Simão,

    Na verdade, quando se refere a relacionamento circular, estamos falando de autorelacionamento, sim é um cenário, que temos que tomar cuidado, mas ele pode se aplicado, o que temos que nos atentar é justamente a ordem de manipulação dos dados.

    Por exemplo em uma tabela de Funcionarios que temos definida uma coluna que identifica o CodigoDoGestor, para este cenário, temos que ter em mente que para definir o gestor de um determinado funcionário, este gestor já deve estar cadastrado, isso se chamada dependência funcional e existencial a nível de dados e não de tabelas.

    Veja o exemplo abaixo, o mesmo apresenta como estabelecer um autorelacionamento lógico, ou seja, não foi definida uma chave estrangeira, pois justamente a ordem de inserção dos dados não esta respeitando as regras hierárquicas.

    Mas nada impede de se estabelecer propriamente o relacionamento físico, criando a chave estrangeira na mesma tabela utilizada para se informar o funcionário e seu respectivo Gestor.

    -- Acessando o Banco de Dados --
    Use BDJuncao
    Go
    
    -- Criando a Tabela Funcao --
    Create Table Funcao
    (CodigoFuncao Char(2) Primary Key Not Null,
      DescricaoFuncao Varchar(50) Not Null,
      ValorSalario Numeric(6,2) Not Null)
    Go
    
    -- Criando a Tabela Areas --
    Create Table Areas
    (CodigoArea Char(2) Primary Key Not Null,
     DescricaoArea Varchar(30) Not Null,
     RamalTelefone SmallInt Not Null)
    Go
    
    -- Criando a Tabela Funcionarios --
    Create Table Funcionarios 
    (NumeroRegistro Int Primary Key Not Null,
     NomeFuncionario Varchar(80) Not Null,
     DtAdmissao Date Default GetDate(),
     Sexo Char(1) Not Null Default 'M',
     CodigoFuncao Char(2) Not Null,
     CodigoArea Char(2) Not Null,
     CodigoDoGestor Int Not Null)
    Go
    
    -- Criando os relacionamentos --
    Alter Table Funcionarios
     Add Constraint [FK_Funcionarios_Funcaos] Foreign Key (CodigoFuncao)
      References Funcao(CodigoFuncao)
    Go
    
    
    Alter Table Funcionarios
     Add Constraint [FK_Funcionarios_Areas] Foreign Key (CodigoArea)
      References Areas(CodigoArea)
    Go
    
    -- Inserindo os Dados --
    Insert Into Funcao (CodigoFuncao, DescricaoFuncao, ValorSalario)
    Values ('F1', 'Aux.Vendas', 350.00), 
    	('F2', 'Vigia', 400.00),
    	('F3', 'Vendedor', 800.00),
    	('F4', 'Aux.Cobrança', 250.00), 
    	('F5', 'Gerente', 1000.00), 
    	('F6', 'Diretor', 2500.00),
    	('F7', 'Presidente', 2500.00)
    Go
    
    Insert Into Areas (CodigoArea,DescricaoArea,RamalTelefone)
    Values ('A1', 'Assist.Técnica', 2246),
    	('A2', 'Estoque', 2589),
    	('A3', 'Administração', 2772),
    	('A4', 'Segurança', 1810),
    	('A5', 'Vendas', 2599),
    	('A6', 'Cobrança', 2688)
    Go
    
    Insert Into Funcionarios (NumeroRegistro, NomeFuncionario, DtAdmissao, Sexo, CodigoArea, CodigoFuncao, CodigoDoGestor)
    Values (101, 'Juca Sampaio', '2003-08-10', 'M', 'A3', 'F5',22),
    	(104, 'Fernando Pereira', '2004-03-02', 'M', 'A4', 'F6',101),
    	(134, 'João Alves', '2002-05-03', 'M', 'A5', 'F1',123),
    	(121, 'Paulo Souza', '2001-12-10', 'M', 'A6', 'F5',115),
    	(195, 'Maria Silveira', '2002-01-05', 'F','A3', 'F5',139),
    	(139, 'Ana Laura', '2003-01-12', 'F', 'A4', 'F6',123),
    	(123, 'Silvio Rocha', '2003-06-29', 'M', 'A6', 'F3',148),
    	(148, 'Iolanda Aguiar', '2002-06-01', 'F', 'A5', 'F3',195),
    	(115, 'Roberto Fernandes', '2003-10-15', 'M', 'A2', 'F2',22),
    	(22, 'Sergio Noriega', '2000-02-10', 'M', 'A6', 'F6',22)
    Go
    
    -- Realizando um AutoRelacionamento (Self Join) --
    Select  F.NumeroRegistro, 
    			F.NomeFuncionario, 
    			A.DescricaoArea 'Descricação da Área de Trabalho',
    			F1.DescricaoFuncao 'Descricação da Função',
    			Year(F.DtAdmissao) As Ano,
    			Month(F.DtAdmissao) As Mês,
    			Day(F.DtAdmissao) as Dia,
    			Convert(Varchar(3),F.CodigoDoGestor) + ' - ' + F2.NomeFuncionario As 'Gestor ou Responsável'
    From Funcionarios F Inner Join Areas A
    								  On F.CodigoArea = A.CodigoArea
    								 Inner Join Funcao F1
    								  On F.CodigoFuncao = F1.CodigoFuncao
    								 Inner Join Funcionarios F2
    								  On F2.NumeroRegistro = F.CodigoDoGestor
    Order By F.CodigoDoGestor Asc
    Go
    
    -- Realizando uma Junção Cruzada (Cross Join) --
    Select F.NomeFuncionario, Fu.DescricaoFuncao 
    From Funcionarios F Cross Join Funcao Fu
    Go


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    • Marcado como Resposta Simão Cândido quarta-feira, 15 de maio de 2019 13:18
    terça-feira, 30 de abril de 2019 13:21
  • Deleted
    terça-feira, 30 de abril de 2019 18:33
  • ok e muito obrigado, bem vamos dizer que a AREA = Usuário, Um usuário precisa enviar uma mensagem para outro usuário, e tendo em consideração que todos os usuário pertencem a mesma tabela e como toda mensagem enviada deve ter sempre um remetente e um destinatário eu criei a tabela ENVIAR_MENSAGEM para identificar o usuário que esta a enviar e a tabela ITENS_MENSAGEM para identificar o usuário vai receber a mensagem.

    o mesmo acontece na vida real, todos que remetemos aguardamos sempre uma resposta

     
    quarta-feira, 15 de maio de 2019 13:16
  • Simão,

    Certo, mas neste caso, todo controle do envio da mensagem esta sendo feito na tabela Enviar_Mensagem.

    Em uma mesma mensagem podemos ter mais de um usuário?


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    quarta-feira, 15 de maio de 2019 17:36
  • Sim.
    segunda-feira, 20 de maio de 2019 12:15
  • Simão,

    Neste caso, você vai precisar ter uma tabela que armazena basicamente vai armazenar:

    - Código da Mensagem;

    - Código dos Usuários envolvidos no envio; e

    - Código dos Usuários envolvidos no recebimento.

    Aparentemente na sua modelagem este cenário não esta contemplado. É isso?


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 20 de maio de 2019 12:24
  •  Sim mas para obter esses dados  de quem envio e que recebeu eu faço consulta usando o código da mensagem que o elo de ligação dos dois.
    segunda-feira, 20 de maio de 2019 12:30
  • Simão,

    Ok, certo, eu faria diferente, pensaria justamente em ter todo os controle dos envolvidos no envio, recebimento e a propria mensagem em uma tabela centralizada, guardando somente os respectivos ids de cada um.

    Mas se esta funcionando para você, vamos em frente.

    Mesmo assim, vou deixar aqui um conceito relacionado a área de modelagem de banco de dados, mais especificamente falando de Cardinalidade, quando tempos N (Muitos) elementos de um lado, relacionados com N (Muitos) elementos do outro, esta relação deve se tornar uma nova entidade.

    Bom, como destaquei é somente um conceito e forma de se trabalhar para refletirmos o seu cenário.

    Abraços.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 20 de maio de 2019 13:08
  • ok. e muito obrigado 

    Falando do conceito  que deixaste , eu concordo plenamente.

    terça-feira, 21 de maio de 2019 14:12