none
Como actualizar registros consecutivamente?

    Pregunta

  • Buenas tardes compañeros, vengo a solicitar ayuda pues estoy bloqueado jaja

    No conozco muy bien el lenguaje de transact sql, apenas estoy iniciando como programador en .net y mas reciente en sql server por eso solicito esto:

    Tengo una tabla con 5 campos que tienen 1000 registros, estos tienen una columna de campo incremental (id) y las demás.. Recién agregué otro campo a la tabla y necesito actualizar esos 1000 registros de manera secuencial, el porqué? porque en el campo 4 de mi tabla tengo valores que me permiten agrupar los registros en, digamos, sucursales diferentes y el 6to campo será un folio secuencial que será incrementado independientemente para cada sucursal, bien lo que quiero hacer es un ciclo donde actualizo esos registros, por lo menos para una de las sucursales..

    He intentado seguir la lógica de un ciclo normal para x lenguaje pero aun no entiendo por completo el comportamiento del SELECT dentro de consultas de update ni nada parecido, intentando usar WHILE para hacer esto recibí innumerables cantidades de errores diciendome que lo estoy haciendo mal jaja.

    Espero puedan ayudarme, o quizá para entender como funciona estos select dentro de otras consultas u operaciones, se los agradeceré.

    Saludos


    Creando el entorno de la aplicación...

    sábado, 09 de junio de 2012 20:13

Respuestas

  • With t
    As
    (
        Select
            *
            , Row_Number() Over (Partition By CuartoCampo Order By ID) As [RID]
        From 
            tabla
    )
    Update tabla
    Set SextoCampo = t.RID
    From
        tabla
        Inner Join
        t
        On tabla.ID = t.ID
    ;

    Eso debería funcionar, si es que entendí bien la pregunta y si usted está usando SQL Server 2005 o superior.

    Pruébelo en una base de datos de prueba antes de aplicarlo en producción.  No quiero que me digan que destruyó sus datos por mi culpa, jeje.

    Como nota adicional, le recuerdo que este tipo de numeración de folio por sucursal como lo describe usted requiere sincronización externa en caso de aplicaciones multiusuario.


    Jose R. MCP

    sábado, 09 de junio de 2012 20:41

Todas las respuestas

  • With t
    As
    (
        Select
            *
            , Row_Number() Over (Partition By CuartoCampo Order By ID) As [RID]
        From 
            tabla
    )
    Update tabla
    Set SextoCampo = t.RID
    From
        tabla
        Inner Join
        t
        On tabla.ID = t.ID
    ;

    Eso debería funcionar, si es que entendí bien la pregunta y si usted está usando SQL Server 2005 o superior.

    Pruébelo en una base de datos de prueba antes de aplicarlo en producción.  No quiero que me digan que destruyó sus datos por mi culpa, jeje.

    Como nota adicional, le recuerdo que este tipo de numeración de folio por sucursal como lo describe usted requiere sincronización externa en caso de aplicaciones multiusuario.


    Jose R. MCP

    sábado, 09 de junio de 2012 20:41
  • Me parece que el Inner Join es redundante,
    y se puede actualizar conjunto T (=t) directamente.

    Blog: http://about.me/GeriReshef

    domingo, 10 de junio de 2012 4:13
  • Puede ser.  Lo puse ahí porque la tabla t no es realmente la tabla llamada 'tabla', así que realmente no tiene el campo RID, así que pienso que el join es necesario para poner las cosas en orden.  A menos claro que yo esté subestimando a SQL Server y que más bien sea lo suficientemente astuto para entender que t contiene a tabla y que la correspondencia es uno a uno.  En fin, no tengo datos para probar ahora mismo, así que esperemos que Moisés nos cuente.

    Jose R. MCP

    domingo, 10 de junio de 2012 7:24
  • With t
    As
    (
        Select
            *
            , Row_Number() Over (Partition By CuartoCampo Order By ID) As [RID]
        From 
            tabla
    )
    Update tabla
    Set SextoCampo = t.RID
    From
        tabla
        Inner Join
        t
        On tabla.ID = t.ID
    ;

    Eso debería funcionar, si es que entendí bien la pregunta y si usted está usando SQL Server 2005 o superior.

    Pruébelo en una base de datos de prueba antes de aplicarlo en producción.  No quiero que me digan que destruyó sus datos por mi culpa, jeje.

    Como nota adicional, le recuerdo que este tipo de numeración de folio por sucursal como lo describe usted requiere sincronización externa en caso de aplicaciones multiusuario.


    Jose R. MCP

    Compañero muchas gracias, esto me quedó como anillo al dedo, la verdad intenté de varias formas pero ninguna me resultó.

    Entonces aquí, numeras todos los registros ordenados en una nueva tabla (t), pero como funciona la segunda parte? actualizas la primera tabla con respecto a t pero el INNER JOIN como funciona en esta consulta?

    Gracias de nuevo compañero


    Creando el entorno de la aplicación...

    lunes, 11 de junio de 2012 16:17
  • La tabla t es una tabla temporal que existe únicamente durante la ejecuión de la sentencia UPDATE que se ve ahí.  Le recomiendo aprender esta nueva sintaxis que es sumamente útil.

    En fin, creamos la tabla temporal t que se encarga de asignar la nueva numeración a cada registro según la partición y el ordenamiento indicado.  Pero claro, esto es una construcción temporal y este nuevo campo NO existe en la tabla, así que hay que trasladar estos valores calculados a la tabla.  Para eso es el UPDATE.

    El update simplemente actualiza la columna del nuevo campo con el valor calculado en la tabla temporal.  El Inner Join está ahí para asegurarse que se utilice el valor calculado para ese registro particular y no para cualquier otro.  Recordemos que la unión de dos tablas sin una condición produce la "multiplicación" de los registros de ambas tablas y no es lo que se quiere aquí.


    Jose R. MCP
    Code Samples

    lunes, 11 de junio de 2012 16:21
  • webJose, hace rato creí haber revisado bien lo que me sugieres y te agradezco por la ayuda pero debo pedirte que me apoyes de nuevo pues en el momento que ejecuté la operación parecía que mi columna ya estaba con los números correspondían (no lo vi bien y la consulta no me generó errores), el hecho es que no se hizo cambio alguno sobre mi columna, ejecuté de nuevo la consulta y me indica "(0 row(s) affected)", ahorita le cambié un poco a la estructura que me sugeriste quedando así:

    with t
    as 
    (
    	select *,
    	row_number() over (partition by sucursal order by TablaID) as ID
    	from Tabla
    )
    select Tabla.ID, t.sucursal
    from Tabla
    inner join t on Tabla.Folio=t.ID;
    y el resultado no tiene ningún registro, quizá y creo suponer (si estoy mal corrigeme por favor), cuando hacemos el inner join no se enlaza ningún campo pues ninguna de las 2 columnas de las 2 tablas (Tabla y t) coincide, coincidirían hasta después de que se haga el update..

    Creando el entorno de la aplicación...



    lunes, 11 de junio de 2012 19:43
  • No entiendo lo que hizo.  Muestre la sentencia UPDATE que usted utilizó para actualizar los datos del sexto campo.

    Jose R. MCP
    Code Samples

    lunes, 11 de junio de 2012 19:51
  • Gracias por responder webJose, la consulta que ejecuto es la siguiente:

    with t
    as (select *, row_number() over (partition by idbase order by idmaster) as ID from master)
    update master
    set master.folio=t.ID
    from master
    inner join t
    on master.folio=t.ID

    pero el resultado es (0 row(s) affected) y no me modifica ningún registro de la columna ;(


    Creando el entorno de la aplicación...


    lunes, 11 de junio de 2012 20:50
  • Está mal la última línea.  El campo folio está vacío.  Justamente queremos llenarlo, así que ese JOIN nunca dará ningún registro.  Es On master.<clave primaria> = t.<clave primaria>.


    Jose R. MCP
    Code Samples

    lunes, 11 de junio de 2012 20:55
  • Claro, como no me fije... Ahora si jeje gracias Jose, te agradezco mucho, en serio..

    Saludos! :D


    Creando el entorno de la aplicación...

    lunes, 11 de junio de 2012 20:58