Curso de C++ Builder


Acceso a bases de datos

TQuery



El componente TQuery permite realizar consultas en SQL. En los siguientes apartados se describen sus propiedades y métodos básicos:

La consulta SQL

La propiedad SQL es de tipo TStringList (un lista de cadenas de caracteres) y contiene la sentencia SQL que ha de ejecutarse sobre la base de datos indicada mediante la propiedad DatabaseName.

Ejemplo:

Otra propiedad bastante interesante del componente TQuery es LiveRequest, que permite que una consulta sea actualizable (es decir, que podamos editar su conjunto de datos sin tener que preocuparnos de cómo almacenar los cambios en la base de datos). Por desgracia, no todas las consultas son actualizables.

Ejecución de sentencias SQL

Para ejecutar en tiempo de diseño la sentencia SQL correspondiente a una consulta (un SELECT) basta con poner su propiedad Active a true (lo que equivale a invocar al método Open()).

En tiempo de ejecución, se puede usar Open() para ejecutar una consulta (SELECT), o ExecSQL() para ejecutar una sentencia SQL de tipo INSERT, UPDATE o DELETE.

Sentencias SQL con parámetros

En las sentencias SQL se pueden utilizar parámetros. Los parámetros son variables que se escriben en la sentencia SQL precedidos de : (dos puntos). El valor de tales parámetros se puede establecer accediente a la propiedad Params del componente TQuery o mediante el método ParamByName.

En tiempo de diseño:

Preparar una consulta SQL con:

  select * from customer
  where CustNo > :ValorMinimo

Editar la propiedad Params estableciendo el parámetro ValorMinimo como un integer con valor 1300.

 
En tiempo de ejecución:
{
  query->SQL->Clear();
  query->SQL->Add(
    "select * from customer where CustNo > :ValorMinimo");
  query->ParamByName("ValorMinimo")->AsInteger = 1300;
  query->Open();
}

En los parámetros también se pueden utilizar comodines:

Query->ParamByName("id")->AsString = Edit->Text + "%";

Los métodos Prepare() y UnPrepare() sirven para ejecutar consultas preparadas, que serán más eficientes si se ejecutan múltiples veces siempre que nuestra base de datos permita este tipo de consultas optimizadas. La propiedad Prepared nos indica si una consulta ha sido preparada o no.

Preparación inicial de una consulta
if (! Query->Prepared)
   Query->Prepare();

Query->Open();
Liberación de recursos
Query->Close();

if (Query->Prepared)
   Query->UnPrepare();

Consultas dependientes [linked queries]

Mediante consultas también se pueden establecer relaciones maestro/detalle. Para ello hemos de dejar un parámetro de la consulta detalle asociado a una columna del conjunto de datos que hace de maestro, SIN especificar su tipo. Para enlazar la consulta basta entonces establecer su propiedad DataSource para que apunte a la tabla maestra. Este tipo de consultas NO son actualizables, por lo que usualmente preferiremos utilizar tablas (TTables).

Consultas heterogéneas

El motor de bases de datos de Borland (BDE) permite incluso realizar consultas que involucren tablas almacenadas en distintas bases de datos. Para ello, en la consulta SQL hay que indicar las tablas utilizando la notación :ALIAS:tabla, donde ALIAS es el alias BDE de la base de datos donde se encuentra la tabla tabla.

Actualizaciones (insert, update & delete)

int __fastcall ejecutarSQL(const AnsiString ADatabase, const AnsiString Instruccion)
{
  std::auto_ptr query(new TQuery(NULL));
  query->DatabaseName = ADatabase;
  query->SQL->Text = Instruccion;
  query->ExecSQL();
  return query->RowsAffected;
}

Datos sintéticos

insert into TablaAleatoria(Entero, Cadena)
values (:Ent, :Cad)

void RellenarTabla(TQuery *Query, int CantRegistros)
{
  randomize();
  Query->Prepare();

  try {
      int Intentos = 3;
      
      while (CantRegistros > 0)
            try {
                Query->ParamByName("ENT")->AsInteger = random(MAXINT);
                Query->ParamByName("CAD")->AsString = RandomString(35);
                Query->ExecSQL();
                Intentos = 3;
                CantRegistros--;
            } catch(Exception&) {
                 if (--Intentos == 0) 
		 throw;
            }
  } __finally {
    Query->UnPrepare();
  }
}


Índice de la sección