Procurar um campo numa tabela

Sem Comentários

Por vezes quando estamos a desenvolver uma alteração numa aplicação já existente, há a necessidade de acrescentar, alterar ou até mesmo apagar colunas de uma tabela. Geralmente isso faz-se no arranque da aplicação numa qualquer rotina de actualização. A questão é, como controlamos se essa alteração já foi feita ou não na base de dados?
Há várias formas é certo mas pessoalmente discordo, sou contra, e abomino coisas como:

  1. Guardar numa tabela da base de dados uma flag boolean que indique se essa actualização já foi feita ou não (e quem controla se a flag já foi criada ou não?);
  2. Colocar um qualquer controlo para o caso de dar erro ao tentar fazer a actualização, o programa não crachar (e se o erro não for por já ter sido feita a alteração mas sim por um outro motivo qualquer?);
  3. Fazer update a um campo numa tabela que supostamente irá guardar a “versão da actualização”;

Pense comigo:
Temos tabelas e campos que são objectos numa base de dados. Estes objectos estão referenciados algures, certo? Estão nas tabelas “sysobjects” e “syscolumns”, não é?

Então porque não fazemos assim:

SELECT * FROM syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
WHERE syscolumns.name = 'campo' AND sysobjects.name = 'tabela'

Se devolver algum registo é porque o campo existe e assim ficamos a saber que se pretendemos apagar este campo o drop não irá dar erro, se não devolver é porque não existe e é seguro criá-lo!

Ou por exemplo, se quisermos só alterar um campo que era smalldatetime e agora queremos que seja datetime:

SELECT * FROM syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
WHERE syscolumns.name = 'campo' AND sysobjects.name = 'tabela' AND syscolumns.xtype = 61

Se devolver algum registo é porque o campo já está como datetime e não é preciso fazer mais nada, se não devolver nenhum registo é porque o campo ainda não é datetime e então podemos fazer o nosso alter column!

Ok, eu sei que isto obriga a que seja feita uma instrução para cada alteração enquanto que os outros métodos controlam-nas em “packs” mas um select não é assim tão lento quanto isso e além do mais podemos reduzir tudo (select + add / alter / drop) a uma só instrução:

IF NOT EXISTS
(SELECT autoval FROM syscolumns
LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id
WHERE syscolumns.name = 'campo' AND sysobjects.name = 'tabela')
ALTER TABLE tabela ADD campo tinyint NOT NULL DEFAULT 1

Se conhecer algum método mais simples e mais eficaz do que este, por favor diga-me.

Até lá irei continuar a usá-lo.

Leave a Reply