Este foro usa cookies
Este foro utiliza cookies para almacenar su información de inicio de sesión si está registrado y su última visita si no lo está. Las cookies son pequeños documentos de texto almacenados en su computadora; las cookies establecidas por este foro solo se pueden usar en este sitio web y no representan ningún riesgo de seguridad. Las cookies en este foro también rastrean los temas específicos que ha leído y la última vez que los leyó. Si Ud. continúa navegando, entenderemos que acepta todas las cookies.

Se almacenará una cookie en su navegador, independientemente de la elección, para evitar que se le vuelva a hacer esta pregunta. Podrá cambiar la configuración de sus cookies en cualquier momento utilizando el enlace en el pie de página.

El foro antiguo se encuentra accesible desde https://foro.gambas-es.org en modo de solo lectura.

Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5

Dudas con clase Result
#1

Creo que me estoy equivocando al entender que Result es un conjunto de registros obtenidos de la bdd.

Ejemplo primero y planteo la duda:

Dim rDatos as Result
rDatos = db.Find("tabla1")
rDatos.MoveFirst (ya sé que esto no es imprescindible aquí)
while rDatos.Available
       blabla(rDatos!campo1, rDatos!campo2, rDatos!campo3)
       rDatos.MoveNext
wend
 Perfecto,  funciona de mil maravillas.
Peeeero si la tabla tiene un montón de campos....... los tengo que pasar todos de uno en uno????

No he encontrado la forma de hacer blabla(rDatos.TodoElregistroDeUNgolpe) o algo que se le parezca

public sub blabla(registro As ???????what)

NI con fields, ni con ResultField, ni nada de nada.

Algo me he perdido.

Una ayudita, please.
    ¡Gracias!
#2

Auto_respuesta:
Código:
Gambas class file


Public Sub Form_Open()
    Dim db As New Connection
    Dim rDatos As Result
    Dim cRegistro As New Collection
    Dim RF As ResultField
 
    
    rDatos = db.Find("tabla1")
    
    While rDatos.Available
        cRegistro.Clear
        For Each RF In rDatos.Fields
            cRegistro.Add(rDatos[RF.name], RF.name)
        Next
        blabla(cRegistro)
        rDatos.MoveNext
    Wend
    
End


Private Sub blabla(data As Collection)
    Dim aKeys As New String[]
    Dim i As Integer
    
    Print "--------------------------------------"
    aKeys = data.Keys
    For i = 0 To aKeys.Max
        Print aKeys[i]; " - "; data[aKeys[i]]
    Next
End
[-] Los siguientes 1 usuarios dice gracias a gartumar2 por este post:
  • jsbsan
    ¡Gracias!
#3

Es una manera, pero si no amplías qué es lo que quieres hacer, no veo qué sentido tiene. Pasas todo a una colección, de la que luego tendrás que buscar el valor con la sintaxis:

 cCampos["nombredecampo"]

Que es la sintaxis exacta para referenciar un campo de un Result.

Si quieres pasar la colección como variable a una función, también puedes hacerlo con el result, blablabla(rs as result) sería suficiente.

Saludos

No podemos regresar
[-] Los siguientes 1 usuarios dice gracias a Shordi por este post:
  • gartumar2
    ¡Gracias!
#4

Pues el tema sería algo aproximado a esto:

Imagina una bdd con mas de 30 tablas, de diversa índole, en las que unas tienen apenas dos columnas, pero otras pueden llegar a las 80 columnas. Las filas pueden llegar a ser varios miles por tabla. Esta información se procesa tanto por personas, como por diversos procesos del programa. Dependiendo de ciertos criterios unas filas serán procesadas en un sitio y otras en otros y saltaran así de proceso en proceso, recibiendo algunos cambios y acabando, según criterios en una impresora o en otra en la que imprimirá la fila completa. Por tanto no es óptimo ir repartiendo el result completo de proceso en proceso, la unidad óptima de información a manejar es la fila. Si para una tabla de 80 columnas tengo que hacer res["campo1"], res["campo2"].......res["campo80"]  Me tiro al suelo y me hago el muerto.
Además de que estamos dando por supuesto que conozco el nombre de los campos (que no) y de que no se van a añadir nuevas tablas en el futuro (cosa que con toda seguridad ocurrirá).

Por todo esto quería saber si había alguna manera de extraer un objeto registro del result, pero no se puede (o no he sabido encontrar cómo). Según medio he entendido, el result no es una colección de filas, sino mas bien, un registro de punteros a los campos de las filas y columnas de la tabla para así poder hacer temas de bloqueos, semáforos y cosas de esas raras que hacen los que saben de esto. Por todo ello, la opción de extraer la fila del result y convertirla en una colección, por ahora, me parece la ideal, aunque se comerá algunos recursos, pero no es crítico.

Gracias, por el interés. Y sigo abierto a sugerencias.
    ¡Gracias!
#5

Cita:Por todo esto quería saber si había alguna manera de extraer un objeto registro del result, pero no se puede (o no he sabido encontrar cómo).
Efectivamente, no se puede... pero ¿Qué inconveniente hay en extraerlo de la BDD en cada proceso? Para eso están la BBDD precisamente... salvo que me hables de una BDD no estructurada, sin índices o de un tipo ODBC, no entiendo muy bien la lógica del asunto. ¿Sacas una selección de las tablas a una colección que pasas a distintos procesos y personas (persona = dispositivo de input-output  con 50 bits por segundo de velocidad de proceso Big Grin Big Grin ) todo en ram y luego lo vuelves a grabar todo a la BDD?
¿Qué inconveniente hay para que cada proceso o persona no pueda extraer la información precisa que necesita de la BDD?

Pero bueno, no me hagas caso, me suena que trabajas sobre algo ya muy consolidado y difícil de replantear... tú sabrás qué es lo mejor.

Saludos

Se me olvidaba. Es un obviedad, pero en los métodos de la clase Connection, tienes Exec, que pasa la consulta SQL directamente a la BDD. Suele ser más rápido y claro de leer en el código. El inconveniente respecto a Result.Find, etc. es que escribiendo

GAMBAS
  1. miresult = miconexion.Exec("Select * from Tabla1 where campo1 = &1", "XXX")
  2.  
  3. 'o también
  4.  
  5. miconexion.Exec("Update mitabla set campo1 = &1 where campo1 = &2" ,"XXX","ZZZ")



ahorras mucho  tecleo y ganas claridad peroestás atando el código al dialecto concreto de SQL de esa BDD en concreto, con lo que tu aplicación pierde portabilidad y flexibilidad. Como programador profesional de gambas durante más de 20 años en el mundo empresarial, la experiencia me dice que las empresas raramente se lanzan a cambiar su base de datos. Si usan MySQL (o MariaBD, que es lo mismo) se mantendrán fieles a eso, si PostGreSQL pues PostGreSQL (y si Oracle... mejor no uses gambas que estarás condenado al infierno ODBC).
Por tanto, si ese es tu caso, no seas tímido con el .Exec, que facilita mucho todas las operaciones sobre las bases de datos.

Saludos.

No podemos regresar
[-] Los siguientes 1 usuarios dice gracias a Shordi por este post:
  • gartumar2
    ¡Gracias!
#6

(16-11-2022, 01:23)gartumar2 escribió:  Por tanto no es óptimo ir repartiendo el result completo de proceso en proceso, la unidad óptima de información a manejar es la fila.

Bien, he estudiado un poco el código que pasaste, es evidente que deseas minimizar las consultas a la base de datos. Si esto es correcto la forma que usas para manejar los datos del registro es correcta desde mi punto de vista (tal vez JSONCOllection sea mas conveniente que Collection).
El método COPIA tiene la desventaja de que los datos que "copias" a la colección pueden estar desfasados con respecto a los datos de la BD si alguien mas (persona o proceso) altera el mismo registro al mismo tiempo (El que guarde ultimo "pisara" los datos) o si la tabla es una tabla relacional que apunta a un registro que no existe en la base porque este fue eliminado al mismo tiempo que se trabaja con una copia.
Pero presenta la ventaja de no depender del estado de conexión con la base de datos.
Finalmente,  alteré tu mismo código para plantear la idea de como guardar los datos sirviéndose de una colección de copia para hacer la comparación.
GAMBAS
  1.  
  2. Public Sub Form_Open()
  3.  
  4.   Dim rDatos As Result
  5.   Dim cRegistro As New Collection
  6.   Dim rTest As Result
  7.   Dim tb As Table
  8.   Dim pk As String[]
  9.  
  10.   rDatos = db.Find("tabla1")
  11.   tb = db.Tables["tabla1"]
  12.   pk = tb.PrimaryKey
  13.   If pk.Count > 0 Then
  14.     sPK = pk[0]
  15.   Else
  16.     sPK = ""
  17.  
  18.   While rDatos.Available
  19.     For Each RF In rDatos.Fields
  20.       cRegistro.Add(rDatos[RF.name], RF.name)
  21.     Next
  22.     blabla(cRegistro.Copy()) '' Siempre usa el método .Copy() ya que si pasas un objeto como parametro en realidad lo que esas pasando es la direccion en memoria del objeto.
  23.     cRegistro.Clear
  24.     rDatos.MoveNext
  25.   Wend
  26.  
  27.  
  28. Private Sub blabla(data As Collection)
  29.  
  30.   cBorrador = data.Copy() '' Acá creas una copia para usar luego.
  31.   '' Acá altearás los datos en algún proceso o formulario en la colección "data" y al tener la copia contra la que comparar al momento de guardar los cambios en la BD solo en caso que estos existan. También podes alterar algún campo que uses como marca temporal o cosas así.
  32.  
  33.  
  34.  
  35.   Dim cCambios As New Collection
  36.  
  37.   If sPK <> "" Then
  38.     cCambios.Add(data[sPK], sPK) '' Agregando el campo de la clave primaria y su valor
  39.     For Each v In data
  40.       If data[data.Key] <> sPK Then
  41.         If data[data.Key] <> cBorrador[data.Key] Then
  42.           cCambios.Add(v, data.Key)
  43.         Endif
  44.       Endif
  45.     Next
  46.  
  47.     If cCambios.count > 1 Then
  48.       Print "Los datos cambiaron"
  49.       ''Guardar los cambios en la base de datos.
  50.     Endif
  51.  



Nota: Para poner código en un mensaje seria mejor si usas el botón con el logo de gambas (el ultimo) y escribe gambas cuando aparezca la caja de dialogo.

1 Saludo.
[-] Los siguientes 1 usuarios dice gracias a tincho por este post:
  • gartumar2
    ¡Gracias!
#7

Clara y razonada respuesta, gracias.

Por supuesto también uso Exec. El uso de los procesos que brinda la Connection (Find, Create, Delete, ..) los uso por comodidad (pereza de tecleo y de pensar la sentencia sql). Cuando la consulta se complica, SQL puro y duro.

La consulta sobre la extracción del registro del Result era más curiosidad de novato que otra cosa. Los que acabamos de llegar a Gambas tenemos que preguntar para aprender. Es la mejor forma.

Un saludo, grande.
[-] Los siguientes 1 usuarios dice gracias a gartumar2 por este post:
  • Shordi
    ¡Gracias!
#8

Otro tema a tener en cuenta es el de las tablas relacionales y las claves foráneas.
Si por ejemplo tenés estas tablas:
| id | programa | licencia|
|----|---------------------------|---------|
| 1 | Gambas3 | 1 |
| 2 | Firefox | 2 |
| 3 | VirtualBox Extension Pack | 3 |
 
| id | licencia | texto |
|----|----------|-----------------------------------------------------------------|
| 1 | GPL v2 | GNU General Public License 2.1 |
| 2 | MPL | Mozilla Public License 2.0 |
| 3 | PUEL | VirtualBox Extension Pack Personal Use and Evaluation License |


¿Que valor vas a poner en el campo "licencia" de la tabla "programas"?  ¿Por ejemplo 1 o GPL v2 ?
  • Si usas "1" de todas maneras vas a tener que consultar la base de datos para saber que valor esta asociado a la clave "1".
  • Si usas "GPL v2" cuando guardes los datos tendras que convertir "GPL v2" en "1"

1 Saludo.
[-] Los siguientes 1 usuarios dice gracias a tincho por este post:
  • gartumar2
    ¡Gracias!
#9

Como decía Jack El Destripador: vayamos por partes.

1) No se coman más la cabeza con esto, era más una duda existencial que un problema en sí mismo.

2)
Cita:¿Que valor vas a poner en el campo "licencia" de la tabla "programas"?  ¿Por ejemplo 1 o GPL v2 ?
  • Si usas "1" de todas maneras vas a tener que consultar la base de datos para saber que valor esta asociado a la clave "1".
  • Si usas "GPL v2" cuando guardes los datos tendras que convertir "GPL v2" en "1"

Pues para algo así, y dependiendo de lo que se necesite, lo primero que haría seria tener en la bdd una vista creada VISTAxx mas o menos así: SELECT t1.*, (SELECT t2.id as licId, t2.licencia (o texto si es lo que me interesa, o los dos) as licLic (o licTexto) FROM tabla2 t2 WHERE t1.licencia = t2.id) FROM tabla1 t1 WHERE loquesea ORDER BY loquesea;
Crearía el result con SELECT * FROM VISTAxx WHERE loquenecesite; (el order by ya lo hace la vista) y en cada registro tengo los campos de la tabla 1 y los asociados de la tabla 2. Cuando tengo que grabar tengo todo disponible y a mano. Para modificaciones, pues si las necesidades del proceso lo permiten, le paso el marrón a la bdd con RESTRICT, CASCADE, o lo que convenga.

Saludos, de nuevo.
    ¡Gracias!


Posibles temas similares…
Tema / Autor Respuestas Vistas Último mensaje

Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)