Selecionando registro de um Recordset usando GetRows
Selecionar uma determinada quantidade de registros de um base de dados é uma das tarefas mais frequentes em aplicações usando banco de dados. E pode ser o gargalo da sua aplicação se não for bem planejada. A esta altura já cabe a pergunta : Como você faz para extrair registros de um base de dados ? Qual o método frequentemente utilizado ? Vamos analisar...
Selecionado registros da tabela Authors da base de dados Biblio.mdb
1-) Creio que muitos usam o seguinte código para tal tarefa:
Dim codigo as integer Dim autor as string Dim ano as integer Set db = DBEngine.Workspaces(0).OpenDatabase(app.path & "\blibio.mdb") Set rs = db.OpenRecordset("Authors", dbOpenTable) Do Until tabela.EOF codigo = rs("Au_Id") autor = rs("Author") ano = rs("Year_Born") rs.movenext .... aqui voce realiza o seu processsamento Loop rs.close set rs=nothing |
Ou seja, você vai percorrendo (movenext) o Recordset , extraindo os registros e fazendo o processamento. Funciona ! voce pode dizer . Tudo bem , funciona , mas você já pensou no fato de que se o Recordset possuir 1000 registros e você está selecionando três campos vai ter 3000 requisições de leitura a sua base de dados ? E se a base de dados possuir 10.000 registros e você estiver selecionando 10 campos ? serão 100.000 requisições de leitura.
Para preencher um grid com os registros selecionados também enfrentamos o mesmo problema. Como os controles vinculados oneram demais o processamento, geralmente usamos o modo não vinculado(sem usar um controle de dados) dos grids (DBGrid) . Para preencher um grid no modo não vinculado precisamos conhecer dois parâmetros: quantas linhas e quantas colunas irão compor o grid. O número de linhas é o total de registros que estaremos selecionando do recordset e o número de colunas são os campos que selecionamos do recordset. Aqui começam os problemas...
Para conhecermos o número de campos do recordset é simples , usamos a propriedade Count do objeto Recordset, assim:
Dim icampos as integer Set db = DBEngine.Workspaces(0).OpenDatabase(app.path & "\blibio.mdb") Set rs = db.OpenRecordset("Authors", dbOpenTable) icampos = rs.fields.Count |
E para determinar a quantidade de registros selecionados ? Geralmente os métodos mais usados são:
1-) Usando a propriedade RecordCount
dim registros Set db = DBEngine.Workspaces(0).OpenDatabase(app.path & "\blibio.mdb") Set rs = db.OpenRecordset("Authors", dbOpenTable) rs.movelast rs.movefirst registros = rs.Recordcount.... |
Ou seja você percorrendo todo o Recordset até o final e volta depois ao início para saber quantos registros vai ter o grid. Acho que nem preciso dizer que este método não é aconselhável .
2-) Usando a função agregada Count da SQL
dim registros Set db = DBEngine.Workspaces(0).OpenDatabase(app.path & "\blibio.mdb") Set rs = db.OpenRecordset("Authors", dbOpenTable) set rstmp=db.OpenRecordset("SELECT
Count(*) as Registros From Authors") |
Este método pode ser mais rápido que o anterior mas você vai precisar criar dois recordsets : um para preencher o grid e outro para obter a quantidade de registros.
Existe uma forma melhor de fazer o serviço ? Sim existe , usando o método GetRows, vejamos então...
O método GetRows foi introduzido ainda nos tempos da DAO 3.0 e RDO 1.0 , mas apresentava problemas de implementação . Com o advento da ADO o método voltou aperfeiçoado e funcionando perfeitamente.
O objetivo em usar o método GetRows é selecionar múltiplos registros de um recordset e armazená-los em um vetor bidimensional. Nosso foco será o método GetRows da ADO 2.0.
A sintaxe na utilização de GetRows é a seguinte:
Nome_do_Vetor = Recordset.GetRows (Linhas , Inicio, Campos )
GetRows é usado para copiar registro de um Recordset para um vetor bidimensional. O primeiro item do vetor identifica os campos (colunas) e o segundo item identifica os registros.
A variável associada ao vetor tem o seu tamanho alocado dinamicamente quando da seleção dos registros.
Se não for informado o valor do argumento Linhas , GetRows retorna todos os registros do recordset e se for solicitado mais registros do que o disponível , GetRows retorna somente a quantidade existente.
Para restringir os campos selecionados, voce pode passar como argumento o nome do campo ou o seu número ou ainda passar como argumento um vetores de campos/números . Após GetRows retornar os registros do Recordset o próximo registro não lido se torna o registro atual, ou se não há mais registros , a propriedade EOF é definida como True.
Vejamos então o código para selecionar registros de um recordset usando GetRows:
Dim codigo as integer Dim autor as string Dim ano as integer Dim contador as integer Dim dbvetor as variant Set db = DBEngine.Workspaces(0).OpenDatabase(app.path & "\blibio.mdb") Set rs = db.OpenRecordset("Authors", dbOpenTable) dbvetor= rs.GetRows rs.close set rs=nothing db.close numero_de_colunas = Ubound(dbvetor,1) numero_de_registros = Ubound(dbvetor,2) for contador=0 to numero_de_registros codigo = dbvetor(contador,1) autor = dbvetor(contador,2) ano = dbvetor(contador,3) .... aqui voce realiza o seu processsamento next |
Vamos entender o código acima:
Ela retorna o valor maior para o indice do vetor na dimensão indicada. Assim se temos um vetor tridimensional definido como:
Dim A(1 To 100, 0 To 3, -3 To 4)
Instrução | Valor Retornado |
UBound(A, 1) |
100 |
UBound(A, 2) |
3 |
UBound(A, 3) |
4 |
Assim quando fizemos:
numero_de_colunas = Ubound(dbvetor,1) numero_de_registros = Ubound(dbvetor,2)
Estamos retornando em numero_de_colunas o maior valor do índice para a primeira dimensão: Ora este é o valor relacionado a quantidade de campos selecionado e estamos retornando em numero_de_registros o maior valor para índice da segunda dimensão que é o valor relacionado com a quantidade de registros.
for contador=0 to numero_de_registros codigo = dbvetor(contador,1) autor = dbvetor(contador,2) ano = dbvetor(contador,3) .... aqui voce realiza o seu processsamento next |
Para encerrar abaixo temos um exemplo simples e prático de preenchimento de um MSFlexgrid usando o GetRows:
Private Sub Command1_Click() Dim cnn As New ADODB.Connection Dim rst As New ADODB.Recordset Dim fld As ADODB.Field Dim avarData() As Variant Dim introws As Integer Dim i As Integer Dim j As Integer Dim linha As String 'Ábre o Recordset cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\teste\nwind.mdb;" 'Open the forward-only, read-only recordset rst.Open "Select * from Customers", cnn, adOpenForwardOnly, adLockReadOnly 'Seleciona todos os registros e armazena no vetor avarData avarData = rst.GetRows 'fecha o recordset rst.Close Set rst = Nothing 'verifica se há registros selecionados If introws > UBound(avarData, 2) Then MsgBox "Não ha registros para selecionar ...", vbAbortRetryIgnore, "JcmSoft" Exit Sub End If 'calcula o total de campos e registros selecionados colunas = UBound(avarData, 1) registros = UBound(avarData, 2) 'define o numero de colunas do grid Grid1.Cols = colunas 'defina as linhas e colunas fixas Grid1.FixedCols = 0 Grid1.FixedRows = 1 'Preenche o grid For i = 0 To registros For j = 0 To colunas linha = linha & avarData(j, i) & Chr(9) Next j Grid1.AddItem linha linha = "" Next i End Sub Private Sub Command2_Click() Unload Me End Sub |
Ao executar o projeto inicialmente você verá a tela1 abaixo e , após clicar no botão Preencher Grid terá a figura 2.0 :
Bem... espero que façam bom proveito ....