Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 17-11-2008
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
Question Parámetro VarChar de búsqueda, ¿es válido aumentar su tamaño para evitar error?

¡Hola!

Supongamos que tengo un SP (procedimiento almacenado) donde uno de sus parámetros es usado como valor a buscar dentro de una tabla. El parámetro, llamado P, está definido como VarChar (10), ya que el campo sobre el que busca el valor tiene la misma definición.

Dentro del SP, la cláusula Where de la sentencia SQL es:
Código SQL [-]
Where Campo Containing :P
(el operador usado también podría ser "=" u otros, en lugar de Containing)

Si ejecuto el procedimiento, dándole un valor de '1234567890A' para ese parámetro, el servidor, me arrojará el típico error "arithmetic exception, numeric overflow, or string truncation". Ya que el valor dado tiene once caracteres cuando el parámetro está definido con un tamaño de 10. Esto ocurre en Firebird, pero publico mi pregunta en esta sección por aplicarse, seguramente, a otras bases de datos también.

Entiendo que en estos casos se aconseja revisar previamente el valor dado para no sobrepasar la longitud máxima definida por el parámetro. Pero, a manera de prueba, hice otra cosa: aumenté el tamaño definido del parámetro a 11.

Resultado: el servidor ya no arroja ningún error, y el SP trabaja como se espera (por supuesto, no encuentra valores de once o más caracteres en un campo VarChar (10)). Probado en IB Expert con Firebird 1.5.

No estoy intentando asignar el valor dado a ningún campo, solamente lo uso para comparar, por lo que esta prueba que hice podría ser una solución alternativa en casos similares al mío. Resulta que el famoso valor dado es una cadena de caracteres que el usuario puede teclear dentro de un cuadro de texto para buscar dicho valor sobre diferentes campos. Y la aplicación por sí misma no conoce con precisión con qué parámetro(s) se va a buscar (aunque puede intervenir en ello, agregando algo de programación) ya que eso es determinado por otra capa del framework que utilizo.

Con esto he descubierto que si aumento, digamos, a 50, el tamaño de estos parámetros en todos los SPs de búsqueda. Ya sólo tendría que limitar la entrada en pantalla a un máximo de 50 caracteres para todos esos cuadros de texto, sin preocuparme más de cuál es el tamaño específico de cada campo donde se busca.

Mi pregunta es si, al hacer esto, ¿no estaría menguando significativamente el rendimiento del servidor a la hora de ejecutar esos SPs de búsqueda?

Quiero pensar que cuando Firebird encuentra una condición como
Código SQL [-]
Where Campo Containing :P
, y el valor de ese parámetro tiene una longitud mayor a la del campo, automáticamente descarta la fila que está comparando.

Comprendo que podría ser preferible revisar la longitud del valor antes de ejecutar el SP, para evitar que el servidor ejecute código inútil. Y quizá con esto esté ya contestándome respecto a lo que debo hacer. Pero viéndolo desde otro punto de vista, el procesamiento inútil del servidor podría ser prácticamente el mismo si buscamos un valor de longitud correcta pero que no existe en la tabla.

Quizá el argumento que termina de convencerme es: si el programa puede evitarle trabajo innecesario al servidor (sin causarle más trabajo), que lo evite. Creo que esta es una de esas cosas que debe hacer la "capa intermedia". La interfaz de usuario no tiene por qué validarlo puesto que carece de gran detalle de conocimiento respecto a los metadatos, y el servidor no debería hacer un procesamiento inútil que puede ser "autorizado" antes por alguien que conozca un poco más esos metadatos: la capa intermedia.

Entonces en la capa intermedia, en la parte del framework de clases donde concentro validaciones similares, agregaré una más para impedir la consulta al servidor cuando el valor String dado sobrepase el tamaño del parámetro VarChar en turno.

Este mensaje ha sido más que nada un pensamiento en voz alta, al más puro estilo Delphius (un abrazo, amigo ). Pero me gustaría conocer sus opiniones respecto a este tipo de problemas.

Saludos.

Al González.

Última edición por Al González fecha: 17-11-2008 a las 22:54:21.
Responder Con Cita
  #2  
Antiguo 17-11-2008
Avatar de sitrico
[sitrico] sitrico is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Caracas, Venezuela
Posts: 295
Poder: 21
sitrico Va por buen camino
Viendo el tema y reflexionando un poco creo que ni tienes razón ni estas equivocado sino todo lo contrario.

Bueno a lo que importa. Yo siempre limito los Tedit para char y varchar a la longitud máxima del campo en la BDD.

Código Delphi [-]
edit.MaxLength := FieldByname('Campo').Size;

Pero si tu consulta busca en varios campos:

Código SQL [-]
Where Campo1 Containing :P or Campo2 Containing :P

es OBLIGATORIO definir la longitud del campo más grande.

En lo personal pienso que no hay problema de definir un largo mayor, puede ser conveniente si piensas que el campo puede "crecer" más adelante. Pero no te recomendaría hacerlo como norma.

Saludos.
__________________
Sitrico
Responder Con Cita
  #3  
Antiguo 18-11-2008
Avatar de Luis M.
[Luis M.] Luis M. is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Ripollet - Barcelona
Posts: 212
Poder: 20
Luis M. Va por buen camino
Saludos.
Siempre es mejor utilizar la entrada de parámetros un poquito más grande
que la longitud del campo.

Si el campo es VarChar(10), el parámetro de entrada VarChar(10), cuando
le pases un valor con 10 dígitos, a este tienes que sumarle dos más por las
comillas.

Parámetro entrada: '1234567890' -> longitud 12, no 10.
Espero se me entienda.

Un saludo.
Responder Con Cita
  #4  
Antiguo 18-11-2008
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 Luis M. Ver Mensaje
....Si el campo es VarChar(10), el parámetro de entrada VarChar(10), cuando
le pases un valor con 10 dígitos, a este tienes que sumarle dos más por las
comillas.

Parámetro entrada: '1234567890' -> longitud 12, no 10....
Disculpa Luis, pero no creo que haya que reservar en un parámetro espacios para las comillas, puesto que el parámetro es declarado como cualquier variable y las comillas delimitadoras nunca son parte del valor de una cadena de caracteres. Las comillas se utilizan para que los compiladores o mecanismos de análisis sintáctico ("parsers") comprendan el dato proporcionado cuando se escribe de forma literal, pero no constituyen parte integral de la cadena de caracteres.

Creí oportuno precisar eso.

De todas formas, gracias por el comentario.

Al.
Responder Con Cita
  #5  
Antiguo 18-11-2008
Avatar de Luis M.
[Luis M.] Luis M. is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Ripollet - Barcelona
Posts: 212
Poder: 20
Luis M. Va por buen camino
Hola Al.
Tienes razón en lo que comentas.
Pero curiosamente a mi me pasaba lo siguiente:
Declaro este SP:
Código Delphi [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE ULTIMO_RECIBO (
    anyo varchar(2))
returns (
    ultimo varchar(10))
as
begin
  /* Procedure Text */
  EXECUTE STATEMENT 'SELECT max(NUMERO) FROM RECIBOS where ANYO = '||:anyo
  INTO :ultimo;
  suspend;
end^

SET TERM ; ^

GRANT EXECUTE ON PROCEDURE ULTIMO_RECIBO TO SYSDBA;

Desde Delphi lo llamo así:
Código Delphi [-]
//--- Introduce último recibo ---
  SP.StoredProcName := 'ULTIMO_RECIBO';
  SP.Prepare;
  try
    SP.Params.ParamValues['ANYO'] := QuotedStr(RecibosANYO.AsString);
    SP.ExecProc;
    cText := IntToStr(SP.ParamByName('ULTIMO').AsInteger + 1);
    RecibosNUMERO.AsString := Copy('00000', 1, 5 - Length(cText)) + cText;
  finally
    SP.UnPrepare;
  end;
RecibosANYO es VarChar(2).
Al ejecutarlo me da el error que describes.
Si cambio en el SP
Código Delphi [-]
CREATE OR ALTER PROCEDURE ULTIMO_RECIBO (
    anyo varchar(2))
por:
Código Delphi [-]
CREATE OR ALTER PROCEDURE ULTIMO_RECIBO (
    anyo varchar(10))
Funciona bien.
A eso me refería.
Un saludo y encantado de leerte.
Responder Con Cita
  #6  
Antiguo 18-11-2008
[maeyanes] maeyanes is offline
Capo de los Capos
 
Registrado: may 2003
Ubicación: Campeche, México
Posts: 2.732
Poder: 24
maeyanes Va por buen camino
Hola...

Luis M., ¿por qué haces tu procedimiento de esa forma?

Eso que tu haces lo puedes lograr así:

Código SQL [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE ULTIMO_RECIBO (
    anyo varchar(2))
returns (
    ultimo integer)
as
begin
  /* Procedure Text */
  SELECT max(NUMERO) FROM RECIBOS where ANYO = :anyo
  INTO :ultimo;
  suspend;
end^

SET TERM ; ^

GRANT EXECUTE ON PROCEDURE ULTIMO_RECIBO TO SYSDBA;

Y no vas a recibir el error que mencionas...


Saludos...
Responder Con Cita
  #7  
Antiguo 18-11-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
No quería entrometerme en el hilo, pero ¡¡ ya estoy !!

Intuyo que el error viene porque el año son 4 dígitos. Tú quizás le pasas 2 dígitos al procedimiento almacenado, pero él quizás devuelva 4 letras y el procedimiento de salida sólo tenía 2 espacios.

Quizás estoy suponiendo mucho... no lo sé, entran en juego muchas variables y no está todo dicho:
- declaración de campos
- valores que tiene en la BBDD
- lo que se le pasa desde delphi
- lo que interpreta el SP (puede ser aquí la traducción de 2 dígitos a 4 para el campo numero)
- lo que devuelve
- etc.

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #8  
Antiguo 18-11-2008
Avatar de Luis M.
[Luis M.] Luis M. is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Ripollet - Barcelona
Posts: 212
Poder: 20
Luis M. Va por buen camino
Hola.
Cita:
Empezado por Lepe Ver Mensaje
No quería entrometerme en el hilo, pero ¡¡ ya estoy !!
Ni mucho menos Lepe, todo lo contrario, es un honor.
Te comento, el año son 2 dígitos, capturo solo los dos últimos.
Tengo algunos SP hechos como lo comentas en tú post y funcionan bien siempre y cuando no les pase parámetros; En el momento que le paso algún parámetro, tengo que implementarlo con EXECUTE STATEMENT, si no, no funcionan.
También comento que solo funciona con EXECUTE STATEMENT cuando hay
comandos como SUM,MAX, etc.
Este funciona perfectamente sín parámetros:
Código Delphi [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE ULTIMO_CARNET 
returns (
    ultimo varchar(10))
as
begin
  /* Procedure Text */
  select max(CODIGO) FROM CARNETS INTO :ultimo;
  suspend;
end^

SET TERM ; ^

GRANT SELECT ON CARNETS TO PROCEDURE ULTIMO_CARNET;

GRANT EXECUTE ON PROCEDURE ULTIMO_CARNET TO SYSDBA;

Espero haberme explicado bien

Un saludo.
Responder Con Cita
  #9  
Antiguo 18-11-2008
[maeyanes] maeyanes is offline
Capo de los Capos
 
Registrado: may 2003
Ubicación: Campeche, México
Posts: 2.732
Poder: 24
maeyanes Va por buen camino
Hola...

Vaya, eso si es muy raro. ¿Será que haces algo mal?

Yo hasta ahora no he tenido ningún tipo de problema haciendo procedimientos almacenados recibiendo y devolviendo parámetros.

De la forma en que te lo puse te debería funcionar sin problemas...


Saludos...
Responder Con Cita
  #10  
Antiguo 18-11-2008
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
Intuyo que Luis se ve obligado a usar Execute Statement porque el parámetro Anyo llega con un par de comillas laterales como parte del valor en sí. Lo cual significaría que desde Delphi lo forma él de esa extraña manera.
Responder Con Cita
  #11  
Antiguo 18-11-2008
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 Luis M. Ver Mensaje
...Desde Delphi lo llamo así:
Código Delphi [-]
//--- Introduce último recibo ---
  SP.StoredProcName := 'ULTIMO_RECIBO';
  SP.Prepare;
  try
    SP.Params.ParamValues['ANYO'] := QuotedStr(RecibosANYO.AsString);
    SP.ExecProc;
    cText := IntToStr(SP.ParamByName('ULTIMO').AsInteger + 1);
    RecibosNUMERO.AsString := Copy('00000', 1, 5 - Length(cText)) + cText;
  finally
    SP.UnPrepare;
  end;
...
¡Ah, pues sí! De hecho ahí se las está metiendo.
Responder Con Cita
  #12  
Antiguo 18-11-2008
Avatar de Luis M.
[Luis M.] Luis M. is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Ripollet - Barcelona
Posts: 212
Poder: 20
Luis M. Va por buen camino
Si le paso el parámetro sin el QuotedStr, no funciona, no me devuelve el valor requerido.
Cosa rara.

Responder Con Cita
  #13  
Antiguo 18-11-2008
[maeyanes] maeyanes is offline
Capo de los Capos
 
Registrado: may 2003
Ubicación: Campeche, México
Posts: 2.732
Poder: 24
maeyanes Va por buen camino
Hola...

Por que así como lo estás haciendo estás concatenando cadenas para poder hacer el Execute Statement; si lo haces de la forma en que te puse, no deberías tener problemas...



Saludos...
Responder Con Cita
  #14  
Antiguo 18-11-2008
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 Luis M. Ver Mensaje
Si le paso el parámetro sin el QuotedStr, no funciona, no me devuelve el valor requerido.
Cosa rara.

Eso es porque usas Execute Statement. Prueba como te dice maeyanes y sin emplear QuotedStr. Verás que te funciona como esperas.
Responder Con Cita
  #15  
Antiguo 18-11-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
Pues ese tipo de fallo me parece los típicos que cometemos a altas horas de la noche o cuando estás muy agobiado. Modificas una cosa, no sale, ahora modificas otra.... hasta que todo "cuadra", eso sí, terminas sin saber cómo lo hiciste .

Saludos y me alegro que se aclarase el tema.
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #16  
Antiguo 18-11-2008
Avatar de Luis M.
[Luis M.] Luis M. is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Ripollet - Barcelona
Posts: 212
Poder: 20
Luis M. Va por buen camino
Cita:
Empezado por Lepe Ver Mensaje
Pues ese tipo de fallo me parece los típicos que cometemos a altas horas de la noche o cuando estás muy agobiado. Modificas una cosa, no sale, ahora modificas otra.... hasta que todo "cuadra", eso sí, terminas sin saber cómo lo hiciste .

Saludos y me alegro que se aclarase el tema.
Me parece que tienes toda la razón
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
Aumentar espacio entre lineas de un memo sin aumentar tamaño de letra gulder Varios 1 28-10-2008 19:33:51
DBGrid, ¿aumentar tamaño de los campos? rev PHP 2 13-03-2008 09:34:09
Cómo cambiar el tamaño de un campo tipo varchar subzero Firebird e Interbase 3 12-10-2007 14:57:27
Como Aumentar el Tamaño de letra en el ZReport???? AGAG4 Impresión 3 07-03-2007 20:02:42
Remedio para aumentar el pecho !!!! tcp_ip_es Humor 1 21-10-2004 23:41:39


La franja horaria es GMT +2. Ahora son las 00:26:39.


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