Array
(
)

Trigger para ajustar campo identity na virada de ano

Rounilo
   - 08 nov 2004

Senhores tenho uma tabela de nome CERTSTOP com um campo
definido como :
codigo integer identity(2004000,1) not null

e pretendo criar um Trigger para, quando da virada do ano, setar o identity para 2005000,1.

Estou tentando com a codificação abaixo e estah dando erro.
Qual eh o erro ?
Poderei fazer de outra forma ??

***********************************
Create TRIGGER TRIG_CERTSTOP
ON CERTSTOP
FOR INSERT
AS
SELECT IDENT_CURRENT(´CERTSTOP´)
IF (DATEPART(YYYY,GETDATE()) >
IDENT_CURRENT
BEGIN
DBCC CHECKIDENT(´CERTSTOP´,RESEED,2005000)
END
*************************************************

Melhor seria se pudesse colocar o novo ano obtido na função datepar
acrescentado de + ´000´.

Agradeço sugestões.
Rounilo

Marcus.magalhaes
   - 09 nov 2004

Bom dia Rounilo.

Cara, criar uma trigger para fazer isso não acho uma boa idéia porque vc irá causar um erro de duplicate key. pq a cada insert seu ponteiro será setado para o mesmo valor inicial

Acredito q a melhor saida seja ou vc rodar o DBCC na mão no dia 31/12 qdo vc souber q ninguém mais vai ser cadastrado ou efetuar esta execução via job schedulado para às 12:00AM do dia 01/01/2005.

Att,

Rounilo
   - 10 nov 2004

Marcus, vou considear suas duas sugestões. Entretanto o problema é que terei que ter esta preocupação todo final de ano.

Uma coisa que não entendi na sua resposta foi a suposta ocorrência de duplicidade de chave. Penso que o que o levou a supor duplicidade foi o fato não ter informado que o número de inclusões, de novos registros, será bem menor do que 999 inclusões; o que sempre fará com que os quatros primeiros dígitos não sejam alterados, representando portanto, o ano.

O que pretendo é incluir no corpo da trigger, uma consulta para obter, da data do dia (GETDATE) o campo ano (yyyy) e acrescentar a este ´000´ e comparar este valor com o campo identity.
O que vai ocorrer no dia a dia:
- Imaginemos que fosse feita uma inclusão hoje e o valor do identity fosse 2004125.
Este valor do identity (2004125) seria comparado com o obtido na getdate acrescentado de 000 que seria ´2004000´. Por ser MAIOR não seria executado o comando DBCC, fazendo com que o sistema fizesse o incremento normal do identity para 2004126. OK ?

- Imaginemos agora um insert feito no dia 01/01/2005 com o valor do identity sendo, por exemplo, 2004789.

O valor que obteria pela funcão getdate e acrescido dos tres zeros seria 2005000, que comparado com 2004789 do identity, resulatia em MENOR. Por ser MENOR seria executado o comando DBCC, alterando o Identity para ´2005001,1´.
Nas próximas inclusões o resultado da comparação seria sempre MAIOR, OK ?

A lógica me parece correta. O que não sei é como codifica-la em uma trigger.

Peço que vc analise este novo comentário.
Obrigado
Rounilo

Marcus.magalhaes
   - 10 nov 2004

Bom dia.

Ok, entendi o ponto da duplicidade, até aí blz.

Mas a lógica do getdate() pegando o ano + ´000´ poderia ser montanda num job q seria agendado para rodar somente em 1o. de janeiro e não a cada insert, o q causaria lentidão no insert. Overhead desnecessário.

Att,

Rounilo
   - 10 nov 2004

Marcus, concordo sua sugestão. Realmente nos parece melhor por ocasionar menor overhead no sistema.

Marcus, senão for pedir demais gostaria que vc me esclarecesse dois pontos:
Posso eu, responsável pela aplicação e pela Base de dados envolvida, implementar este JOB ou terá que ser implementada por um DBA?

Qual o erro na codificação da Trigger ? Será bom conhece-lo para evitar futuros problemas.

Sds

Marcus.magalhaes
   - 10 nov 2004

Boa tarde Rounilo.

Respondendo às suas questões :

1) O ideal é que um DBA faça todos os agendamentos, pois só ele pode ter a senha de sa, ou pelo menos deveria. E em ambientes de produção, apesar do DBA não ser o dono da base, ele é a pessoa responsável pela sua manutenção/administração.

2) Aqui está seu código corrigido :
Create Table CERTSTOP
(
Col1IntIdentity(1, 1)NOT NULL,
Col2VarChar(10)NOT NULL
)
GO

Create TRIGGER TRIG_CERTSTOP ON CERTSTOP FOR INSERT
AS
Begin
IF Convert(Int, Convert(VarChar, DATEPART(YYYY,GETDATE())) + ´000´) > IDENT_CURRENT(´CERTSTOP´)
BEGIN
DBCC CHECKIDENT(´CERTSTOP´,RESEED,2005000)
END
End
GO

DBCC CHECKIDENT(´CERTSTOP´,RESEED,2003000)
GO

Insert Into certstop (col2) values (´teste1´)
Insert Into certstop (col2) values (´teste2´)
Insert Into certstop (col2) values (´teste3´)
Insert Into certstop (col2) values (´teste4´)

Select *
From certstop

Drop table CERTSTOP
GO

Outra coisa, como isto seria uma Trigger e este tipo de objeto age somente depois da ação ter sido efetivada, o 1o. registro que fizesse com que seu if fosse verdadeiro não seria afetado, portanto não teria um novo código. Observe isso no exemple que estou te mandando acima, a primeira linha NUNCA será 2004xxx.

PS.: eu setei para 2003000 o identity inicial para que o teste funcionasse.

Att,