Quando o cliente nos baralha a cabeça - Ajuda em 3 situações

Heias.
Eu dei uma vista de olhos ao topico todo.
Como já foi dito aqui, eu gerava esse campo especial que tu queres através de um trigger sempre que se inserisse imóveis. E nunca o utilizaria como chave (mas convém ser indexado).
O problema da race condition é solucionável usando transactions. Podes usar stored procedures, não faças é isso fora da db porque não tens maneira de impedir race conditions e um agente ficar com duas casa com o nº 40 por exemplo.


So há uma coisa que não percebi bem. Que é o que acontece quando se apaga uma casa ou agente. Se apagares uma casa não faz sentido que, se o contador de casas desse agente estava no 41 quando fores inserir uma nova casa ele fique na mesma no 41 porque utilizaste o espaço deixado vazio pela casa que foi apagada. Penso que fará mais sentido pensar no nº de casa como um contador de todas as casa que o agente já teve e não de todas as casa que o agente actualmente tem.

Just my 2 cents.
 
Sem teres que alterar a estrutura das tuas tabelas, poderás criar uma view com:
Código:
CREATE VIEW codigos_imoveis AS
SELECT @id_imovel_agente := IF(@agencia = id_agencia AND @agente = id_agente, @id_imovel_agente + 1, 1) AS id_imovel_agente,
        CONCAT(CONCAT(CONCAT(CONCAT(id_agencia, '-'), id_agente), '-'), @id_imovel_agente) AS codigo,
        @agencia := id_agencia AS id_agencia,
        @agente := id_agente AS id_agente,
        id_imovel
FROM agencias_agentes_imoveis
Sendo que agencias_agentes_imoveis poderá ser uma outra view ou explicitas os inner joins que tinhas feito nesta propria view.

Para que os id_imovel_agente se mantenham coesos, não deverás apagar os imoveis. Em vez disso, cria uma tabela onde consideras os imoveis "removidos"
Código:
CREATE TABLE imoveis_inactivos (
    id_imovel INTEGER NOT NULL,
    PRIMARY KEY(id_imovel)
);

Para ver todos os imoveis "activos", basta usar qq coisa do género:
Código:
SELECT *
FROM imoveis
WHERE id_imovel NOT IN (SELECT id_imovel FROM imoveis_inactivos)

Usando a view:
Código:
SELECT *
FROM agencias_agentes_imoveis
WHERE id_imovel NOT IN (SELECT id_imovel FROM imoveis_inactivos)

Não tenho a informação da tua estrutura das tabelas e relações entre si, isto é só uma forma de mostrar uma possivel forma de dar a volta ao problema =)
 
Sem teres que alterar a estrutura das tuas tabelas, poderás criar uma view com:
Código:
CREATE VIEW codigos_imoveis AS
SELECT @id_imovel_agente := IF(@agencia = id_agencia AND @agente = id_agente, @id_imovel_agente + 1, 1) AS id_imovel_agente,
        CONCAT(CONCAT(CONCAT(CONCAT(id_agencia, '-'), id_agente), '-'), @id_imovel_agente) AS codigo,
        @agencia := id_agencia AS id_agencia,
        @agente := id_agente AS id_agente,
        id_imovel
FROM agencias_agentes_imoveis
Sendo que agencias_agentes_imoveis poderá ser uma outra view ou explicitas os inner joins que tinhas feito nesta propria view.

Para que os id_imovel_agente se mantenham coesos, não deverás apagar os imoveis. Em vez disso, cria uma tabela onde consideras os imoveis "removidos"
Código:
CREATE TABLE imoveis_inactivos (
    id_imovel INTEGER NOT NULL,
    PRIMARY KEY(id_imovel)
);

Para ver todos os imoveis "activos", basta usar qq coisa do género:
Código:
SELECT *
FROM imoveis
WHERE id_imovel NOT IN (SELECT id_imovel FROM imoveis_inactivos)

Usando a view:
Código:
SELECT *
FROM agencias_agentes_imoveis
WHERE id_imovel NOT IN (SELECT id_imovel FROM imoveis_inactivos)

Não tenho a informação da tua estrutura das tabelas e relações entre si, isto é só uma forma de mostrar uma possivel forma de dar a volta ao problema =)

para quê criar uma tabela à parte para imoveis inactivos se podes colocar um campo na tabela chamado activo e metes a S ou a N?

Depois é só restringir o select.

Select * from imoveis where activo = 'S';

Crias um campo na tabela chamado ordem que não faz parte da chave e cada vez que apagas(mudas o activo para 'N') um imovel reordenas esse campo com todos os imoveis activos do agente.

Ou na view mostras o Nº da linha e ordenas os registos por data de criação ( tens de ter neste campo a data e hora) crescente.
 
Última edição:
Nunca apliquei views. Como procedo para a sua aplicação?
Para os SELECTs, tratas como se fosse uma tabela. Para modificações, terás que obedecer a um conjunto de critérios (non-UNIONs, non-JOINS, etc)
Para criares:
Código:
CREATE VIEW codigos_imoveis AS
SELECT @id_imovel_agente := IF(@agencia = id_agencia AND @agente = id_agente, @id_imovel_agente + 1, 1) AS id_imovel_agente,
        CONCAT(CONCAT(CONCAT(CONCAT(id_agencia, '-'), id_agente), '-'), @id_imovel_agente) AS codigo,
        @agencia := id_agencia AS id_agencia,
        @agente := id_agente AS id_agente,
        id_imovel
FROM agencias_agentes_imoveis

para quê criar uma tabela à parte para imoveis inactivos se podes colocar um campo na tabela chamado activo e metes a S ou a N?

Depois é só restringir o select.

Select * from imoveis where activo = 'S';

Crias um campo na tabela chamado ordem que não faz parte da chave e cada vez que apagas(mudas o activo para 'N') um imovel reordenas esse campo com todos os imoveis activos do agente.

Ou na view mostras o Nº da linha e ordenas os registos por data de criação ( tens de ter neste campo a data e hora) crescente.
Ambas as soluções são validas, e uma será preferivel à outra dependendo da situação (a nivel de performance).

Em ultimo caso, prefiro criar uma tabela extra ao acrescentar uma simples flag. Se um dia precisares de adicionar mais informação relacionada com os inactivos, deixas de ter a tua tabela na forma normal Boyce–Codd.
(exemplo: quando é que o imovel ficou inactivo, quem o "desactivou", etc)
 
No meu trabalho para cada projecto em que se apaga um registo tivesse uma duplicação de tabelas tinhamos a BD atolhada de lixo.

Podes sempre colocar 2 campos na tabela principal com cod_utilizador_alt ( código do utilizador que efectuou a alteração) e data_alteração geridos por triggers on change que actulizam estes 2 campos.

e se necessário crias uma tabela de histórico tb gerida por triggers on change da tabela principal onde guardas os valores antigos e os valores novos do registo alterado.

deixa-me fazer-te uma pergunta, já alguma vez programás-te para um cliente? ou tiraste um curso de programação dakeles bué basicos que andam prá í e andas a brincar aos programadores?

desculpa ser tão sêco mas é o que parece, não me leves a mal.
 
Última edição:
A questão é que nunca usei transactions, nem triger, nem SP e tenho alguma dificuldade nestes aspectos. Poderão indicar material de estudo sobre os aspectos que falaste.

O que são as transactions?

Não, a ideia é mesmo manter, se apagar não fica no 41 já irá ser 42. Então por exemplo aqui com a função MAX não poderia resolver?

Obrigado pelos 2 cents, pois ajudaram a esclarecer algumas confusões que estava a fazer. Obrigado ;)

Heias.
Eu dei uma vista de olhos ao topico todo.
Como já foi dito aqui, eu gerava esse campo especial que tu queres através de um trigger sempre que se inserisse imóveis. E nunca o utilizaria como chave (mas convém ser indexado).
O problema da race condition é solucionável usando transactions. Podes usar stored procedures, não faças é isso fora da db porque não tens maneira de impedir race conditions e um agente ficar com duas casa com o nº 40 por exemplo.


So há uma coisa que não percebi bem. Que é o que acontece quando se apaga uma casa ou agente. Se apagares uma casa não faz sentido que, se o contador de casas desse agente estava no 41 quando fores inserir uma nova casa ele fique na mesma no 41 porque utilizaste o espaço deixado vazio pela casa que foi apagada. Penso que fará mais sentido pensar no nº de casa como um contador de todas as casa que o agente já teve e não de todas as casa que o agente actualmente tem.

Just my 2 cents.
 
Mas eu tenho um campo na tabela chamado estado! Os estados possíveis são: Activo, Desactivo, Vendido, Reservado.

E também tenho o campo data_insercao!

Com esse Select vou seleccionar os imóveis activos, eu tenho isso! Não é essa a minha dúvida... Acho que não percebeste bem a minh dúvida ou fui eu que não percebi.

Quero é um novo campo onde "reinicie" o id de imóvel do agente, isto é: Não lhe mostrar o ID do imóvel, mas sim um número calculado na altura da inserção que corresponde ao que o se quer (e o que se quer é um número de ordem do imóvel por agência e agente). Secalhar antes de inserir, verificar qual é o número máximo existente daquela combinação de agente e agência, somando um, e guardo junto com o registo...
Talvez por aqui...


para quê criar uma tabela à parte para imoveis inactivos se podes colocar um campo na tabela chamado activo e metes a S ou a N?

Depois é só restringir o select.

Select * from imoveis where activo = 'S';

Crias um campo na tabela chamado ordem que não faz parte da chave e cada vez que apagas(mudas o activo para 'N') um imovel reordenas esse campo com todos os imoveis activos do agente.

Ou na view mostras o Nº da linha e ordenas os registos por data de criação ( tens de ter neste campo a data e hora) crescente.
 
A ideia da tabela extra também me parece viável que teria relação muitos para muitos correcto?

Só que não me recordava como obter o id do último registo auto increment de uma inserção numa dada tabela mas agora lembrei-me que posso sempre utilizar o função mysql_insert_id()...

Para os SELECTs, tratas como se fosse uma tabela. Para modificações, terás que obedecer a um conjunto de critérios (non-UNIONs, non-JOINS, etc)
Para criares:
Código:
CREATE VIEW codigos_imoveis AS
SELECT @id_imovel_agente := IF(@agencia = id_agencia AND @agente = id_agente, @id_imovel_agente + 1, 1) AS id_imovel_agente,
        CONCAT(CONCAT(CONCAT(CONCAT(id_agencia, '-'), id_agente), '-'), @id_imovel_agente) AS codigo,
        @agencia := id_agencia AS id_agencia,
        @agente := id_agente AS id_agente,
        id_imovel
FROM agencias_agentes_imoveis


Ambas as soluções são validas, e uma será preferivel à outra dependendo da situação (a nivel de performance).

Em ultimo caso, prefiro criar uma tabela extra ao acrescentar uma simples flag. Se um dia precisares de adicionar mais informação relacionada com os inactivos, deixas de ter a tua tabela na forma normal Boyce–Codd.
(exemplo: quando é que o imovel ficou inactivo, quem o "desactivou", etc)
 
Exactamente.

Novamente, eu tenho esses 2 campos, o id do user que faz o registo/alteração e a data_insercao que actualiza caso for actualizada a informação. Apenas não está a ser gerida por triggers.

Sim já programei não para um cliente, mas sim para vários. Apenas não tive nenhum projecto com a extensão com que este se aplica. Mas isso é bom é sinal que se pode evoluir cada vez mais. Muito mais que isso, tenho curso sim e não é básico, a questão é que é tudo teoria e pouca prática. Eu conheço os conceitos mas nunca os apliquei na prática, naturalmente que vão surgindo dúvidas.
Não levo ninguém a mal, são as críticas e desde que sejam construtivas que são óptimas para evoluirmos, é sempre bom contarmos com outras opiniões e gosto de discutir ideias. O "problema" é que estou a fazer confusão com isto das referências e como disse é muita teoria e pouca prática e faço sistemas de CRUD, tudo o que vai além disso é um desafio. Por isso as dúvidas com views, SP, triggers. Também sei que existem o cursores, por exemplo, mas nunca apliquei na prática.

Gostava de optar por uma solução viável e para isso precisava da vossa ajuda/críticas/ideias/sugestões/concelhos. É tudo bem-vindo.

Obrigado pela vossa ajuda e colaboração.


No meu trabalho para cada projecto em que se apaga um registo tivesse uma duplicação de tabelas tinhamos a BD atolhada de lixo.

Podes sempre colocar 2 campos na tabela principal com cod_utilizador_alt ( código do utilizador que efectuou a alteração) e data_alteração geridos por triggers on change que actulizam estes 2 campos.

e se necessário crias uma tabela de histórico tb gerida por triggers on change da tabela principal onde guardas os valores antigos e os valores novos do registo alterado.

deixa-me fazer-te uma pergunta, já alguma vez programás-te para um cliente? ou tiraste um curso de programação dakeles bué basicos que andam prá í e andas a brincar aos programadores?

desculpa ser tão sêco mas é o que parece, não me leves a mal.
 
Acho que o teu cliente tb não percebe grande coisa de Dados, BD e afins. um ID uma chave não se muda.

cabe-te a ti arranjar uma solução que lhe resolva o problema e não te traga problemas, se é que me entendes.

Era como mudares a matricula de cada carro que vendesses um ID é um identificador único uma chave que pode ser composta por um ou mais campos, se algum desses campos não for unico não deve fazer parte da chave, não podes a cada vez que apagas, ou vendes um imovel mudar os ids de todos os imóveis que tens.

Esse teu cliente anda muito baralhado, imagina que alguem que fazer uma reclamação acerca dum imovel que foi vendido, que passou a chamar-se de outra maneira como é que tu o identificas?

ou que o imovel F passou a ser C porque venderam 2 imoveis, percebes????
 
Esse teu cliente anda muito baralhado, imagina que alguem que fazer uma reclamação acerca dum imovel que foi vendido, que passou a chamar-se de outra maneira como é que tu o identificas?
A solução que encontrei para um problema parecido (sempre que houver uma alteração num registo deve preservar o actual e criar um novo, para se ter histórico das alterações que o registo original vai sofrendo ao longo do tempo) foi criar um campo na tabela que recebe sempre o id do registo original (mesmo quando o original é ainda único). Sempre que é preciso ver as alterações do circuito faço uma busca pelo id original no respectivo campo.
 
A solução que encontrei para um problema parecido (sempre que houver uma alteração num registo deve preservar o actual e criar um novo, para se ter histórico das alterações que o registo original vai sofrendo ao longo do tempo) foi criar um campo na tabela que recebe sempre o id do registo original (mesmo quando o original é ainda único). Sempre que é preciso ver as alterações do circuito faço uma busca pelo id original no respectivo campo.

O problema aqui é que podem mudar isso vezes sem conta, de cada vez que desaparece um imovel todos os outros de alteram é de loucos, isso não faz sentido nenhum, o tipo da imobiliária é um inventor dos grandes.
 
Percebo perfeitamente.

Pois não percebe não. Exactamente eu sei que me cabe a mim, apenas quis trocar ideias com vocês, tipo Brainstorming para perceber como daria facilmente a volta à situação, contando com a vossa ajuda e experiência.

Mas o imóvel F não vai passar a ser o C, apenas tenho que reiniciar os ids, pensei em fazer isso noutro campo tal como disseram. Ou seja como faço outro campo sem ser o id, mas do género que fosse também autoincrement... Mas como faço sem usar chaves compostas, por exemplo?

Acho que o teu cliente tb não percebe grande coisa de Dados, BD e afins. um ID uma chave não se muda.

cabe-te a ti arranjar uma solução que lhe resolva o problema e não te traga problemas, se é que me entendes.

Era como mudares a matricula de cada carro que vendesses um ID é um identificador único uma chave que pode ser composta por um ou mais campos, se algum desses campos não for unico não deve fazer parte da chave, não podes a cada vez que apagas, ou vendes um imovel mudar os ids de todos os imóveis que tens.

Esse teu cliente anda muito baralhado, imagina que alguem que fazer uma reclamação acerca dum imovel que foi vendido, que passou a chamar-se de outra maneira como é que tu o identificas?

ou que o imovel F passou a ser C porque venderam 2 imoveis, percebes????
 
Sim o id original irei sempre manter. A questão agora é optar pela melhor via, utilizando ou outra tabela ou outro campo... com esta história eu também acabei baralhado e já fiz e refiz tanta coisa que cheguei a um ponto que estou a dar em maluco com isto.

A solução que encontrei para um problema parecido (sempre que houver uma alteração num registo deve preservar o actual e criar um novo, para se ter histórico das alterações que o registo original vai sofrendo ao longo do tempo) foi criar um campo na tabela que recebe sempre o id do registo original (mesmo quando o original é ainda único). Sempre que é preciso ver as alterações do circuito faço uma busca pelo id original no respectivo campo.
 
Podes crer!

Mais uma vez e peço desculpa por gerar tanta confusão, mas que me aconselham a proceder neste caso?

O meu muito obrigado pela vossa atenção e ajuda.

O problema aqui é que podem mudar isso vezes sem conta, de cada vez que desaparece um imovel todos os outros de alteram é de loucos, isso não faz sentido nenhum, o tipo da imobiliária é um inventor dos grandes.
 
Crias um campo na tabela chamado ordem que não faz parte da chave e cada vez que apagas(mudas o activo para 'N') um imovel reordenas esse campo com todos os imoveis activos do agente.
A ideia é permanecer com o mesmo código desde a sua criação. Este código é, em parte, derivado de chaves primárias (tal como exemplifiquei, no meu caso seria uma chave composta num tabela intermediaria para relações N:N)
A outra parte é dependente do agente, e é calculada para o agente (daí o uso da view para gerar esta parte do código).

Ou na view mostras o Nº da linha e ordenas os registos por data de criação ( tens de ter neste campo a data e hora) crescente.
Já devias saber que views não podem ser ordenadas. No caso que exemplifiquei, será naturalmente ordenada pelas chaves compostas.

Acho que o teu cliente tb não percebe grande coisa de Dados, BD e afins. um ID uma chave não se muda.

cabe-te a ti arranjar uma solução que lhe resolva o problema e não te traga problemas, se é que me entendes.
O cliente certamente que saberá vender imoveis, e Dados, BD e afins não lhe tiram o sono nem a vontade de ter as coisas como ele deseja.
Quanto à solução, o user veio pedir opiniões... está explicito no titulo tópico, e não é preciso que lhe relembrem...


Concluindo, ainda não vi razão para o user experimentar o codigo sql que postei e expor duvidas relacionadas com esse código.
Ou então, ainda não vi outra solução prática e exemplificada em todo o resto desta thread...

Ajudem-se a vocês proprios e não percam tempo com bitaites.
 
O problema aqui é que podem mudar isso vezes sem conta, de cada vez que desaparece um imovel todos os outros de alteram é de loucos, isso não faz sentido nenhum, o tipo da imobiliária é um inventor dos grandes.

Sim o id original irei sempre manter. A questão agora é optar pela melhor via, utilizando ou outra tabela ou outro campo... com esta história eu também acabei baralhado e já fiz e refiz tanta coisa que cheguei a um ponto que estou a dar em maluco com isto.

Vou dar um exemplo do que escrevi:

suponhamos que o inserimos um novo registo com o id=75, este id é também guardado no campo id_original=75, mais tarde se este imóvel passar para outro vendedor, em vez de alterar o registo, cria uma copia deste, que pode, p.ex, ter o id=123, no entanto o id_original mantém-se o 75, faz as alterações que tem de fazer neste novo id (123). Se mais tarde este imóvel voltar a sofrer alguma alteração, será sobre o id 123, cria uma cópia do registo 123, no entanto o id_original continuará a ser sempre 75. Deste modo consegue sempre saber as alterações de um determinado imóvel.

Esse teu cliente anda muito baralhado, imagina que alguem que fazer uma reclamação acerca dum imovel que foi vendido, que passou a chamar-se de outra maneira como é que tu o identificas?
Voltando a este problema, se um cliente fizer uma reclamação, se for utilizado o método que exemplifiquei (nunca alterar um registo, mas criar uma cópia), consegue sempre chegar ao registo da reclamação.
 
Back
Topo