none
Relacionamento entre tabelas RRS feed

  • Pergunta

  • Pessoal estou com uma pequena dúvida e estou pedindo um help!!

    Tenho que relacionar um campo de uma tabela com outro que não é chave primaria, como faço? Vou postar o código:

    create table tbCliente
    (
    idCliente int primary key not null,
    nome varchar(80) not null,
    cpf char(14) not null,
    telefone char(13),
    endereco varchar(max),
    bairro varchar(100),
    cidade varchar(100),
    estado varchar(100),
    dataDia varchar(50),
    cadastradoPor varchar(50)
    )

    ------------------------------------

    create table tbOrdemServico
    (
    idOrdem int primary key not null,
    idCliente int not null,
    idServico int not null,
    dataDia varchar(50),
    cadastradorPor varchar(50),
    /*Chave estrangeira idCliente*/
    CONSTRAINT FK_tbOrdemServico_tbCliente_idCliente FOREIGN KEY(idCliente) REFERENCES tbCliente(idCliente),
    /*Chave estrangeira idServico*/
    CONSTRAINT FK_tbOrdemServico_tbServico_idServico FOREIGN KEY(idServico) REFERENCES tbServico(idServico)
    )

    Queria saber se posso adicionar um campo nome na tabela de baixo usando os dados da promeira tabela, como o campo "idCliente" que usa o código da primeira tabela. Sei que o código é chave primaria na primeira e chave extrageira na segunda, eis aí o "X" da questão, como criar o campo nome na tabela de baixo usando os nomes da tabela de cima?

    Pessoal desde já fico muito agradecido

    JAVF

    domingo, 4 de novembro de 2012 13:33

Respostas

  • Normalmente esse tipo de redundância é desnecessária, pois você resolve isso facilmente com um Join entre as tabelas. Porém, às vezes ela se faz necessária pela vantagem do ganho de desempenho para buscar a informação.

    Ou seja, se você tem diversas consultas nas quais precisa buscar o nome do cliente e se um Join "custa" muito caro para o SQL, devido ao tamanho das tabelas, "pode ser" que seja mais vantajoso replicar a informação. Ainda que você tenha índices que possa te favorecer nestas tabelas, realmente existem casos onde a redundância de informações acaba sendo mais útil, devido à alguma estratégia.

    Assim sendo, saiba que uma chave estrangeira pode ser criada não somente contra uma chave primária, mas também contra um índice único. O fato é que uma chave estrangeira só pode ser criada contra uma tabela que garanta que aquela coluna que fará parte da referência é única, isto é, não se repete.

    Dessa forma, o código abaixo poderia ser utilizado:

    create table tbCliente
    (
    idCliente int primary key not null,
    nome varchar(80) not null,
    cpf char(14) not null,
    telefone char(13),
    endereco varchar(max),
    bairro varchar(100),
    cidade varchar(100),
    estado varchar(100),
    dataDia varchar(50),
    cadastradoPor varchar(50),
    Constraint UQ_Nome unique (nome)
    )
    ------------------------------------
    create table tbOrdemServico
    (
    idOrdem int primary key not null,
    idCliente int not null,
    NomeCliente varchar(80) not null,
    idServico int not null,
    dataDia varchar(50),
    cadastradorPor varchar(50),
    /*Chave estrangeira idCliente*/
    CONSTRAINT FK_tbOrdemServico_tbCliente_idCliente FOREIGN KEY(idCliente) REFERENCES tbCliente(idCliente),
    CONSTRAINT FK_tbOrdemServico_tbCliente_NmCliente FOREIGN KEY(NomeCliente) REFERENCES tbCliente(nome)
    )

    Veja que é criado um índice único para o nome do cliente e, na tabela de ordem serviço, é criada uma foreign key contra a coluna nome.

    Isto poderia ser utilizado, mas não deve: se você fizer isso não poderá mais ter clientes com mesmo nome. E sabemos que muitas pessoas possuem exatamente o mesmo nome. Então não dá pra criarmos uma regra na qual o nome tem que ser único.

    Com isso, o único recurso que você tem em mãos é mudar a chave primária da tabela Clientes, para que seja composta tanto pelo Id quanto pelo nome. Porém, isso pode atrapalhar o resto da sua vida, pois em toda tabela que você precisar criar uma ligação com a tabela Clientes, terá que criar uma coluna nome em tal tabela e usar os dois campos (Id e nome) para fazer a referência. Ou seja, pode ser um tiro no pé.

    Seria algo como isso:

    create table tbCliente
    (
    idCliente int not null,
    nome varchar(80) not null,
    cpf char(14) not null,
    telefone char(13),
    endereco varchar(max),
    bairro varchar(100),
    cidade varchar(100),
    estado varchar(100),
    dataDia varchar(50),
    cadastradoPor varchar(50),
    Constraint PK_Cliente Primary Key (idCliente,nome)
    )
    ------------------------------------
    create table tbOrdemServico
    (
    idOrdem int primary key not null,
    idCliente int not null,
    NomeCliente varchar(80) not null,
    idServico int not null,
    dataDia varchar(50),
    cadastradorPor varchar(50),
    /*Chave estrangeira idCliente*/
    CONSTRAINT FK_tbOrdemServico_tbCliente_idCliente FOREIGN KEY(idCliente,NomeCliente) REFERENCES tbCliente(idCliente,nome)
    )

    Enfim, acho que não deve fazer isso, a menos que tenha um motivo muito sólido.

    Acho que não deve nem ter o nome do cliente na tabela de ordem de serviço, mas se for realmente necessário e se quiser garantir a consistência das informações, talvez precise criar uma trigger para isso.


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 5 de novembro de 2012 10:42
    Moderador

Todas as Respostas

  • JAVF,

    Para que exatamente vc precisa desse campo?  Você já possui o IdCliente na tabela tbOrdemServico, dependendo do motivo você consegue resolver com a criação de uma view com um join entre essas duas tabelas. Nesse seu caso, você só iria gerar redundância de informações. 

    Abs,

    segunda-feira, 5 de novembro de 2012 10:23
  • Normalmente esse tipo de redundância é desnecessária, pois você resolve isso facilmente com um Join entre as tabelas. Porém, às vezes ela se faz necessária pela vantagem do ganho de desempenho para buscar a informação.

    Ou seja, se você tem diversas consultas nas quais precisa buscar o nome do cliente e se um Join "custa" muito caro para o SQL, devido ao tamanho das tabelas, "pode ser" que seja mais vantajoso replicar a informação. Ainda que você tenha índices que possa te favorecer nestas tabelas, realmente existem casos onde a redundância de informações acaba sendo mais útil, devido à alguma estratégia.

    Assim sendo, saiba que uma chave estrangeira pode ser criada não somente contra uma chave primária, mas também contra um índice único. O fato é que uma chave estrangeira só pode ser criada contra uma tabela que garanta que aquela coluna que fará parte da referência é única, isto é, não se repete.

    Dessa forma, o código abaixo poderia ser utilizado:

    create table tbCliente
    (
    idCliente int primary key not null,
    nome varchar(80) not null,
    cpf char(14) not null,
    telefone char(13),
    endereco varchar(max),
    bairro varchar(100),
    cidade varchar(100),
    estado varchar(100),
    dataDia varchar(50),
    cadastradoPor varchar(50),
    Constraint UQ_Nome unique (nome)
    )
    ------------------------------------
    create table tbOrdemServico
    (
    idOrdem int primary key not null,
    idCliente int not null,
    NomeCliente varchar(80) not null,
    idServico int not null,
    dataDia varchar(50),
    cadastradorPor varchar(50),
    /*Chave estrangeira idCliente*/
    CONSTRAINT FK_tbOrdemServico_tbCliente_idCliente FOREIGN KEY(idCliente) REFERENCES tbCliente(idCliente),
    CONSTRAINT FK_tbOrdemServico_tbCliente_NmCliente FOREIGN KEY(NomeCliente) REFERENCES tbCliente(nome)
    )

    Veja que é criado um índice único para o nome do cliente e, na tabela de ordem serviço, é criada uma foreign key contra a coluna nome.

    Isto poderia ser utilizado, mas não deve: se você fizer isso não poderá mais ter clientes com mesmo nome. E sabemos que muitas pessoas possuem exatamente o mesmo nome. Então não dá pra criarmos uma regra na qual o nome tem que ser único.

    Com isso, o único recurso que você tem em mãos é mudar a chave primária da tabela Clientes, para que seja composta tanto pelo Id quanto pelo nome. Porém, isso pode atrapalhar o resto da sua vida, pois em toda tabela que você precisar criar uma ligação com a tabela Clientes, terá que criar uma coluna nome em tal tabela e usar os dois campos (Id e nome) para fazer a referência. Ou seja, pode ser um tiro no pé.

    Seria algo como isso:

    create table tbCliente
    (
    idCliente int not null,
    nome varchar(80) not null,
    cpf char(14) not null,
    telefone char(13),
    endereco varchar(max),
    bairro varchar(100),
    cidade varchar(100),
    estado varchar(100),
    dataDia varchar(50),
    cadastradoPor varchar(50),
    Constraint PK_Cliente Primary Key (idCliente,nome)
    )
    ------------------------------------
    create table tbOrdemServico
    (
    idOrdem int primary key not null,
    idCliente int not null,
    NomeCliente varchar(80) not null,
    idServico int not null,
    dataDia varchar(50),
    cadastradorPor varchar(50),
    /*Chave estrangeira idCliente*/
    CONSTRAINT FK_tbOrdemServico_tbCliente_idCliente FOREIGN KEY(idCliente,NomeCliente) REFERENCES tbCliente(idCliente,nome)
    )

    Enfim, acho que não deve fazer isso, a menos que tenha um motivo muito sólido.

    Acho que não deve nem ter o nome do cliente na tabela de ordem de serviço, mas se for realmente necessário e se quiser garantir a consistência das informações, talvez precise criar uma trigger para isso.


    Roberson Ferreira - Database Developer
    Acesse: www.robersonferreira.com.br
    Email: contato@robersonferreira.com.br

    Se esta sugestão for útil, por favor, classifique-a como útil.
    Se ela lhe ajudar a resolver o problema, por favor, marque-a como Resposta.

    segunda-feira, 5 de novembro de 2012 10:42
    Moderador