Estou trabalhando com os programadores em uma solução de banco de dados. Eles querem adicionar uma coluna computada para imitar as chaves antigas para as consultas, procedimentos e sistemas mais antigos e indexá-la. As novas chaves serão GUIDS.
Para fazer isso, eles desejam criar uma função para a coluna computada que cria um valor e o mantém. Não vai deixá-los persistir na coluna. Eu não tenho nenhuma curiosidade sobre a ideia e também não consigo encontrar nenhuma informação na web sobre a técnica (é uma técnica?).
Estou pensando que eles precisam adicionar um gatilho em vez disso. Alguém tem alguma idéia?
A função será executada assim:
(SELECT [INT Identity field] FROM TABLE WHERE [GUID COLUMN] = @GUIDKEY
Ele retorna um campo INT Identity baseado no GUID.
Isso será executado em cada inserção em uma tabela relacionada. Portanto, se a Tabela Um tiver a chave primária, a tabela relacionada Dois será atualizada (usando o GUID passado) para obter a chave da Tabela um e inseri-la na tabela dois.
Ainda não entendo por que isso precisa ser uma coluna em uma tabela , muito menos uma persistente.
Por que não apenas criar uma função com valor de tabela que você aplica quando (e somente quando) a consulta realmente precisa dela? Como a chave antiga nunca será alterada, ela não precisa ser computada ou persistida de qualquer maneira.
Se você realmente deseja que a chave antiga viva em vários lugares (e parece que as pessoas que não deveriam tomar esse tipo de decisão já tomaram esse tipo de decisão), basta fazer a pesquisa em um gatilho e preenchê-lo no momento da gravação . Então é apenas uma coluna estática em uma tabela.
Eu ainda recomendo uma função com valor de tabela para facilitar isso, para que você possa escrever o gatilho de forma que ele lide com operações de várias linhas ... sem ter que escrever um loop ou chamar uma função de valor escalar sobre e novamente para cada linha.
Apenas para mostrar como essas coisas realmente são semelhantes (e questione seu desenvolvedor líder que "não gosta disso"):
Agora, se você tiver uma função com valor de tabela, o código é bastante semelhante, mas você descobrirá que o desempenho é muito melhor em operações de várias linhas e quase idêntico para operações de uma única linha.
Não sei por que você acha que precisa de uma função ou de uma coluna computada para fazer isso. Você pode simplesmente adicionar uma nova coluna à tabela com um valor padrão e indexá-la como quiser.
Já que você atualizou sua pergunta, vamos abordar que ideia realmente horrível é essa. Vou simplificar um pouco o exemplo.
Tentar persistir uma coluna computada com base em uma função escalar (mesmo uma determinística com SCHEMABINDING ) falhará se eles realizarem acesso a dados.
Nem você pode indexá-lo:
Você também terá muitos problemas porque a função executará linha por linha para recuperar dados e forçará todas as consultas na tabela a serem executadas em série .
Se você estiver modificando dados na tabela que a função faz referência e selecionando dados da tabela que chama a função na coluna computada, você pode acabar com alguns cenários de bloqueio realmente confusos em que a função é impedida de retornar dados para uma consulta em uma tabela aparentemente não relacionada.
Esta é uma má idéia ao redor. Aaron deu o que eu acho que é o melhor conselho em seu comentário:
Você pode ler sobre Colunas Computadas Persistentes em BOL e os Índices relacionados em Colunas Computadas .
Há restrições na expressão que você pode usar em uma coluna computada persistente. A expressão "deve ser determinística quando PERSISTED for especificado."
Se bem entendi, você tem:
t
.t
tem uma coluna guid, vamos chamá-la degc
.t.gc
para um valor de chave diferente de um tipo diferente, que é usado no código herdado. Vamos chamar a tabelalt
e a coluna de chave herdadalk
.lt.lk
aparecert
comot.lk
código legado que pode continuar usando-o.Eu investigaria usando uma visão.
t
, para algo comot_base
.t
que une e retornat_base
alt
coluna det_base
elt.lk
.O problema real
O problema que os desenvolvedores estão tentando resolver é um problema de migração bastante padrão, de um tipo de dados para um novo. Eles têm um novo problema que não foi previsto no momento em que o banco de dados foi originalmente projetado; ou seja, eles agora precisam sincronizar dados entre bancos de dados. Isso tende a ser um esforço caro, principalmente se os tipos de dados forem utilizados em muitos códigos. Procurar medidas de redução de custos não é totalmente irracional.
A solução deles
A matemática diz que não
Em primeiro lugar, é importante perceber que o problema é provavelmente matematicamente intratável. Um GUID ou UUID é apenas um número de 128 bits ou 16 bytes. O tamanho de uma
IDENTITY
coluna depende do tipo de dados usado, mas normalmente sãoINT
(32 bits, 4 bytes); às vezesBIGINT
(64 bits, 8 bytes) é usado. Não há uma maneira matemática de mapear totalmente o intervalo de GUIDs para o intervalo de INTs ou mesmo BIGINTs. É matematicamente possível se a coluna forDECIMAL(38,0)
, que é grande o suficiente, mas isso é altamente incomum.Praticidade
Mesmo que seja possível mapear GUIDs para o
DECIMAL
tipo, isso não significa que seja prático. Praticamente ninguém faz isso, então você terá que gastar tempo (=dinheiro) garantindo que o mapeamento funcione corretamente. Sua solução apresenta um risco não insignificante de criar bugs estranhos e difíceis de diagnosticar.Além disso, você não preservará os IDs existentes dos dados com sua solução. Isso pode quebrar quaisquer marcadores que os usuários finais tenham que incluam os IDs.
Finalmente, sua solução provavelmente estará enraizada . Não é uma boa prática por causa de todos os motivos acima, mas se eles conseguirem, é provável que eles não trabalhem para se afastar dele tão cedo porque é muito "fácil" continuar usando as chaves inteiras em todos os novos código.
Uma abordagem mais padrão
Uma abordagem relativamente padrão para introduzir a sincronização em um sistema existente é adicionar um novo ID exclusivo . Esse novo ID é colocado nos dados , além das chaves antigas existentes. Então as chaves substitutas não são sincronizadas.
Isso tem alguns benefícios importantes:
Há dois pequenos aborrecimentos com essa abordagem:
Ambos os problemas são gerenciáveis, porém, e são compensações razoáveis a serem feitas se mudar tudo para GUIDs agora for muito caro.
Também vale a pena notar que esta solução permitiu exatamente a consulta que eles estão pedindo para poder fazer.
Isso pode ser tarde demais para ajudá-lo agora, mas acho que é uma boa informação daqui para frente.