Ir al contenido


Foto

Update restar campos Time


  • Por favor identifícate para responder
8 respuestas en este tema

#1 elarys

elarys

    Newbie

  • Miembros
  • Pip
  • 9 mensajes

Escrito 18 abril 2013 - 09:58

Hola estoy migrando de MySql a Firebird y me trabe en Update

Tengo estas 3 tablas las resumo para el caso


CREATE TABLE CATEGORIA
(
  IDGRUPO Smallint NOT NULL,
  GRUPOS Varchar(10),
  RESTAR Time,
  PRIMARY KEY (IDGRUPO)
);

CREATE TABLE REGISTRO
(
  CODIGO Smallint NOT NULL,
  NOMBRE Varchar(20),
  GRUPO Smallint,
  TIEMPO Time,
  PRIMARY KEY (CODIGO)
);

CREATE TABLE TIEMPOS
(
  IDTIME Smallint NOT NULL,
  TIEMPO Time,
  CODIGO Smallint,
  PRIMARY KEY (IDTIME)
);


Esta es mi consulta en MySql 5.5 que funciona correctamente


UPDATE REGISTRO R
INNER JOIN CATEGORIA C ON (R.GRUPO = C.IDGRUPO)
INNER JOIN TIEMPOS T ON (R.CODIGO = T.CODIGO)
SET R.TIEMPO = (T.TIEMPO - C.RESTAR)
WHERE R.CODIGO > 0


Pero en Firebird no le gusta el INNER JOIN y da el siguiente error

Error: *** IBPP::SQLException ***
Context: Statement::Prepare( UPDATE REGISTRO R
INNER JOIN CATEGORIA C ON (R.GRUPOS = C.GRUPOS)
INNER JOIN TIEMPOS T ON (R.NUMERO = T.NUMERO)
SET R.TIEMPO = (T.TIEMPO - C.RESTAR)
WHERE R.NUMERO > 0 )
Message: isc_dsql_prepare failed

SQL Message : -104
Invalid token

Engine Code : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 2, column 1
INNER

Me dijeron por ahi que use subconsultas, alguna idea

Ademas necesito que esa resta sea Formateada en (HH:MM:SS.ZZZ)
Hora, minutos, segundos y centesimas, osea pasarlo a campo de tipo Time
  • 0

#2 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 18 abril 2013 - 10:12

Buenas,

Correcto, la respuesta tu mismo la has dado, hacer subconsultas, en este caso sería algo así


UPDATE REGISTRO R
SET R.TIEMPO = ((select T.TIEMPO from TIEMPOS T where R.CODIGO = T.CODIGO) - (select C.RESTAR from CATEGORIA C where R.GRUPO = C.IDGRUPO)
WHERE R.CODIGO > 0


Salvo error u omisión

Nos leemos

  • 0

#3 elarys

elarys

    Newbie

  • Miembros
  • Pip
  • 9 mensajes

Escrito 19 abril 2013 - 06:24

Gracias, pero me da error

Message: isc_dsql_execute2 failed

SQL Message : -413
Overflow occurred during data type conversion.

Engine Code : 335544334
Engine Message :
conversion error from string "4753.6180"
At procedure 'DIFERENCIA' line: 8, col: 3

UPDATE REGISTRO R
SET R.TIEMPO = (
(SELECT T.TIEMPO FROM TIEMPOS T WHERE R.CODIGO = T.CODIGO) -
(SELECT C.RESTAR FROM CATEGORIA C WHERE R.GRUPO = C.IDGRUPO))
WHERE R.CODIGO > 0


Tabla Registro ejemplo
52 | PEPE | 1 | [null]
53 | JUAN | 1 | [null]


Tabla Tiempos ejemplo
1 | 01:24:13.618 | 52
2 | 01:54:25.618 | 53


Tabla Categoria ejemplo
1 | Grupo A | 00:05:00.000


Resultado del Update deberia ser
52 | PEPE | 1 | 01:19:13.618
53 | JUAN | 1 | 01:49:25.618

  • 0

#4 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 19 abril 2013 - 08:13

A ver, ¿tienes un procedimiento llamado Diferencia?, si es asi, coloca el procedimiento completo aqui.

Saludos.
  • 0

#5 elarys

elarys

    Newbie

  • Miembros
  • Pip
  • 9 mensajes

Escrito 19 abril 2013 - 08:18

Si pero con el update que plantie arriba o este procedimiento el error es el mismo
conversion error from string "4753.6180"

SET TERM ^ ;

create or alter procedure DIFERENCIA
as
declare variable CODIGO smallint;
declare variable TIEMPO_DIFERENCIA time;
begin
  for select registro.codigo,
          tiempos.tiempo - categoria.restar
    from  registro
    inner join categoria on (registro.grupo = categoria.idgrupo)
    inner join tiempos  on (registro.codigo = tiempos.codigo)
    into  :codigo,
          :tiempo_diferencia
  do begin
    update registro
    set    registro.tiempo = :tiempo_diferencia
    where  registro.codigo = :codigo;
  end
end^
SET TERM ; ^

  • 0

#6 elarys

elarys

    Newbie

  • Miembros
  • Pip
  • 9 mensajes

Escrito 19 abril 2013 - 08:23

Me plantean tomar los campos de tipo Time asi, separar hora, minutos, segundos y milesimas
Todavia no probe este procedimiento, estoy en otra pc, luego la pruebo y veo como va.

SET TERM ^ ;

create or alter procedure DIFERENCIA
as
declare variable CODIGO smallint;
declare variable TIEMPO_FINAL time;
declare variable TIEMPO_DIFERENCIA double precision;
declare variable HORAS smallint;
declare variable MINUTOS smallint;
declare variable SEGUNDOS smallint;
declare variable MILESIMAS smallint;
begin
  for select registro.codigo,
            tiempos.tiempo - categoria.restar
    from  registro
    inner join categoria on (registro.grupo = categoria.idgrupo)
    inner join tiempos  on (registro.codigo = tiempos.codigo)
    into  :codigo,
          :tiempo_diferencia
  do begin
    -- La diferencia de dos datos de tipo time es el numero de segundos
    -- en formato deciamal(9,4), debe entonces hacerse la conversion
    horas    = cast ((tiempo_diferencia / 3600.0) as smallint);
    tiempo_diferencia = tiempo_diferencia - (horas  * 3600);
    minutos  = cast ((tiempo_diferencia /  60.0) as smallint);
    tiempo_diferencia = tiempo_diferencia - (minutos *  60);
    segundos = cast ((tiempo_diferencia        ) as smallint);
    tiempo_diferencia = tiempo_diferencia - (segundos      );
    milesimas = cast (tiempo_diferencia * 1000 as smallint);

    tiempo_final =  cast
                    (
                              cast(horas    as varchar(2))
                    || ':' || cast(minutos  as varchar(2))
                    || ':' || cast(segundos  as varchar(2))
                    || ':' || cast(milesimas as varchar(4))
                    as time
                    );
    update registro
    set    registro.tiempo = :tiempo_final
    where  registro.codigo = :codigo;
  end
end

^

SET TERM ; ^

  • 0

#7 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 19 abril 2013 - 08:33

Pues como indica el error, es un problema de convsersión, estas intentando ingresar un valor string en un campo que no lo es, debes revisar bien donde está el problema, si es en la entrada o el tipo de datos del campo.

Saludos.
  • 0

#8 elarys

elarys

    Newbie

  • Miembros
  • Pip
  • 9 mensajes

Escrito 19 abril 2013 - 08:55

Claro es un cambio de conversion fallido, pero yo no ingrese nada, lo datos los toma de lo que puse como ejemplo, y cuando quiere pasar no se cual sera 01:24:13.618 o 01:54:25.618 lo pasa a (9,4) 9 enteros y 4 decimales y da el valor 4753.6180, asi lo hace para hacer dicha resta, por eso me plantearon, manejarlo con el ultimo procedure que mostre, destripando como para decirlo de alguna manera, a los campos Time.

Ahora me planteo todo a codigo en vez de con una simple consulta.
Porque ya me llevo demasiado tiempo y no llego a un final favorable.
Y haciendo la programacion me dio el resultado esperado.
Si alguien lo desea posteo el codigo luego.
  • 0

#9 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 19 abril 2013 - 10:27

Veo dos cosas:

Primero, un time - time puede darte un time "imposible", imagina que a las 1h23m le restas 12h00m, te daría negativo, o si sumas, puede darte mas milisegundos de los que tiene un día, o si uno de los dos time esta null la operación te daría cosas raras.

En cualquier caso, el procedure que usas es muy complejo para solo restar un cierto time a todas las entradas, yo lo haría así (que por cierto, haciéndolo así no necesitas procedure en absoluto, pero es mejor tener el código dentro de la base de datos):


SET TERM ^ ;

CREATE OR ALTER PROCEDURE DIFERENCIA
AS
BEGIN
  UPDATE tiempos SET tiempos.tiempo = tiempos.tiempo -
    (select categoria.restar fom categoria where categoria.idgrupo=
      (select registro.grupo from registro where registro.codigo=tiempos.codigo))
END^
SET TERM ; ^

  • 0




IP.Board spam blocked by CleanTalk.