Gerar valores automáticos
Talvez seja necessário gerar automaticamente valores sequenciais para uma coluna em uma tabela específica. O Transact-SQL fornece duas maneiras de fazer isso: usar a propriedade IDENTITY com uma coluna específica em uma tabela ou definir um objeto SEQUENCE e usar valores gerados por esse objeto.
A propriedade IDENTITY
Para usar a propriedade IDENTITY, defina uma coluna usando um tipo de dados numéricos com uma escala de 0 (significando apenas números inteiros) e inclua a palavra-chave IDENTITY. Os tipos permitidos incluem todos os tipos inteiros e decimais em que você dá explicitamente uma escala de 0.
Uma semente opcional (valor inicial) e um incremento (valor de etapa) também podem ser especificados. Deixando de fora a semente e o incremento definirá ambos para 1.
Nota
A propriedade IDENTITY é especificada no lugar de especificar NULL ou NOT NULL na definição de coluna. Qualquer coluna com a propriedade IDENTITY não é automaticamente anulável. Você pode especificar NOT NULL apenas para autodocumentação, mas se especificar a coluna como NULL (significando anulável), a instrução de criação de tabela gerará um erro.
Apenas uma coluna em uma tabela pode ter a propriedade IDENTITY definida; é frequentemente usado como a CHAVE PRIMÁRIA ou uma chave alternativa.
O código a seguir mostra a criação da tabela Sales.Promotion usada nos exemplos da seção anterior, mas desta vez com uma coluna de identidade chamada PromotionID como chave primária:
CREATE TABLE Sales.Promotion
(
PromotionID int IDENTITY PRIMARY KEY,
PromotionName varchar(20),
StartDate datetime NOT NULL DEFAULT GETDATE(),
ProductModelID int NOT NULL REFERENCES Production.ProductModel(ProductModelID),
Discount decimal(4,2) NOT NULL,
Notes nvarchar(max) NULL
);
Nota
Os detalhes completos da instrução CREATE TABLE estão além do escopo deste módulo.
Inserindo dados em uma coluna de identidade
Quando a propriedade IDENTITY é definida para uma coluna, as instruções INSERT na tabela geralmente não especificam um valor para a coluna IDENTITY. O mecanismo de banco de dados gera um valor usando o próximo valor disponível para a coluna.
Por exemplo, você pode inserir uma linha na tabela Sales.Promotion sem especificar um valor para a coluna PromotionID :
INSERT INTO Sales.Promotion
VALUES
('Clearance Sale', '01/01/2021', 23, 0.10, '10% discount')
Observe que, embora a cláusula VALUES não inclua um valor para a coluna PromotionID , você não precisa especificar uma lista de colunas na cláusula INSERT - as colunas Identity estão isentas desse requisito.
Se esta linha for a primeira inserida na tabela, o resultado será uma nova linha como esta:
ID promocional
PromotionName
StartDate
ID do Modelo do Produto
Discount
Notas
1
Liquidação
2021-01-01T00:00:00
23
0.1
10% desconto
Quando a tabela foi criada, nenhum valor de semente ou incremento foi definido para a coluna IDENTITY, de modo que a primeira linha é inserida com um valor de 1. A próxima linha a ser inserida receberá um valor PromotionID de 2 e assim por diante.
Recuperando um valor de identidade
Para retornar o valor IDENTITY atribuído mais recentemente dentro da mesma sessão e escopo, use a função SCOPE_IDENTITY; Assim:
SELECT SCOPE_IDENTITY();
A função SCOPE_IDENTITY retorna o valor de identidade mais recente gerado no escopo atual para qualquer tabela. Se você precisar do valor de identidade mais recente em uma tabela específica, poderá usar a função IDENT_CURRENT, da seguinte forma:
SELECT IDENT_CURRENT('Sales.Promotion');
Valores de identidade prevalecentes
Se quiser substituir o valor gerado automaticamente e atribuir um valor específico à coluna IDENTITY, primeiro será necessário habilitar as inserções de identidade usando a instrução SET IDENTITY INSERT table_name ON. Com essa opção ativada, você pode inserir um valor explícito para a coluna de identidade, como qualquer outra coluna. Quando terminar, você poderá usar a instrução SET IDENTITY INSERT table_name OFF para continuar usando valores de identidade automáticos, usando o último valor inserido explicitamente como uma semente.
SET IDENTITY_INSERT SalesLT.Promotion ON;
INSERT INTO SalesLT.Promotion (PromotionID, PromotionName, ProductModelID, Discount)
VALUES
(20, 'Another short sale',37, 0.3);
SET IDENTITY_INSERT SalesLT.Promotion OFF;
Como você aprendeu, a propriedade IDENTITY é usada para gerar uma sequência de valores para uma coluna dentro de uma tabela. No entanto, a propriedade IDENTITY não é adequada para coordenar valores em várias tabelas dentro de um banco de dados. Por exemplo, suponha que sua organização diferencie entre vendas diretas e vendas para revendedores e queira armazenar dados para essas vendas em tabelas separadas. Ambos os tipos de venda podem precisar de um número de fatura exclusivo, e você pode querer evitar a duplicação do mesmo valor para dois tipos diferentes de venda. Uma solução para esse requisito é manter um pool de valores sequenciais exclusivos em ambas as tabelas.
Repropagando uma coluna de identidade
Ocasionalmente, você precisará redefinir ou ignorar valores de identidade para a coluna. Para fazer isso, você estará "resemeando" a coluna usando a função DBCC CHECKIDENT. Você pode usar isso para ignorar muitos valores ou para redefinir o próximo valor de identidade para 1 depois de excluir todas as linhas da tabela. Para obter detalhes completos sobre o uso do DBCC CHECKIDENT, consulte a documentação de referência do Transact-SQL.
SEQUÊNCIA
No Transact-SQL, você pode usar um objeto de sequência para definir novos valores sequenciais independentemente de uma tabela específica. Um objeto de sequência é criado usando a instrução CREATE SEQUENCE, opcionalmente fornecendo o tipo de dados (deve ser um tipo inteiro ou decimal ou numérico com uma escala de 0), o valor inicial, um valor de incremento, um valor máximo e outras opções relacionadas ao desempenho.
CREATE SEQUENCE Sales.InvoiceNumber AS INT
START WITH 1000 INCREMENT BY 1;
Para recuperar o próximo valor disponível de uma sequência, use a construção NEXT VALUE FOR, da seguinte forma:
INSERT INTO Sales.ResellerInvoice
VALUES
(NEXT VALUE FOR Sales.InvoiceNumber, 2, GETDATE(), 'PO12345', 107.99);
IDENTIDADE ou SEQUÊNCIA
Ao decidir se deseja usar colunas IDENTITY ou um objeto SEQUENCE para preencher valores automaticamente, tenha em mente os seguintes pontos:
Use SEQUENCE se seu aplicativo exigir o compartilhamento de uma única série de números entre várias tabelas ou várias colunas dentro de uma tabela.
SEQUENCE permite que você classifique os valores por outra coluna. A construção NEXT VALUE FOR pode usar a cláusula OVER para especificar a coluna de classificação. A cláusula OVER garante que os valores retornados sejam gerados na ordem da cláusula ORDER BY da cláusula OVER. Essa funcionalidade também permite gerar números de linha para linhas à medida que elas são retornadas em um SELECT. No exemplo a seguir, a tabela Production.Product é classificada pela coluna Name e a primeira coluna retornada é um número sequencial.
SELECT NEXT VALUE FOR dbo.Sequence OVER (ORDER BY Name) AS NextID, ProductID, Name FROM Production.Product;
Embora a instrução anterior estivesse apenas selecionando valores SEQUENCE para exibir, os valores ainda estão sendo 'usados' e os valores SEQUENCE exibidos não estarão mais disponíveis. Se você executar o SELECT acima várias vezes, obterá valores SEQUENCE diferentes a cada vez.
Use SEQUENCE se seu aplicativo exigir que vários números sejam atribuídos ao mesmo tempo. Por exemplo, um aplicativo precisa reservar cinco números sequenciais. A solicitação de valores de identidade poderia resultar em lacunas na série se outros processos fossem emitidos simultaneamente números. Você pode usar o procedimento do sistema sp_sequence_get_range para recuperar vários números na sequência de uma só vez.
SEQUENCE permite alterar a especificação da sequência, como o valor de incremento.
Os valores IDENTITY são protegidos contra atualizações. Se você tentar atualizar uma coluna com a propriedade IDENTITY, receberá um erro.