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 31-01-2016
Kenobi Kenobi is offline
Miembro
 
Registrado: mar 2007
Posts: 191
Poder: 18
Kenobi Va por buen camino
paso de parametros a tdataset

Hola, frecuentemente utilizo una rutina como esta para "enlazar" un dataset con otro
Código Delphi [-]
if not consulta.prepared then consulta.prepare;
consulta.close;
consulta.parambyname('parametro').asLoqueSea := valor
consulta.open;

pues bien, estoy intentando crear un procedure generico que reciba 2 parametros uno el dataset y el otro el campo:

Código Delphi [-]
procedure generico(data:tdataset;campo:String)
begin
data.paramByName(campo).asvariant := campo;

el problema es que el dta set no me acepta el paramByName e intentado con :

Código Delphi [-]
tquery(data).parambyname(campo).asVAriant := campo

pero no resulta...

espero que se entienda la idea
Gracias
Responder Con Cita
  #2  
Antiguo 31-01-2016
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.040
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
No puedes pasar el nombre de un campo como parámetro.

Además, creo recordar que está mal el planteamiento que haces aquí:
Código Delphi [-]
if not consulta.prepared then 
begin
  consulta.prepare;
  consulta.close;
  consulta.parambyname('parametro').asLoqueSea := valor;
  consulta.open;
end;
Creo recordar que, en todo caso, aunque no es necesario el prepare, debes hacer así:
Código Delphi [-]
consulta.close;
consulta.parambyname('parametro').asLoqueSea := valor;
consulta.prepare;
consulta.open;
Responder Con Cita
  #3  
Antiguo 31-01-2016
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 28
Lepe Va por buen camino
La idea del "prepare", es que se cree el SQL con parámetros (como ya lo haces), y se compila una sola vez la instrucción (prepare), se da valor a los parámetros y se ejecuta/abre.

Tiene sentido cuando un mismo SQL se va a ejecutar varias veces en la misma tabla con los mismos campos, por ejemplo inserciones masivas, actualizaciones, selecciones, etc...

Código SQL [-]
select * from tabla where fecha between :fecha_inicial and :fecha_final

Muy típico en listados por fechas, creas la ventana de listados donde asignas el SQL, lo preparas y cuando el usuario cambia las fechas en la interfaz, solo asignas el valor de los parámetros.

En teoría es lo más eficiente, ya que evitas:
- averiguar los campos que se seleccionan (solo se hace una vez en la vida del Form, donde se crean los campos del TQuery, rellenando el FieldsDef, etc).
- compilar el SQL para obtener el plan de ejecución (qué índices se usarán según los join que hagas, los campos del order by, etc)

Es cierto que no es necesario llamar a "prepare" porque lo hace internamente, pero es buena práctica; solo con ver un "if not query.prepared", sabes que el SQL no se modifica. Obviamente no tiene sentido hacerlo en un FormCreate, porque si se acaba de crear el Form y el TQuery, aún no está preparado.

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #4  
Antiguo 31-01-2016
Kenobi Kenobi is offline
Miembro
 
Registrado: mar 2007
Posts: 191
Poder: 18
Kenobi Va por buen camino
Cita:
Empezado por Casimiro Notevi Ver Mensaje
No puedes pasar el nombre de un campo como parámetro.
Hola, creo que si se puede de hecho lo estoy haciendo en este momento, claro con algo mas en el código:

tengo 2 tquery

personas:
Código SQL [-]
SELECT * from personas WHERE campo=:dNI

autos:
Código SQL [-]
SELECT * from autos WHERE campo=:matricula


Código Delphi [-]
procedure cargar_query(nombreParametro,valorParametro:String;
begin
  query.close;
  query.paramByName(nombreParametro).asVariant := valorParametro;
  query.open;
end;

y luego para llamar al procedure pues :
Código Delphi [-]
cargar_query('DNI','007');  // ....aca me carga al agente ....
cargar_query('matricula','bmw-007'); // ....  y su auto ....

a lo que me refiero es que le puedo pasar el nombre y el valor de un parametro al paramByName ya que lo que espera es un String ....

claro que es lo que falta pues como decir con un parametro cual es la query en cuestion, lo intente con

Código Delphi [-]
procedure cargar_query(query:TdataSet;nombreParametro,valorParametro:String);
begin
  query.close;
  query.paramByName(nombreParametro).asVariant := valorParametro;  // un tdataset no acepta el metodo paramByname ....
  query.open;
end;

mi idea es hacer algo asi

Código Delphi [-]
 tquery(query).paramByName(nombreParametro).asVariant:=valorParametro;

, pero no funciona

y alli esta el detalle ....lo que quiero es hacer ese casting y eliminar muchas declaraciones de este procedure para cada query en particular y asi reduciria mucho el codigo ...

Saludos ...
Responder Con Cita
  #5  
Antiguo 31-01-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Muy complicado de hacer; las diferentes implementaciones estan en distintos arboles de herencia.

Por ejemplo en DB.pas se define el tipo TParam para operar con los parametros de los TQuery

Pero en ADODB.pas se define otro tipo TParameter que no tiene nada que ver con TParam

Tampco hay un ancestro comun para los TQuery. ADOQuery hereda de TCustomAdoDataSet quien hereda de TDataSet; y es en TCustomAdoDataSet donde se agrega la funcionalidad para los TParameter


Lo mas cercano que podes hacer es declarar una interface y luego crear clases wrapper, asi:

Código Delphi [-]
unit Unit3;

interface

type
  IQuery = interface
    ['{055FBC2E-FB1C-41DC-9696-B3071C8D04C4}']
    procedure SetParamValue(const AName: string; AValue: Variant);
    function GetParamValue(const AName: string): Variant;
    procedure Close;
    procedure Open;
  end;

procedure cargar_query(const AQuery: IQuery; const Parametro, Valor: string);

implementation

procedure cargar_query(const AQuery: IQuery; const Parametro, Valor: string);
begin
  AQuery.Close;
  AQuery.SetParamValue(Parametro, Valor);
  AQuery.Open;
end;

end.

Wrapper ADO:

Código Delphi [-]
type
  TAdoQueryWrapper = class(TADOQuery, IQuery)
  public
    procedure SetParamValue(const AName: string; AValue: Variant);
    function GetParamValue(const AName: string): Variant;
  end;

{ TAdoQueryWrapper }

function TAdoQueryWrapper.GetParamValue(const AName: string): Variant;
begin
  Result := Parameters.ParamByName(AName).Value;
end;

procedure TAdoQueryWrapper.SetParamValue(const AName: string; AValue: Variant);
begin
  Parameters.ParamByName(AName).Value := AValue;
end;

Ejemplo de uso:

Código Delphi [-]
procedure TForm2.Button1Click(Sender: TObject);
var
  AQuery: TAdoQueryWrapper;
begin
  AQuery := TAdoQueryWrapper.Create(NIL);
  AQuery.Connection := ADOConnection1;
  DataSource1.DataSet := AQuery;
  AQuery.SQL.Text := ' SELECT * FROM Clientes WHERE Id > :Id ';
  cargar_query(AQuery, 'Id', '5');
end;
Responder Con Cita
  #6  
Antiguo 01-02-2016
Avatar de fjcg02
[fjcg02] fjcg02 is offline
Miembro Premium
 
Registrado: dic 2003
Ubicación: Zamudio
Posts: 1.410
Poder: 22
fjcg02 Va camino a la fama
Es cierto lo que comentan, dependiendo del dataset, hay diferentes formas de definir los parámetros de un dataset.

Dataset.ParamByName() ..

ó

DataSet.Parameters.ParamByName()...

Tendrás que hacer unas pruebas, y ver si utilizas una forma u otra teniendo en cuenta qué objetos utilizas. Si utilizas diferentes objetos, tendrás que hacer un cast.

Código SQL [-]
if dataset.Class = TQUery then
  Dataset.ParamByName( ....

if dataset.Class = TADOQuery then
  Dataset.Parameters.ParamByName(....

Dataset.Open;
Espero haberte dado alguna idea.

Un saludo
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino -
Responder Con Cita
  #7  
Antiguo 01-02-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
No es buena idea, ya que si cambias la clase del dataset, te tenes que acordar de agregar el cast a esa clase; es agregar un if

Ademas, si se manda por parametro un TDataSet, eso quiere decir que puedo mandar sin problemas un TTable, un TClientDataSet; y evidentemente eso no es lo que espera el procedimiento

Tambien implica agregar en la clausula uses las distintas bibliotecas: ADODB para TADOxx, DB para TDataSet, DBClient para TClientDataSet; esto es malo porque es acoplamiento (se depende de otra unidad para poder compilar la nuestra). El codigo acoplado es mas dificil de mantener, mas dificil de testear, mas dificil de aislar. Yo siempre estoy luchando con sacar todo lo que sobra en los uses, y si puedo poner todo en la seccion de implementation, mejor aun

Delphi por suerte soporta OOP e interfaces, no volvamos a la programacion estructurada

Lo mas sano es declarar una interface y enviarla como parametro; si mas adelante cambio de TADOQuery a TQuery, al enviarlo por parametro el compilador me va a recordar amablemente que la clase TQuery no implementa dicha interface

Hay que aprender a escribir codigo que arroje los errores en tiempo de compilacion, no en ejecucion

Última edición por AgustinOrtu fecha: 01-02-2016 a las 14:30:10.
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
Copiar informacion de un Tdataset a otro Tdataset joelphi Varios 10 19-02-2009 22:27:44
Paso de parámetros a TDataset arturom Firebird e Interbase 9 04-04-2008 18:04:03
Paso de parametros senpiterno Varios 1 11-04-2004 03:44:17
paso de parametros gustavo2 SQL 7 16-01-2004 15:46:23
Paso de parametros __cadetill PHP 2 12-08-2003 10:15:09


La franja horaria es GMT +2. Ahora son las 07:11:16.


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