none
recorrer una tabla registro a registro

    Question

  • tengo una tabla en access que tiene 3 campos que me interesan: nam0orden, aam0ira, aam0codigo

    quisiera recorrerla desde el ultimo registro hasta el primero

    está ordenada por nam0orden, se me ocurrió ordenarla descendentemente e ir al TOP 1

    he leido que deberia usar un dataReader

    int nwm0orden = 0; string awm0codigo; string awm0ira; cmd.CommandText = "SELECT TOP 1 nam0orden, aam0codigo, aam0ira FROM menus order by nam0orden desc"; OleDbDataReader myReader = cmd.ExecuteReader(); try {

    // aqui leo el último registro e inicializo las variables de memoria myReader.Read(); nwm0orden = myReader.GetInt32(0); awm0codigo = myReader.GetString(1); awm0ira = myReader.GetString(2);

    // este select que sigue me da todos los registros, pero yo quiero el siguiente que en realidad

    // es el anterior, no el siguiente, debido a esto el while nunca se ejecuta cmd.CommandText = "SELECT nam0orden, aam0codigo, aam0ira FROM menus order by nam0orden desc "; while (myReader.Read()) { if (awm0ira == null) { awm0ira = awm0codigo; //grabo cmd.CommandText = "update from menus set (aam0ira) value ("+ awm0ira +")"; cmd.ExecuteNonQuery(); } myReader.Read(); nwm0orden = myReader.GetInt32(0); awm0codigo = myReader.GetString(1); awm0ira = myReader.GetString(2); } myReader.Close(); } catch (Exception ex) { rt1.Text = ex.Message; }



    Friday, February 08, 2013 5:57 AM

All replies

  • pero si usas el TOP 1 solo recuperas un unico registro, para que quieres recorrerla, usa directo un if en lugar del while

    en lugar de

    while (myReader.Read())

    usa

     if(myReader.Read())      

    -------

    ademas alli en el codigo veo algo que no tiene sentido, porque usas primero un SEELCT con el TOP1 pero despues tienes otro que recupera toda la tabla

    la verdad ese codigo no tiene ningun sentido

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Friday, February 08, 2013 7:40 AM
  • tienes razon este codigo no tiene sentido asi como está.

    por eso les estaba pidiendo ayuda, para ver como lo cambio y que haga lo que quiero, que es recorrer la tabla desde el último registro hasta el primero.

    con el top 1 y estando ordenada en orden descendente: consigo leer el último registro.

    pero no pude resolver el leer el anterior a ese, no pude escribir una sentencia que dijera: leer el siguiente y que la base este ordenada descendentemente.

    creo que parte del problema es que necesitaria un archivo con la SINTAXIS de las sentencias SQL, existe ?????

    podrian decirme que correcciones le debo hacer a este codigo para obtener como resultado recorrer el archivo desde su ultimo registro hasta el primero ?????

    Friday, February 08, 2013 6:56 PM
  • con el top 1 y estando ordenada en orden descendente: consigo leer el último registro.

    pero si la idea es recorrer todos los registros com se relaciona esto con obtener el ultimo ?

    porque son dos acciones separadas

    estas recorriendo de forma correcta el reader usando el

    while (myReader.Read())

    pero recuerda que esto puede devolver varios registros, asignarlo a una variable quizas no sea lo correcto, deberias suar una lista

    [WinForms] Edición Empleados

    analiza la capa de datos de este ejemplo

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Friday, February 08, 2013 7:05 PM
  • public void RellenarVacios()
            {
                int nwm0orden = 0;
                string awm0codigo;
                string awm0ira;
                cmd.CommandText = "SELECT       nam0orden, aam0codigo, aam0ira FROM menus ORDER BY nam0orden desc";            
                OleDbDataReader myReader = cmd.ExecuteReader();
                try
                {
                    myReader.Read();
                    nwm0orden = Convert.ToInt32(myReader["nam0orden"]);
                    awm0codigo = Convert.ToString(myReader["aam0codigo"]);
                    awm0ira = Convert.ToString(myReader["aam0ira"]);
    
                    while (myReader.Read())                     
                    {
                        awm0ira = Convert.ToString(myReader["aam0ira"]);
                        nwm0orden = Convert.ToInt32(myReader["nam0orden"]);
                        if (awm0ira == "                    ")
                        {
                            awm0ira = awm0codigo;
                            //grabo
                            cmd1.Connection = conn;                        
                            cmd1.CommandText = "UPDATE menus SET aam0ira = '"+ awm0codigo +"' WHERE nam0orden = "+ nwm0orden;
                            cmd1.ExecuteNonQuery();
                        }                   
                        awm0codigo = Convert.ToString(myReader["aam0codigo"]);                    
                    }
                    myReader.Close();
                }
                catch (Exception ex)
                {
                    rt1.Text = ex.Message;
                }
            }

    gracias Leandro

    me guiaste a conseguir mi pescado

    esta es la solución de mi problema, por lo menos una que funciona.

    tenia errores en la sintaxis del UPDATE.

    es correcto que para recorrer usara el READER y que para grabar utilizara el ExecuteNonQuery ???? 

    mi problema es que necesito un archivo con la sintaxis de las sentencias SQL para ACCESS, podrias indicarme donde lo consigo ????

    Friday, February 08, 2013 8:48 PM
  • es correcto que para recorrer usara el READER y que para grabar utilizara el ExecuteNonQuery ?

    se podria pero ojo porque ado.net no permite tener mas de un reader abierto si recorres y actualizas podrias tener problemas

    quizas para esto seria mejor cargar un datatable para recorrerlo, ashi si vas a poder realziar un update mientras recorres

    mi problema es que necesito un archivo con la sintaxis de las sentencias SQL para ACCESS, podrias indicarme donde lo consigo ?

    son bastante parecidos a los de SQL Server aunque quizas algo como esto ayude

    Data Manipulation Language

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Friday, February 08, 2013 8:53 PM
  • funciono perfecto el código que puse último.

    utilice estas sentencias:

     cmd.CommandText = "SELECT       nam0orden, aam0codigo, aam0ira FROM menus ORDER BY nam0orden desc";  

    cmd1.CommandText = "UPDATE menus SET aam0ira = '"+ awm0codigo +"' WHERE nam0orden = "+ nwm0orden;

    por tuve que usar dos variables cmd y cmd1

    por ahi lei que el reader no puede hacer UPDATE es correcto ????

    usar el datatable significa que tengo que leer toda la tabla y luego trabajarla en memoria ???? realmente es una tentación, pero creo que debo ahorrar en memoria, tiempo de transferencia, con vista a hacer programas que funcionen en web, que opinas ????

    Friday, February 08, 2013 10:10 PM
  • el UPDATE no esta correcto, concatenar los valores en un string no esta bien, tienes que suar parametros

    string query = "UPDATE menus SET aam0ira = @param WHERE nam0orden = @orden";
    
    OleDbCommand cmd1 = new OleDbCommand(query, conn);
    cmd1.Parameters.AddWithValue("@param", awm0codigo);
    cmd1.Parameters.AddWithValue("@orden", nwm0orden);



    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Friday, February 08, 2013 11:36 PM
  • usar el datatable significa que tengo que leer toda la tabla y luego trabajarla en memoria ?

    exacto, usas el OleDbDataAdapter para hacer un Fill() en un datatable

    con vista a hacer programas que funcionen en web, que opinas ?

    depende de la cantidad de datos que tengas, si son poco registros no creo que usar un datatable afecte a al performance

    ahora si son varios miles quizas se podria evaluar

    si la db seria sql server se podria mantener el reader y actualizar pero si es otra la db puede que no lo soporte


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Friday, February 08, 2013 11:38 PM
  • Hola McGiver,

    Creo que la modificación que quieres hacer puedes hacerla de un tiro a la BD con un sólo ExecuteNonQuery. Esto te permitiria no cargar datos ni nada y sería casi instantáneo.

    ¿Puedes explicar qué es realmente lo que quieres resolver? ¿Qué Sistema Gestor de BD estás usando? ¿SQLServer 2012?

    Saludos


    @XaviPaper
    http://geeks.ms/blogs/xavipaper

    Friday, February 08, 2013 11:59 PM
  • Hola Xavi, mi apodo es Macgyber (con b) jeje

    te cuento yo tengo una tabla en access que tiene varios campos

    nam0orden indice, secuencial, numerico, ascendente

    aam0ira a veces tiene un string y otras esta VACIO

    aam0codigo siempre tiene un string

    lo que quiero es cuando aam0ira == "   " > rellenarlo con el contenido de aam0codigo pero el del registro siguiente

    me puse como condición no leer la tabla en memoria

    la solucion que se me ocurrio es leer la tabla desde el ultimo registro al primero mediante un datareader

    a medida que leo voy guardando el aam0codigo por si lo preciso cuando lea el registro siguiente que seria el anterior

    si al leer un registro encuentro que aam0ira == "    " entonces lo relleno con el aam0codigo que guarde en awm0codigo

    es aqui donde lo grabo con un ExecuteNonQuery

    tenia problemas con la sintaxis del SELECT y del UPDATE pero al final lo solucione, cuentame que se te ocurre a ti ????

    Saturday, February 09, 2013 2:39 AM
  • Hola Leandro Tuttini

    Mis programas tienen la cualidad de ser sencillo, intuitivo, RAPIDO, barato, pequeño, SEGURO, sin errores, exacto.

    Entonces debo cuidar el tema de la rapidez y la seguridad, por eso es que no comparto mucho el trabajar con los datos en memoria.

    RAPIDO

    Tengo un programa que demora 8'' en ingresar un asiento contable, mi competidor demora 24'', parece insignificante, pero en caso de tener que meter un volumen muy grande de asientos podrian ser 8 hs. contra 24 hs.

    SEGURO

    Por otro lado en mi programa si surge un problema (apagon, cuelgue, ...) lo que se pierde es a lo sumo el ultimo asiento ingresado, en cambio en el producto de mi colega es necesario cada cierta cantidad de registros salir del datagrid de ingreso de datos para que todos los datos se graben, cuand sucede el imprevisto se pierde todo lo ingresado desde la ultima vez que se entro.

    Por eso mi interés en solucionar por este camino en particular el problema.

    Saturday, February 09, 2013 2:51 AM
  • lo que quiero es cuando aam0ira == "   " > rellenarlo con el contenido de aam0codigo pero el del registro siguiente

    el problema aqui es justamente como determians el registro siguiente, ahi esta el tema

    es mas si es el ultimo registro el siguiente cual seria ?

    se me ocurre una unia instruccion del update como ser

    UPDATE menus SET aam0ira= (SELECT TOP 1 aam0codigo FROM menus m WHERE m.nam0orden = (menus.nam0orden +1))
    WHERE menus.aam0ira = ' '

    ojo no la he probado, es solo una idea

    el tema hay que ver si al hacer el

    WHERE m.nam0orden = (menus.nam0orden +1)

    este registro no tiene el codigo en vacio, imagine que el campo codigo tine todos datos validos

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Saturday, February 09, 2013 6:53 AM
  • Hola MacGiber,

    Me lo has complicado, eh? En principio creia que era para SQLServer y por tanto la solución no es muy complicada:

    UPDATE M1
    SET aam0ira = (
    	SELECT TOP 1 M2.aam0codigo
    	FROM menus M2
    	WHERE M2.nam0orden > M1.nam0orden
    	ORDER BY M2.nam0orden
    )
    FROM menus M1
    WHERE RTRIM(M1.aam0ira) = ''

    Creo que la SQL es auto explicativa.

    Sin embargo en Access no se puede poner a la derecha de la asignación una subconsulta... arrrrg. Para solucionar este problema he tenido que hacer lo siguiente:

    UPDATE menus M1, menus M2
    SET M1.aam0ira = M2.aam0codigo
    WHERE 
      RTRIM(M1.aam0ira) = '' AND
      M2.nam0orden > M1.nam0orden AND
      NOT EXISTS(
        SELECT *
        FROM menus M3
        WHERE 
          M3.nam0orden > M1.nam0orden AND
          M3.nam0orden < M2.nam0orden
      )
    

    La jugada pasa por seleccionar en M2 la línea siguiente. Para ello tenemos que asegurar que no hay ninguna fila (M3) que esté entre la fila que queremos modificar (M1) y de la que pillamos el valor (M2).

    Esto lo puedes lanzar directamente desde un ExecuteNonQuery y debería funcionar...

    Pruebalo a ver y pregunta si no acaba de funcionar


    @XaviPaper
    http://geeks.ms/blogs/xavipaper

    Saturday, February 09, 2013 11:49 PM