Visual Basic, VB .NET, ASP, Active X, Access, SQL Server

Mantendo um número serial único

Há situações em que você precisa de um campo a ser usado como identificador único e crescente para algum documento, porém sem deixar lacunas na numeração entre um documento e outro. No Access, campos de auto-numeração não são bons para isto, porque qualquer transação que adicione um registro, provoca o crescimento do campo em uma unidade, mesmo que a transação seja abortada. Se tiver uma tabela para conter o último número usado, você também terá que se preocupar em evitar que dois usuários peguem o mesmo número antes dele ser incrementado pela última rotina que o utilizou. A dica para resolver este problema é simples. A rotina que pega o número, deve realizar todas as suas ações no banco de dados dentro de uma transação. Antes de fechar a transação que usou o número, a tabela que o mantém é atualizada com uma instrução Update. Esta instrução adiciona 1 ao número apenas se ele ainda estiver com o mesmo valor que foi pego no início da transação, caso contrário, a transação é abortada e se reinicia pegando novamente o novo valor do número serial. Um exemplo deste esquema poderia ser como segue:

    Dim rs As ADODB.Recordset, cn As ADODB.Connection
    Dim lngSerial As Long

    Set cn = CreateObject("ADODB.Connection")
    cn.ConnectionString = strConexao
    cn.Open

    Set rs = CreateObject("ADODB.Recordset")

INICIO:
    rs.Open "Select Numero From TabelaSerialUnico",  cn
    'Salva serial único
    lngSerial = rs("Numero")

    'Inicia transação
    cn.BeginTrans


    'faz tudo que tem de fazer


    'atualiza tabela TabelaSerialUnico somente
    'se o número não foi alterado por outra
    'transação

    Dim RecAfec As Long, strSql As String
    strSql = "UPDATE TabelaSerialUnico SET Numero = Numero + 1 " _

                 "WHERE Numero = " & CStr(lngSerial)
    cn.Execute strSql, RecAfec, adExecuteNoRecords
    If RecAfec = 0 Then
'número mudou, já foi usado, reinicia
        cn.RollbackTrans

        GoTo INICIO
    Else
        cn.CommitTrans
'conclui

        rs.Close
        Set rs = Nothing

        cn.Close
        Set cn = Nothing
    End If