Colunas Identity Parte-II

Exemplos práticos

por Paulo Ribeiro

Colunas com a propriedade identity são utilizadas para geração de números inteiros auto-incrementáveis, sendo bastante úteis na construção de relacionamentos como alvo de primary-keys. O objetivo dessa matéria será fornecer exemplos práticos da utilização de colunas identity, assunto que foi iniciado em Colunas Identity Parte I: para que servem e como criar.

Nos exemplos dessa matéria serão utilizadas duas tabelas: pedido e item_pedido, cuja estrutura está relacionada na Listagem 1.

 

create table pedido

(

id_pedido int not null identity (1,1)

,dt_emissao smalldatetime not null

,id_emitente int not null

)

go

create table item_pedido

(

id_item_pedido int not null identity (1,1)

,id_pedido int not null

,cod_produto int not null

,qtde int not null

,vlr_unitario dec(8,2) not null

,vlr_descto_unitario dec(8,2) not null

)

alter table pedido add constraint pk_pedido primary key clustered (id_pedido)

alter table item_pedido add constraint pk_item_pedido primary key nonclustered (id_item_pedido)

alter table item_pedido add constraint fk_item_pedido_pedido foreign key (id_pedido) references pedido (id_pedido)

alter table item_pedido add constraint un_item_pedido unique clustered (id_pedido,cod_produto)

go

Listagem 1. Script para criação das tabelas pedido e item_pedido

Como inserir linhas em tabelas que possuem colunas identity

Como a propriedade identity gera um número auto-incrementável, não se deve atribuir valores para colunas identity no comando de inserção. Se tentássemos atribuir um valor para a coluna id_pedido – que possui a propriedade identity habilitada – durante uma inserção na tabela pedido, seríamos impedidos pela exception 8101 (ver Listagem 2)

 

insert into pedido

values (1,'2005-09-01',204)

----------------------------------------------------------------------------------------------------

Server: Msg 8101, Level 16, State 1, Line 1

An explicit value for the identity column in table 'pedido' can only be specified when a column list is used and IDENTITY_INSERT is ON.

Listagem 2. Erro ao tentar atribuir um valor para coluna identity

Para que o comando INSERT na tabela pedido seja concluído com sucesso, vamos alterar a linha de comando especificando todas as colunas - exceto id_pedido (ver Listagem 3).

 

insert into pedido (dt_emissao, id_emitente)

values ('2005-09-01',204)

----------------------------------------------------------------------------------------------------

 

(1 row(s) affected)

Listagem 3. Inserindo linhas em tabelas que possuem colunas identity

Bem, agora que o pedido foi inserido com sucesso vamos a uma nova questão: qual foi o número do pedido gerado automaticamente pela propriedade identity no comando INSERT da Listagem 3?

Consultando o valor gerado na coluna identity com @@IDENTITY

A variável de ambiente @@IDENTITY armazena o último identity gerado na sessão. Assim, se quiséssemos prosseguir com o cadastramento do item de pedido (tabela item_pedido), precisaríamos consultar o valor de @@IDENTITY para que pudéssemos informá-lo no cadastramento do item (ver Listagem 4).

 

set NOCOUNT on

declare @id_pedido int

 

--inserindo um pedido (a coluna id_pedido nao foi informada)

insert into pedido (dt_emissao, id_emitente)

values ('2005-09-01',204)

 

-- resgatando o numero do pedido

select @id_pedido = @@IDENTITY

 

-- inserindo o detalhe do pedido

insert into item_pedido (id_pedido, cod_produto, qtde, vlr_unitario, vlr_descto_unitario)

values (@id_pedido,101014, 5, 10.50, 1.00)

 

----------------------------------------------------------------------------------------------------

id_pedido dt_emissao id_emitente

----------- ------------------------------------------------------ -----------

2 2005-09-01 00:00:00 204

 

id_item_pedido id_pedido cod_produto qtde vlr_unitario vlr_descto_unitario

-------------- ----------- ----------- ----------- ------------ -------------------

1 2 101014 5 10.50 1.00

Listagem 4. Consultando o valor identity após inserção com @@IDENTITY

Se excluirmos linhas da tabela pedido, estaremos criando “buracos” na numeração de pedidos. Dependendo da situação, pode ser necessário inserções pontuais, especificando-se a numeração do pedido que se deseja incluir.

Como atualizar manualmente colunas identity durante a inserção

Se inserirmos os pedidos 1,2,3,4,5 e depois excluirmos o pedido 3, esse número não será reutilizado por outro pedido: a numeração ficará com uma “falha” no pedido que foi excluído. Par incluir outro pedido com o mesmo id do pedido excluído (=3), teremos que desabilitar a propriedade identity no comando de inserção com o comando SET IDENTITY_INSERT ON. O “desligamento” da propriedade identity ficará ativo apenas na sessão, permanecendo assim até que a sessão seja finalizada ou o comando SET IDENTITY_INSERT OFF seja executado. (ver Listagem 5).

 

set nocount ON

 

-- inserindo pedidos 3,4 e 5

insert into pedido (dt_emissao,id_emitente) values ('2005-09-02',205)

select id_pedido=@@identity

insert into pedido (dt_emissao,id_emitente) values ('2005-09-03',206)

select id_pedido=@@identity

insert into pedido (dt_emissao,id_emitente) values ('2005-09-04',207)

select id_pedido=@@identity

go

 

-- excluindo pedido 3

delete from pedido where id_pedido=3

go

 

-- ligando a propriedade identity_insert

set IDENTITY_INSERT pedido ON

 

-- incluindo pedidos

insert into pedido (id_pedido,dt_emissao,id_emitente)

values (3,'2005-09-05',208) -- incluindo outro pedido com id_pedido=3

insert into pedido (id_pedido,dt_emissao,id_emitente)

values (100,'2005-09-06',209) -- incluindo id_pedido=100

 

-- desligando a propriedade identity_insert

set IDENTITY_INSERT pedido OFF

 

-- incluindo pedidos com a propriedade identity habilitada

insert into pedido (dt_emissao,id_emitente)

values ('2005-09-07',210)

 

-- consultando a tabela pedido

select * from pedido

go

 

----------------------------------------------------------------------------------------------------

id_pedido

----------------------------------------

3

 

id_pedido

----------------------------------------

4

 

id_pedido

----------------------------------------

5

 

id_pedido dt_emissao id_emitente

----------- ------------------------------------------------------ -----------

1 2005-09-01 00:00:00 204

2 2005-09-01 00:00:00 204

3 2005-09-05 00:00:00 208

4 2005-09-03 00:00:00 206

5 2005-09-04 00:00:00 207

100 2005-09-06 00:00:00 209

101 2005-09-07 00:00:00 210

Listagem 5. Desativando a propriedade identity

Note que durante o período em que a propriedade identity estava desabilitada, foram inseridos os pedidos de 3 e 100. Ao habilitar novamente o identity e efetuar nova inserção, repare que a numeração de pedidos foi automaticamente ajustada considerando a inserção manual; esse é um detalhe importante e que deve ser observado.

Conclusão

Colunas identity possuem regras que devem ser respeitadas nos comandos de inserção e atualização; essas regras informam basicamente como devem ser tratatas alterações nesse tipo de coluna. Na terceira e última parte dessa matéria aprenderemos a corrigir o valor de colunas identity, falaremos também sobre a utilização da função IDENTITY (sim, aqui é função e não propriedade!) com SELECT INTO.

Até lá!

Leia todos artigos da série