Usuário com melhor resposta
Problema em retornar o ID(PK) da tabela

Pergunta
-
Pessoal, preciso de ajuda
Eu tenho essa tabela
Tenho esse script de limpeza de base
EXEC sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'; GO EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'; GO EXEC sp_MSForEachTable 'IF OBJECTPROPERTY(object_id(''?''), ''TableHasForeignRef'') = 1 DELETE FROM ? else TRUNCATE TABLE ?'; GO EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'; GO EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'; GO EXEC sp_MSForEachTable 'IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1 DBCC CHECKIDENT (''?'', RESEED, 0)';
Estou construindo esse script pra inserir na tabela
USE DB_GrandesFaturadores GO BEGIN TRY DECLARE @TempoInicio datetime, @TempoFim datetime SET @TempoInicio = (SELECT GETDATE() TempoInicio) BEGIN TRANSACTION ImportacaoCadastro DECLARE @CnpjFornecedor VARCHAR(50), @SiglaFornecedor VARCHAR(50), @Email VARCHAR(50), @Telefone VARCHAR(50), @UtilidadeFornecida VARCHAR(50), @contato VARCHAR(50), @DataInclusao VARCHAR(50), @LoginInclusao VARCHAR(50), @DataAtualizacao DATETIME, @LoginAtualizacao VARCHAR(50), @DiaVencimento int, @UnidadeMedida VARCHAR(50), @TokenAcesso VARCHAR(50), @IdFornecedorTipo int DECLARE FornecedorAntigo CURSOR FOR SELECT CnpjFornecedor, SiglaFornecedor, Email, Telefone, UtilidadeFornecida, contato, DataInclusao, CASE WHEN LoginInclusao IS NULL THEN 'N/C' ELSE LoginInclusao END, DataAtualizacao, LoginAtualizacao, DiaVencimento, UnidadeMedida, TokenAcesso FROM SRVDES01.UTILIDADEPUBLICA_PRD_20151103.dbo.Fornecedor OPEN FornecedorAntigo FETCH NEXT FROM FornecedorAntigo INTO @CnpjFornecedor, @SiglaFornecedor, @Email, @Telefone, @UtilidadeFornecida, @contato, @DataInclusao, @LoginInclusao, @DataAtualizacao, @LoginAtualizacao, @DiaVencimento, @UnidadeMedida, @TokenAcesso WHILE @@FETCH_STATUS = 0 BEGIN IF NOT EXISTS (SELECT UnidadeMedida FROM DB_GrandesFaturadores..FornecedorTipo WHERE UnidadeMedida = @UnidadeMedida) BEGIN INSERT INTO DB_GrandesFaturadores..FornecedorTipo (Nome, UnidadeMedida) VALUES (@UtilidadeFornecida, @UnidadeMedida) SET @IdFornecedorTipo = (SELECT IDENT_CURRENT ('DB_GrandesFaturadores.dbo.FornecedorTipo')); END ELSE BEGIN SET @IdFornecedorTipo = (SELECT Id FROM DB_GrandesFaturadores..FornecedorTipo WHERE UnidadeMedida = @UnidadeMedida) END INSERT INTO DB_GrandesFaturadores..Fornecedor (CnpjFornecedor, IdFornecedorTipo, Nome, NomeAbreviado, DiaVencimento, TokenAcesso, DataCriacao, LoginCriacao, DataAtualizacao, LoginAtualizacao) VALUES (@CnpjFornecedor, @IdFornecedorTipo, @SiglaFornecedor, 'N/C', @DiaVencimento, @TokenAcesso, @DataInclusao, @LoginInclusao, @DataAtualizacao, @LoginAtualizacao) --================================================================================================== --Problema para retorna o ID correto declare @idfornecedorcontatoANTES int = (SELECT IDENT_CURRENT ('DB_GrandesFaturadores.dbo.FornecedorContato')) print 'Id FornecedorContato ANTES: ' + CAST(@idfornecedorcontatoANTES as VARCHAR(50)) INSERT INTO DB_GrandesFaturadores..FornecedorContato (CnpjFornecedor, Nome, Email, Telefone) VALUES (@CnpjFornecedor, @contato, @Email, @Telefone) print 'inserido FornecedorContato' declare @idfornecedorcontatoDepois int = (SELECT IDENT_CURRENT ('DB_GrandesFaturadores.dbo.FornecedorContato')) print 'IdFornecedorContato Depois: ' + CAST(@idfornecedorcontatoDepois as VARCHAR(50)) --================================================================================================== FETCH NEXT FROM FornecedorAntigo INTO @CnpjFornecedor, @SiglaFornecedor, @Email, @Telefone, @UtilidadeFornecida, @contato, @DataInclusao, @LoginInclusao, @DataAtualizacao, @LoginAtualizacao, @DiaVencimento, @UnidadeMedida, @TokenAcesso END CLOSE FornecedorAntigo DEALLOCATE FornecedorAntigo COMMIT TRANSACTION ImportacaoCadastro SET @TempoFim = (SELECT GETDATE() TempoFim) SELECT @TempoInicio as Inicio, @TempoFim AS Fim, DateDiff(HOUR, @TempoInicio, @TempoFim) AS Hora, DateDiff(MINUTE, @TempoInicio, @TempoFim) AS Minutos, DateDiff(SECOND, @TempoInicio, @TempoFim) AS Segundos END TRY BEGIN CATCH ROLLBACK TRANSACTION ImportacaoCadastro DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity inT; DECLARE @ErrorState inT; SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState ); IF (SELECT CURSOR_STATUS('global','FornecedorAntigo')) >= -1 --Cursor está aberto BEGIN CLOSE FornecedorAntigo DEALLOCATE FornecedorAntigo PRINT 'Cursor FornecedorAntigo Fechado' END SET @TempoFim = (SELECT GETDATE() TempoFim) SELECT @TempoInicio , @TempoFim, DateDiff(MINUTE, @TempoInicio, @TempoFim) AS Minutos END CATCH
O meu problema é o retorno do ID da tabela FornecedorContato, o primeiro insert está como zero
Resultado
Não sei se tem alguma coisa haver com com essa linha
EXEC sp_MSForEachTable 'IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1 DBCC CHECKIDENT (''?'', RESEED, 0)';
Quando eu coloco o RESEED igual a 1, a tabela FornecedorTipo do meu banco começa com 2
Resultado
Não sei o que pode estar de errado
Respostas
-
Rafael,
O problema está no seu CHECKIDENT, como você mesmo identificou.
Mas, o que acontece: (Fonte)
"Current identity value is set to the new_reseed_value. If no rows have been inserted to the table since it was created, or all rows have been removed by using the TRUNCATE TABLE statement, the first row inserted after you run DBCC CHECKIDENT uses new_reseed_value as the identity. Otherwise, the next row inserted uses new_reseed_value + the current increment value."
Ou seja... o DELETE e o TRUNCATE possuem comportamentos distintos quando é feito o DBCC CHECKIDENT
Eu fiz uma simulação rápida aqui, veja:
create table identity_del (a int identity (1,1)) GO create table identity_trunc (a int identity (1,1)) GO insert into identity_del default values go 10 insert into identity_trunc default values go 10 delete from identity_del go truncate table identity_trunc GO dbcc checkident (identity_del, reseed, 0) dbcc checkident (identity_trunc, reseed, 0) go select IDENT_CURRENT('identity_del'),IDENT_CURRENT('identity_trunc') GO select * from identity_del select * from identity_trunc drop table identity_trunc drop table identity_del
[]'s!
/* Logan Destefani Merazzi - DBA | @LoganMerazzi | http://www.merazzi.eti.br
Se a resposta for útil, vote nela. Se resolveu, marque-a como resposta. */- Marcado como Resposta Rafael Augusto Miranda segunda-feira, 16 de novembro de 2015 18:09
Todas as Respostas
-
Rafael,
Sim tem tudo haver com a linha, o comando Reseed 0 esta reinicializando a contagem de valores da sua coluna Identity para Zero.
Porque você esta utilizando esta linha de comando?
Pedro Antonio Galvao Junior [MVP | MCC | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | Professor Universitario | SoroCodigos | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]
-
Fiz porque, após a limpeza da tabela X, eu quero que o autoincremento começa-se denovo e não do ultimo ID
Esse seria os passsos
Insere registro 1, 2, 3, ......, 40
Ultimo ID da tabela 40
Limpeza da tabela e reset seed
Insere os registro novamente 1, 2, 3, ......, 40
- Editado Rafael Augusto Miranda sábado, 14 de novembro de 2015 15:16
-
-
Rafael,
O problema está no seu CHECKIDENT, como você mesmo identificou.
Mas, o que acontece: (Fonte)
"Current identity value is set to the new_reseed_value. If no rows have been inserted to the table since it was created, or all rows have been removed by using the TRUNCATE TABLE statement, the first row inserted after you run DBCC CHECKIDENT uses new_reseed_value as the identity. Otherwise, the next row inserted uses new_reseed_value + the current increment value."
Ou seja... o DELETE e o TRUNCATE possuem comportamentos distintos quando é feito o DBCC CHECKIDENT
Eu fiz uma simulação rápida aqui, veja:
create table identity_del (a int identity (1,1)) GO create table identity_trunc (a int identity (1,1)) GO insert into identity_del default values go 10 insert into identity_trunc default values go 10 delete from identity_del go truncate table identity_trunc GO dbcc checkident (identity_del, reseed, 0) dbcc checkident (identity_trunc, reseed, 0) go select IDENT_CURRENT('identity_del'),IDENT_CURRENT('identity_trunc') GO select * from identity_del select * from identity_trunc drop table identity_trunc drop table identity_del
[]'s!
/* Logan Destefani Merazzi - DBA | @LoganMerazzi | http://www.merazzi.eti.br
Se a resposta for útil, vote nela. Se resolveu, marque-a como resposta. */- Marcado como Resposta Rafael Augusto Miranda segunda-feira, 16 de novembro de 2015 18:09
-
Logan
Obrigado pela ajuda, funcionou corretamente, realmente não tinha prestado atenção no uso correto do dbcc checkident junto com delete e truncate
Abraços
- Editado Rafael Augusto Miranda segunda-feira, 16 de novembro de 2015 18:11