Problemas con Devolución de Registros a una Grilla
Tengo problemas al generar un sentencia SQL que me devuelva más de 800,000 Registros y la hora de volcarlos a un Control ADO me genera un error de memoria Virtual y paginación por Visual Basic . Ya le amplíe la memoria Virtual pero, a mi parecer el problema es que no soporta la cantidad de registros que me esta devolviendo.
Como puedo hacer para mostrar todos estos registros en una Grilla y que sea rapido.
Como puedo hacer para mostrar todos estos registros en una Grilla y que sea rapido.
1 Respuesta
Respuesta de athrarn
1
1
athrarn, - Sistemas Operativos : - MS-DOS, Windows 3
1.- Espero no te moleste, pero 256 caracteres para el nombre de un cliente... Vamos, si yo me llamara Felipe Juan Froilan de Todos los Santos de nombre... No llegaría a los 50... jejejeje.
Vale, haz la carga con la consulta. Por el SQL deduzco que la tabla sera contra un producto Microsoft, porque ese script de sql...
Supongamos que hacemos la conexión en una clase como esta (Con ADO):
Dim innerRS As ADODB.Recordset
Private Sub Class_Initialize()
On Error GoTo FalloConexion
Set Conexion = New ADODB.Connection
Conexion.ConnectionString = strMontarCad(LOGIN_ORACLE, PASS_ORACLE, "", SERVICIO_ORACLE)
Conexion.Open
Exit Sub
FalloConexion:
MsgBox Err.Description
End Sub
Private Function strMontarCad(ByVal PestrUsuario As String, ByVal PestrClave As String, ByVal PestrServidor As String, ByVal PestrBD As String) As String
Dim mCadenaConex As String
'mCadenaConex = "Provider=MSDAORA.1;Password=" & PestrClave & ";User ID=" & PestrUsuario & ";Data Source=" & PestrBD & ";Persist Security Info=True"
'mCadenaConex = "Provider=OraOLEDB.Oracle.1;Password=" & PestrClave & ";User ID=" & PestrUsuario & ";Data Source= " & PestrBD & ";Persist Security Info=true"
'mCadenaConex = "Provider =Microsoft.Jet.OLEDB.4.0;Data Source=" & app.Path & "\\Tailored01\BBDDComercial\BBDDComercialv04.mdb;"
mCadenaConex = "Provider =Microsoft.Jet.OLEDB.4.0;Data Source=" & CONST_PATH_BBDD & ";User Id=Admin;Password=;"
strMontarCad = mCadenaConex
End Function
Public Function ExecuteQuery(ByVal SQL As String) As ADODB.Recordset
Set innerRS = New ADODB.Recordset
innerRS.CacheSize = 30
InnerRS. Open SQL, Conexion. ConnectionString, adOpenForwardOnly, adLockBatchOptimistic, adAsyncFetch
Set ExecuteQuery = innerRS
End Function
Public Sub ExecuteSQL(SQL As String)
Conexion. BeginTrans
Conexion.Execute SQL
Conexion.CommitTrans
DoEvents
End Sub
Private Sub Class_Terminate()
If (Conexion.State <> adStateClosed) Then
Conexion.Close
End If
End Sub
Una vez declarada la conexion, hacemos la definicion de la estructura :
type RegistroClientes_MSTO
cli_id as long '(suponiendo que no me pase de long con 18 caracteres)
name as string
first_name as string
last_name as string
country as string
street_address_number as string
.
.
.
Y no lo pongo entero por que es muy largo ;-)
.
.
flag_telefono as string
end type
ahora, generas una consulta que guarde los datos en la estructura :
Dim sql As String
Dim RS As Recordset
Dim Registro as RegistroClientes_MSTO
sql = "Select * from [dbo].[Clientes_MSTO] "
Set RS = objConexion.ExecuteQuery(sql)
While Not RS.EOF
' Ahora asignas todos los rs(loque sea).value a su registro correspondiente :
Registro.cli_id= rs("cli_id").value
Registro.name = rs("name").value
'etc, etc, etc
añadiroperador Registro
RS.MoveNext
Wend
Y generamos una funcion de añadir operador de este estilo :
'Declaramos el array dinámico :
dim ConjuntoOperadores() as RegistroClientes_MSTO
' Un contador para saber cuantos elementos tenemos, que deberá esta inicializado a 0 al principio de todo
dim lngCountConjuntoOperadores as long
Public Sub añadiroperador(pePalabra As RegistroClientes_MSTO)
If lngCountConjuntoOperadores = 0 Then
ReDim Preserve ConjuntoOperadores(0 To 0)
ConjuntoOperadores(0).CadaUnodeLosCampos = pePalabra.CadaUnoDeLosCampos
lngCountConjuntoOperadores = 1
Exit Sub
End If
ReDim Preserve ConjuntoOperadores(LBound(ConjuntoOperadores) To UBound(ConjuntoOperadores) + 1)
ConjuntoOperadores(UBound(ConjuntoOperadores)).CadaUnoDeLosCampos = pePalabra.CadaUnoDeLosCampos
lngCountConjuntoOperadores = lngCountConjuntoOperadores + 1
End Sub
Una vez tienes relleno el Array necesitaras. Por volumen de Datos :
Un algoritmo optimizado de busqueda. Como el Binario :
ej :
Public Function blnBuscarCliente(PeClienteaBuscar As String) As Boolean
Dim medio As Long
Dim blnEncontrado As Boolean
blnEncontrado = False
Dim mayor As Long
Dim menor As Long
Dim salir As Boolean
mayor = lngCountConjuntoOperadores - 1
menor = 0
salir = False
While Not blnEncontrado And Not salir
medio = ((mayor - menor) \ 2) + menor
If ConjuntoOperadores(medio).name > PeClienteaBuscar Then
If mayor = medio Then
salir = True
End If
mayor = medio
ElseIf ConjuntoOperadores(medio).name < PeClienteBuscar Then
If menor = medio Then
salir = True
End If
menor = medio
Else
blnEncontrado = True
End If
Wend
blnBuscarCliente = blnEncontrado
'Tambien puedes devolver el ID.
End Function
Ahora Con los datos cargados y una función de búsqueda muy rápida,
Añade los controles de VB 6.0 HScrollBar o VScrollBar (con valores max el lngCountConjuntoOperadores y min 1) y un listview o un control similar, para almacenar los datos en pantalla.
En el evento SCroll() del ScrollBar que selecciones pregunta por el valor del VScrollBar1. Value y tendras el indice que necesitas buscar. Si borras el contenido del ListView y cargas los datos que se ven en el grid, por ejemplo 10 antes y diez después de lo que has mostrado en el listview, ya tendrás lo que buscas...
Vale, haz la carga con la consulta. Por el SQL deduzco que la tabla sera contra un producto Microsoft, porque ese script de sql...
Supongamos que hacemos la conexión en una clase como esta (Con ADO):
Dim innerRS As ADODB.Recordset
Private Sub Class_Initialize()
On Error GoTo FalloConexion
Set Conexion = New ADODB.Connection
Conexion.ConnectionString = strMontarCad(LOGIN_ORACLE, PASS_ORACLE, "", SERVICIO_ORACLE)
Conexion.Open
Exit Sub
FalloConexion:
MsgBox Err.Description
End Sub
Private Function strMontarCad(ByVal PestrUsuario As String, ByVal PestrClave As String, ByVal PestrServidor As String, ByVal PestrBD As String) As String
Dim mCadenaConex As String
'mCadenaConex = "Provider=MSDAORA.1;Password=" & PestrClave & ";User ID=" & PestrUsuario & ";Data Source=" & PestrBD & ";Persist Security Info=True"
'mCadenaConex = "Provider=OraOLEDB.Oracle.1;Password=" & PestrClave & ";User ID=" & PestrUsuario & ";Data Source= " & PestrBD & ";Persist Security Info=true"
'mCadenaConex = "Provider =Microsoft.Jet.OLEDB.4.0;Data Source=" & app.Path & "\\Tailored01\BBDDComercial\BBDDComercialv04.mdb;"
mCadenaConex = "Provider =Microsoft.Jet.OLEDB.4.0;Data Source=" & CONST_PATH_BBDD & ";User Id=Admin;Password=;"
strMontarCad = mCadenaConex
End Function
Public Function ExecuteQuery(ByVal SQL As String) As ADODB.Recordset
Set innerRS = New ADODB.Recordset
innerRS.CacheSize = 30
InnerRS. Open SQL, Conexion. ConnectionString, adOpenForwardOnly, adLockBatchOptimistic, adAsyncFetch
Set ExecuteQuery = innerRS
End Function
Public Sub ExecuteSQL(SQL As String)
Conexion. BeginTrans
Conexion.Execute SQL
Conexion.CommitTrans
DoEvents
End Sub
Private Sub Class_Terminate()
If (Conexion.State <> adStateClosed) Then
Conexion.Close
End If
End Sub
Una vez declarada la conexion, hacemos la definicion de la estructura :
type RegistroClientes_MSTO
cli_id as long '(suponiendo que no me pase de long con 18 caracteres)
name as string
first_name as string
last_name as string
country as string
street_address_number as string
.
.
.
Y no lo pongo entero por que es muy largo ;-)
.
.
flag_telefono as string
end type
ahora, generas una consulta que guarde los datos en la estructura :
Dim sql As String
Dim RS As Recordset
Dim Registro as RegistroClientes_MSTO
sql = "Select * from [dbo].[Clientes_MSTO] "
Set RS = objConexion.ExecuteQuery(sql)
While Not RS.EOF
' Ahora asignas todos los rs(loque sea).value a su registro correspondiente :
Registro.cli_id= rs("cli_id").value
Registro.name = rs("name").value
'etc, etc, etc
añadiroperador Registro
RS.MoveNext
Wend
Y generamos una funcion de añadir operador de este estilo :
'Declaramos el array dinámico :
dim ConjuntoOperadores() as RegistroClientes_MSTO
' Un contador para saber cuantos elementos tenemos, que deberá esta inicializado a 0 al principio de todo
dim lngCountConjuntoOperadores as long
Public Sub añadiroperador(pePalabra As RegistroClientes_MSTO)
If lngCountConjuntoOperadores = 0 Then
ReDim Preserve ConjuntoOperadores(0 To 0)
ConjuntoOperadores(0).CadaUnodeLosCampos = pePalabra.CadaUnoDeLosCampos
lngCountConjuntoOperadores = 1
Exit Sub
End If
ReDim Preserve ConjuntoOperadores(LBound(ConjuntoOperadores) To UBound(ConjuntoOperadores) + 1)
ConjuntoOperadores(UBound(ConjuntoOperadores)).CadaUnoDeLosCampos = pePalabra.CadaUnoDeLosCampos
lngCountConjuntoOperadores = lngCountConjuntoOperadores + 1
End Sub
Una vez tienes relleno el Array necesitaras. Por volumen de Datos :
Un algoritmo optimizado de busqueda. Como el Binario :
ej :
Public Function blnBuscarCliente(PeClienteaBuscar As String) As Boolean
Dim medio As Long
Dim blnEncontrado As Boolean
blnEncontrado = False
Dim mayor As Long
Dim menor As Long
Dim salir As Boolean
mayor = lngCountConjuntoOperadores - 1
menor = 0
salir = False
While Not blnEncontrado And Not salir
medio = ((mayor - menor) \ 2) + menor
If ConjuntoOperadores(medio).name > PeClienteaBuscar Then
If mayor = medio Then
salir = True
End If
mayor = medio
ElseIf ConjuntoOperadores(medio).name < PeClienteBuscar Then
If menor = medio Then
salir = True
End If
menor = medio
Else
blnEncontrado = True
End If
Wend
blnBuscarCliente = blnEncontrado
'Tambien puedes devolver el ID.
End Function
Ahora Con los datos cargados y una función de búsqueda muy rápida,
Añade los controles de VB 6.0 HScrollBar o VScrollBar (con valores max el lngCountConjuntoOperadores y min 1) y un listview o un control similar, para almacenar los datos en pantalla.
En el evento SCroll() del ScrollBar que selecciones pregunta por el valor del VScrollBar1. Value y tendras el indice que necesitas buscar. Si borras el contenido del ListView y cargas los datos que se ven en el grid, por ejemplo 10 antes y diez después de lo que has mostrado en el listview, ya tendrás lo que buscas...
Gracias, pero me gustaría que me envíes el ejemplo te envío la Tabla(Es un Script de sql).
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Clientes_MSTO]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo]. [Clientes_MSTO]
GO
CREATE TABLE [dbo]. [Clientes_MSTO] (
[cli_id] [decimal](18, 0) IDENTITY (1, 1) NOT NULL ,
[name] [varchar] (256) NULL ,
[first_name] [varchar] (150) NULL ,
[last_name] [varchar] (150) NULL ,
[country] [varchar] (50) NULL ,
[street_address_number] [varchar] (50) NULL ,
[street_address_name] [varchar] (256) NULL ,
[street_name] [varchar] (256) NULL ,
[city] [varchar] (100) NULL ,
[state] [varchar] (100) NULL ,
[phone1] [varchar] (20) NULL ,
[phone2] [varchar] (20) NULL ,
[doc_type] [varchar] (50) NULL ,
[doc_num] [varchar] (20) NULL ,
[sex] [varchar] (20) NULL ,
[zipcode] [varchar] (20) NULL ,
[census_tract] [varchar] (20) NULL ,
[year_listed] [varchar] (20) NULL ,
[wealth_rating] [varchar] (20) NULL ,
[type] [varchar] (20) NULL ,
[Fecha_Hora_Creacion] [datetime] NULL ,
[campaña_Creacion] [varchar] (50) NULL ,
[Fecha_Hora_Modificacion] [datetime] NULL ,
[campaña_Modificacion] [varchar] (50) NULL ,
[Agente_Creacion] [varchar] (50) NULL ,
[Agente_Modificacion] [varchar] (50) NULL ,
[origenREGISTER] [varchar] (254) NULL ,
[Type_File] [varchar] (254) NULL ,
[Type_List] [varchar] (254) NULL ,
[tmp] [varchar] (254) NULL ,
[ID_operador] [decimal](18, 0) NULL ,
[flag] [numeric](18, 0) NULL ,
[Desc_Operador] [varchar] (200) NULL ,
[Origen_Base_Datos] [varchar] (200) NULL ,
[Tipo_name] [varchar] (50) NULL ,
[flag_gestion] [numeric](18, 0) NOT NULL ,
[flag_telefono] [varchar] (40) NULL
) ON [PRIMARY]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Clientes_MSTO]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo]. [Clientes_MSTO]
GO
CREATE TABLE [dbo]. [Clientes_MSTO] (
[cli_id] [decimal](18, 0) IDENTITY (1, 1) NOT NULL ,
[name] [varchar] (256) NULL ,
[first_name] [varchar] (150) NULL ,
[last_name] [varchar] (150) NULL ,
[country] [varchar] (50) NULL ,
[street_address_number] [varchar] (50) NULL ,
[street_address_name] [varchar] (256) NULL ,
[street_name] [varchar] (256) NULL ,
[city] [varchar] (100) NULL ,
[state] [varchar] (100) NULL ,
[phone1] [varchar] (20) NULL ,
[phone2] [varchar] (20) NULL ,
[doc_type] [varchar] (50) NULL ,
[doc_num] [varchar] (20) NULL ,
[sex] [varchar] (20) NULL ,
[zipcode] [varchar] (20) NULL ,
[census_tract] [varchar] (20) NULL ,
[year_listed] [varchar] (20) NULL ,
[wealth_rating] [varchar] (20) NULL ,
[type] [varchar] (20) NULL ,
[Fecha_Hora_Creacion] [datetime] NULL ,
[campaña_Creacion] [varchar] (50) NULL ,
[Fecha_Hora_Modificacion] [datetime] NULL ,
[campaña_Modificacion] [varchar] (50) NULL ,
[Agente_Creacion] [varchar] (50) NULL ,
[Agente_Modificacion] [varchar] (50) NULL ,
[origenREGISTER] [varchar] (254) NULL ,
[Type_File] [varchar] (254) NULL ,
[Type_List] [varchar] (254) NULL ,
[tmp] [varchar] (254) NULL ,
[ID_operador] [decimal](18, 0) NULL ,
[flag] [numeric](18, 0) NULL ,
[Desc_Operador] [varchar] (200) NULL ,
[Origen_Base_Datos] [varchar] (200) NULL ,
[Tipo_name] [varchar] (50) NULL ,
[flag_gestion] [numeric](18, 0) NOT NULL ,
[flag_telefono] [varchar] (40) NULL
) ON [PRIMARY]
GO
No almacenes los registros en "la grilla", supongo que te refieres a uno de los múltiples componentes de Microsoft con forma de lista.
Realiza la consulta en un recordset y créate una estructura de datos que pueda almacenar los de la tabla.
Luego implementa funciones de Array dinámico que almacenen en el array los datos.
Una vez almacenados los datos en una estructura, implementa algoritmos de búsqueda para un registro en particular. Como el algoritmo de búsqueda binario. Devuelvete el id del elemento seleccionado y carga en "la grilla" los 10 anteriores y los 10 posteriores a ese elemento. Si controlas cuando se desplaza por las barras de desplazamiento de "la grilla" entonces buscas el nuevo elemento medio de la misma y los recolocas en el mismo.
Si me dices la tabla, te envío código de ejemplo.
Un saludo.
PD: El algoritmo de búsqueda binario será el más rápido de los algoritmos no indexados si tienes los elementos ordenados. Que lo estarán si guardas los datos en un Array dinámico.
Siento haber tardado en contestar, pero he tenido un accidente en el coche.
Realiza la consulta en un recordset y créate una estructura de datos que pueda almacenar los de la tabla.
Luego implementa funciones de Array dinámico que almacenen en el array los datos.
Una vez almacenados los datos en una estructura, implementa algoritmos de búsqueda para un registro en particular. Como el algoritmo de búsqueda binario. Devuelvete el id del elemento seleccionado y carga en "la grilla" los 10 anteriores y los 10 posteriores a ese elemento. Si controlas cuando se desplaza por las barras de desplazamiento de "la grilla" entonces buscas el nuevo elemento medio de la misma y los recolocas en el mismo.
Si me dices la tabla, te envío código de ejemplo.
Un saludo.
PD: El algoritmo de búsqueda binario será el más rápido de los algoritmos no indexados si tienes los elementos ordenados. Que lo estarán si guardas los datos en un Array dinámico.
Siento haber tardado en contestar, pero he tenido un accidente en el coche.
- Compartir respuesta
- Anónimo
ahora mismo