Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 17-02-2009
Avatar de CarlosHernandez
CarlosHernandez CarlosHernandez is offline
Miembro
 
Registrado: oct 2003
Posts: 139
Poder: 21
CarlosHernandez Va por buen camino
campo bdd integer, delphi string sin error

tengo un campo integer en firebird, pero en la programacion de delphi lo trato como un campo string, cuando realizo la busqueda me muestra el registro solicitado, mi duda es si en la tabla esta como integer y yo en delphi lo trato string porque igual lo muestra y lo amacena sin dar ningun tipo de error???

Código Delphi [-]
var
carnet,prestamo:string;
begin

with IBQuery1 do begin
close;
SQL.Clear;                                        //
SQL.Add('select * from Carnetvis where(ncarnet=:parnumc and tipocarnet='+QuotedStr(combobox2.Text)+')');
Prepare;
ParamByName('parnumc').Asstring:=edit1.text;
open;
carnet:=inttostr(fieldbyname('ncarnet').Asinteger);
prestamo:=fieldbyname('prestamo').AsString;
end;
Label1.caption:=carnet;

end;

pregunto por la curiosidad y ademas porque ya en mi sistema tengo el campo ncarnet varchar, y lo cambie a integer y el sistema funciona todo perfecto despues que actualizo los query dbexpress....
__________________
begin
Elverdugo79@hotmail.com
end;
Responder Con Cita
  #2  
Antiguo 17-02-2009
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por CarlosHernandez Ver Mensaje
si en la tabla esta como integer y yo en delphi lo trato string porque igual lo muestra y lo amacena sin dar ningun tipo de error???
Siempre y cuando introduzcas un número correcto, no tiene porque haber ningun problema. El método AsString convierte el dato textual al formato requerido por el campo subyacente.

Intenta colocar un texto que no corresponda a un número y seguro que ahí verás que sí hay error.

// Saludos
Responder Con Cita
  #3  
Antiguo 17-02-2009
Avatar de CarlosHernandez
CarlosHernandez CarlosHernandez is offline
Miembro
 
Registrado: oct 2003
Posts: 139
Poder: 21
CarlosHernandez Va por buen camino
gracias roman si ya lo probe y efectivamente me da el error, esto quiere decir que lo puedo trabajar en programacion de las dos forma (string e integer) sin error?? esto tambien pasa con otros tipos de datos??
__________________
begin
Elverdugo79@hotmail.com
end;
Responder Con Cita
  #4  
Antiguo 17-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Hola!

Cuando se trata de campos, las propiedades AsXXX ofrecen una manera muy eficaz de leer y asignar valores. Pero existe algo de considerar en las propiedades AsXXX de los parámetros, que explico en seguida.

Hace varios días, durante una asesoría a un colega, encontramos que había problemas con el método AsString de un parámetro al usar una sintaxis como:
Código Delphi [-]
ParamByName ('CampoNumerico').AsString := Edit1.Text;
Resulta que la base de datos era Paradox vía BDE, y al tratar de ejecutar la sentencia SQL el servidor la rechazaba por un problema de tipos. El campo era flotante, y, sólo por intentar algo diferente, sugerí cambiar la sentencia por:
Código Delphi [-]
ParamByName ('CampoNumerico').AsFloat := StrToFloat (Edit1.Text);
Y entonces funcionó.

En ese momento adjudiqué el problema por completo a la BDE. Pero leyendo ahora este hilo me entró la sospecha de algo relacionado a la propiedad DataType de los parámetros, y dicha sospecha se ha confirmado. Resulta que los métodos SetAsXXX de TParam, que son las rutinas de escritura de sus propiedades AsXXX, ¡cambian el valor de DataType en función de la propiedad usada para la asignación!

Código Delphi [-]
...
procedure TParam.SetAsBoolean(Value: Boolean);
begin
  FDataType := ftBoolean;
  Self.Value := Value;
end;

procedure TParam.SetAsFloat(const Value: Double);
begin
  FDataType := ftFloat;
  Self.Value := Value;
end;

procedure TParam.SetAsString(const Value: string);
begin
  if FDataType <> ftFixedChar then FDataType := ftString;
  Self.Value := Value;
end;

procedure TParam.SetAsVariant(const Value: Variant);
begin
  if ParamRef = Self then
  begin
    FBound := not VarIsClear(Value);
    FNull := VarIsClear(Value) or VarIsNull(Value);
    if FDataType = ftUnknown then
      case VarType(Value) of
        varSmallint, varShortInt, varByte: FDataType := ftSmallInt;
        varWord, varInteger: FDataType := ftInteger;
        varCurrency: FDataType := ftBCD;
        varLongWord, varSingle, varDouble: FDataType := ftFloat;
  ...
end;
...
(unidad DB.pas de Delphi 7)

Entonces eso explica, en parte, por qué la BDE / Paradox rechazaba aquella sentencia, en la que se intentaba asignar valor a un parámetro numérico con la propiedad AsString de ese TParam.

Nunca he tenido este problema con Firebird vía IBX o dbExpress (creo), así que ya había dado por hecho que estas propiedades AsXXX eran meros convertidores (como las de TField).

Pero con esto que sale a la luz, ¿deberíamos usarlas con precautoria atención ante la posibilidad de cambiar de motor? Incluso, según se ve, hasta la misma propiedad Value lo hace (SetAsVariant es su método de escritura).

¿Está mal que los métodos SetAsXXX de TParam modifiquen la propiedad DataType? Sin razonarlo mucho, pareciera que sí, pero alguna explicación deberá existir.

Por alguna razón, para la VCL los objetos TParam son de "menos valía" que los TField. De hecho hay un divertido y "criminal" mecanismo de pérdida de parámetros en la mayoría de las clases que implementan el método PSSetParams, cuando nos olvidamos de establecerlos correctamente en el lado cliente.

Creo que habría que investigar cómo trata cada tecnología (BDE, IBX, ADO, dbExpress) a los parámetros, para tener una idea clara de la seguridad que ofrecen las propiedades AsXXX y Value de TParam.

Un abrazo parametrizado.

Al González.

Última edición por Al González fecha: 17-02-2009 a las 05:01:53.
Responder Con Cita
  #5  
Antiguo 17-02-2009
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Hola,

Es cierto Al, el tratamiento a los campos es distinto que a los parámetros. Tal como yo lo decía es incorrecto, ya que, como bien notas, las propiedades AsXXX no hacen una conversión sino que simplemente cambian el tipo de datos (DataType).

Ahora, no me parece descabellado. Más bien habría que ver porqué TField no lo hace. Si yo escribo

Código Delphi [-]
Query.ParamByName(...).AsXYZ := valor;

explícitamente estoy diciendo que quiero tratar el parámetro como un tipo XYZ; ¿por qué, entonces no había de hacerse el cambio de DataType?

Pero no deja de ser raro que el BDE no acepte el paso de un parámetro float como AsString puesto que el motor en sí si acepta consultas como:

Código SQL [-]
update productos
set precio = "1123.58"
where ...

siendo precio un campo numérico.

Por otra parte, los métodos SetAsXYZ de TField en realidad sólo lanzan una excepción; es decir que están hechos para ser redefinidos. Entonces, cuando hacemos algo como

Código Delphi [-]
Table.FieldByName('precio').AsString := '1123.58';

en realidad estamos llamando al método SetAsString, no de TField, sino de TFloatField. Cuando abrimos la tabla, se crean los campos del tipo adecuado según especifique la tabla física, de manera que ya se sabe de antemano que el campo real es de tipo float, y por tanto, el valor que se dé, debe convertirse a ese tipo de datos antes de mandarlo a la base.

Pero en el caso de un Query, no se sabe de antemano a qué tipo de datos corresponde el parámetro en la base, así que tiene que confiar en lo que le decimos y cambiar el valor de DataType.

Bueno, desde luego estoy especulando, pero creo que por ahí va el porqué TParam ajusta DataType y TField (o sus descendientes) no.

// Saludos
Responder Con Cita
  #6  
Antiguo 17-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por roman Ver Mensaje
Pero en el caso de un Query, no se sabe de antemano a qué tipo de datos corresponde el parámetro en la base, así que tiene que confiar en lo que le decimos y cambiar el valor de DataType.

Bueno, desde luego estoy especulando, pero creo que por ahí va el porqué TParam ajusta DataType y TField (o sus descendientes) no.
Podría ser, pero cuando uno mismo ha definido los parámetros en tiempo de diseño, como que no esperas que al asignarles valor en tiempo de ejecución Delphi modifique alguna de esas definiciones. Es decir, habiendo establecido los parámetros como lo hacemos con los campos persistentes, bajo conocimiento del tipo específico que tienen.

No lo sé, es razonable y a la vez curioso. Pero ahora me percato que la propia ayuda de TParam lo advierte:
Cita:
Setting AsFloat sets the DataType property to ftFloat.
Que pases buena noche Román, yo todavía trabajaré un rato más. Con un ojo al gato y otro al garabato, como solía decirme mi madre cuando era yo un chaval.
Responder Con Cita
  #7  
Antiguo 17-02-2009
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Al González Ver Mensaje
Podría ser, pero cuando uno mismo ha definido los parámetros en tiempo de diseño, como que no esperas que al asignarles valor en tiempo de ejecución Delphi modifique alguna de esas definiciones.
¿Por qué no? Siempre puede uno cambiar de opinión ¿Para qué si no, están esos métodos SetAsXYZ? Ya sea en TParam o TField, se trata de que podamos, según convenga, asignar el valor de una u otra forma (aunque, como ya observaste, con el debido cuidado). Aún especificando el tipo de datos del parámetro en tiempo de diseño, se trata de una acción de confianza; la VCL confía en nosotros igual que el compilador confia cuando hacemos un moldeo de tipos.

// Saludos
Responder Con Cita
  #8  
Antiguo 17-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por roman Ver Mensaje
¿Para qué si no, están esos métodos SetAsXYZ? Ya sea en TParam o TField...
En TField están para asignar fácilmente un valor al campo, aunque dicho valor esté expresado bajo otro tipo de dato, realizando una conversión implícita del valor asignado. Mientras que en TParam tal conversión no es llevada a cabo. En este caso es el objeto TParam el que se "convierte", no el valor dado.

El extrañamiento viene de la sorpresa de esta "inesperada" diferencia de comportamiento en propiedades que, pareciera, "deberían" hacer lo mismo.

Quizá sólo es cosa de costumbre y el que se pierde la convicción de que habría un "StrToFloat" implícito al usar AsString con un parámetro definido como numérico flotante.

Pensando en voz alta, en TField la propiedad DataType está muy relacionada con la clase del objeto y la manera en que guarda el dato, como quien dice la clase es su determinante. En TParam el valor es un Variant (no hay clases específicas derivadas de TParam), y quizá esta es la piedra angular que explica la diferencia. Al guardar TParam el valor en un Variant resulta tentador (y esperable) que ese Variant pueda ser, tal cual, lo que le sea asignado, creándose entonces la obligación de ajustar DataType al tipo del variante interno y no al revés.

¡Pero no! Pasé por alto algo importante en el código que pegué antes. SetAsVariant no cambia DataType a menos que éste se encuentre indefinido (ftUnknown):
Código Delphi [-]
procedure TParam.SetAsVariant(const Value: Variant);
begin
  if ParamRef = Self then
  begin
    FBound := not VarIsClear(Value);
    FNull := VarIsClear(Value) or VarIsNull(Value);
    if FDataType = ftUnknown then
      case VarType(Value) of
        varSmallint, varShortInt, varByte: FDataType := ftSmallInt;
        varWord, varInteger: FDataType := ftInteger;
        varCurrency: FDataType := ftBCD;
        varLongWord, varSingle, varDouble: FDataType := ftFloat;
        varDate: FDataType := ftDateTime;
        varBoolean: FDataType := ftBoolean;
        varString, varOleStr: if FDataType <> ftFixedChar then FDataType := ftString;
        varInt64: FDataType := ftLargeInt;
      else
        if VarType(Value) = varSQLTimeStamp then
          FDataType := ftTimeStamp
        else if VarType(Value) = varFMTBcd then
          FDataType := ftFMTBcd
        else 
          FDataType := ftUnknown;
      end;
    FData := Value;
  end else
    ParamRef.SetAsVariant(Value);
end;

A ver. Entonces si asignamos con la propiedad Value, el DataType que hayamos definido en tiempo de diseño se mantiene, lo cual es frecuentemente deseable. Mientras que las propiedades AsXXX nos servirán para hacer asignación de valor y cambio de tipo con una sola instrucción.

Creo que ahora tiene más lógica. Cuando se quiera o se necesite conservar el tipo definido en tiempo de diseño debe usarse Value. Cuando se quiera o necesite ajustar el tipo (o no importe si éste cambia) puede usarse AsXXX.

Sólo tener en cuenta que en determinadas ocasiones, debido a lo anteriormente visto, podría ser obligado escribir algo como
Código Delphi [-]
Parametro.Value := StrToXXX (Edit1.Text);
en lugar de
Código Delphi [-]
Parametro.AsString := Edit1.Text;

EDITO:

No sé por qué me queda la sensación de que hay un cabo suelto en todo esto, quizá es el desconocimiento de cómo son transferidos los parámetros al servidor...

¡Es más! Creo que uno no debería usar las propiedades AsXXX de TParam con el mero propósito de "facilitar cualquier asignación". Más bien con el bien intencionado propósito de asignar un valor y buscar que el DataType cambie a / se mantenga en el tipo específico de dicho valor, porque, para el contexto de la consulta SQL, ese tipo específico es el que se necesita.

Tomando texto de la ayuda e interpretándolo:

Cita:
Set AsFloat to assign the value for a float field to the parameter. Setting AsFloat sets the DataType property to ftFloat.
Establezca AsFloat para asignar el valor al parámetro para corresponder a un campo flotante...

Cita:
Use Value in generic code that manipulates the values of parameters without needing to know the field type the parameters represent.
Utilice Value en código genérico ["en general"] que manipule el valor de los parámetros sin necesidad de conocer el tipo de campo que éstos representan.

El "cabo suelto" era por esta sensación de que podría usarse AsXXX indiscriminadamente, para "facilitar cualquier asignación". Está bien que se usen esas propiedades para facilitar asignaciones, pero no cuando eso cause que el tipo del parámetro cambie a uno que no corresponda al contexto de la sentencia SQL, AUN cuando la sentencia funcione con la versión del motor de base de datos en turno. No sería del todo confiable, pues se supone que el DataType y el valor en sí del parámetro son los que determinan el valor que es enviado al servidor. No es lo mismo que le llegue un 5 que un '5', cualquiera que sea el formato interno del envío.

Creo que convendría investigar la forma en que el DataType influye en lo que es enviado al servidor y por qué en algunos casos, como el expuesto por Carlos, no hay falla.

Última edición por Al González fecha: 17-02-2009 a las 09:17:49.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
string a integer? acertij022 Varios 4 26-02-2008 23:24:30
String a Integer tuflotas Varios 9 22-01-2008 21:09:34
Integer a String en PHP noshy PHP 13 06-08-2007 19:26:36
de String a Integer!! kye_z Varios 2 20-11-2004 20:04:36
Convertir campo tipo number de oracle a integer o string Sóstrato OOP 1 13-06-2003 09:18:55


La franja horaria es GMT +2. Ahora son las 21:24:37.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi