Sign in Join
Wiki copytemporary

SqlDBHowto/es: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introducción
22
33   Este texto se configura como un "cómo-hacer". Pretende responder a una serie de preguntas una por una, explicando cómo se pueden utilizar las distintas clases. Todas estas cuestiones puestas una detrás de otra forman una especie de tutoría.
44
55   Voy a tratar de esccribir de tal manera que el texto pueda ser utilizado para Lazarus, así como FreePascal. Sin embargo, los ejemplos son para FreePascal (es decir, son aplicaciones de consola)
66
77## ¿Cómo conectarse a un servidor de base de datos?
88
99   SQLdb no se conecta a un servidor de base de datos directamente sino que utiliza el cliente correspondiente al servidor de base de datos utilizado. SQLdb envía los comandos a la librería de cliente, la cual se conecta a la base de datos y le pasa los comandos. Esto significa que una librería de cliente debe ser instalada en el equipo para establecer una conexión con una base de datos. En Windows un cliente suele ser una .dll, bajo Linux un .so y bajo OS/X una .dylib.
1010
1111   Cuando la librería de cliente se ha instalado correctamente puede conectarse a un servidor de base de datos utilizando un componente TSQLConnection. Hay disponibles componentes TSQLConnection para diferentes servidores de base de datos ( [[SQLdb Package/es|ver paquete SQLdb]]) - siendo el listado de las disponibles el siguiente:
1212
1313- Firebird/Interbase: TIBConnection ([[Firebird|ver enlace]])
1414- MS-SQL: TMSSQLConnection (disponible desde la versión 2.6.1 de FPC,[[Lazarus Database Overview|ver enlace]])se puede crear una conexión con el método *open*. Si
1515- MySQL v4.0: TMySQL40Connection ([[mysql|ver enlace]])
1616- MySQL v4.1: TMySQL41Connection ([[mysql|ver enlace]])
1717- MySQL v5.0: TMySQL50Connection ([[mysql|ver enlace]])
1818- MySQL v5.1: TMySQL51Connection (disponible desde la versión 2.5.1 de FPC,[[mysql|ver enlace]])
1919- MySQL v5.5: TMySQL55Connection (disponible desde la versión 2.?.? [[mysql|ver enlace]])
2020- ODBC: TODBCConnection ([[ODBCConn|ver enlace]])
2121- Oracle: TOracleConnection (Oracle)
2222- PostgreSQL: TPQConnection ([[postgresql|ver enlace]])
2323- Sqlite3: TSQLite3Connection (disponible desde la versión 2.2.2 de FPC, [[SQLite|ver enlace]])
2424- Sybase ASE: TSybaseConnection (disponible desde la versión 2.6.1 de FPC, [[Lazarus Database Overview|ver enlace]])
2525
26-<figure>
27-<img src="Conectores_BBDD.png" title="Conectores_BBDD.png" />
28-<figcaption>Conectores_BBDD.png</figcaption>
29-</figure>
26+![](/wiki-images/8/8f/Conectores_BBDD.png)
3027
3128   Las diferencias entre las versiones de cliente MySQL son grandes, en la medida que los clientes y las conexiones no se pueden intercambiar. Con un cliente MySQL versión 4.1 instalado, tienes que utilizar un TMySQL41Connection. *Si se utiliza la misma versión de librería que de cliente* probablemente con la 4.1 se podría conectar a *un servidor* MySQL 5.0, pero el requerimiento de correspondencia librería-conector a la misma versión es necesario.
3229
3330   Aunque los detalles difieren entre las distintas base de datos, por lo general hay que establecer cuatro propiedades para conectarse a un servidor de base de datos:
3431
3532- El nombre del servidor o su dirección IP.
3633- El nombre de la base de datos.
3734- El usuario.
3835- La contraseña.
3936
4037   Cuando estas propiedades se establecen, se puede crear una conexión con el método, *open*. Si falla la conexión se lanza una excepción *EDatabaseError*. Utiliza la propiedad *connected* para comprobar si la conexión se ha establecido con el servidor de base de datos. Utiliza el método *close* para finalizar la conexión con el servidor.
4138
4239``` pascal
4340Program ConectaDB
4441
4542 var UnaConexion : TSQLConnection;
4643
4744 Procedure CrearConexion;
4845 begin
4946 UnaConexion := TIBConnection.Create(nil);
5047 UnaConexion.Hostname := 'localhost';
5148 UnaConexion.DatabaseName := '/opt/firebird/examples/employee.fdb';
5249 UnaConexion.UserName := 'sysdba';
5350 UnaConexion.Password := 'contraseñamaestra';
5451 end;
5552
5653 begin
5754 CrearConexion;
5855 UnaConexion.Open;
5956 if UnaConexion.Connected then
6057 writeln('¡Conexión realizada!')
6158 else
6259 writeln('¡Imposible!, porque si la conexión falla, '+
6360 'una excepción debe ser lanzada, por lo que este código no '+
6461 'será Ejecutado');
6562 UnaConexion.Close;
6663 UnaConexion.Free;
6764 end.
6865```
6966
7067   Si se produce una excepción, lea atentamente el mensaje de error. Tal vez el servidor de base de datos no está funcionando, el nombre de usuario o la contraseña son incorrectos o el nombre o la dirección IP de base de datos estan escritos de forma incorrecta. Si el mensaje de error indica que la librería cliente no puede ser encontrada, comprueba si el cliente está instalado correctamente. A menudo, el mensaje de error muestra literalmente el nombre del archivo buscado. También es buena idea verificar en la documentación si alguna de estas propiedades está o no soportada para un conector concreto puesto que es posible que en algún caso deban dejarse sin rellenar (no me refiero a la documentación de la BBDD sino de la unidad que conecta).
7168
7269## ¿Cómo ejecutar consultas directas o crear una tabla?
7370
7471   SQLdb -el nombre lo dice todo- sólo funciona con servidores de base de datos que hacen uso de SQL. SQL significa *Structured Query Language* (Lenguaje estructurado de consulta). SQL es un lenguaje desarrollado para permitir trabajar con bases de datos relacionales. Prácticamente todos los sistemas de base de datos tiene su propio dialecto, pero un gran número de sentencias SQL son iguales en todos los sistemas de base de datos. Podemos hacer una diferencia entre las sentencias SQL que devuelven la información y sentencias que no devuelven información. Si desea utilizar la información que devuelve la sentencias SQL, tienes que utilizar el componente *TSQLQuery* (ver ¿Cómo leer datos de una tabla?). Si no piensas utilizar la información devuelta por la consulta SQL, entonces también puedes usar el método *ExecuteDirect* de un *TSQLConnection*.
7572
7673   La mayoría de sistemas de base de datos ejecutan las sentencias SQL dentro de una transacción. Si desea que los cambios realizados dentro de una transacción estén disponible en otras transacciones, o disponer de los cambios disponible incluso después de cerrar la transacción, entonces tienes que realizar el *commit* de la transacción. Para soportar las operaciones SQLdb tiene el componente TSQLTransaction. Una sentencia SQL que se ejecuta por SQLdb siempre debe ser ejecutada dentro de una transacción. Incluso si el sistema de base de datos no soporta las transacciones. Además, hay sistemas de bases de datos que soportan transacciones para los que TSQLConnection no (todavía) soporta la transacción. Incluso entonces, debes utilizar el componente TSQLTransaction.
7774
7875   Para utilizar `TSQLConnection.ExecuteDirect` para ejecutar una sentencia SQL debes especificar que *Transaction* se debe utilizar. A su vez, al utilizar `TSQLTransaction` debes especificar que *TSQLConnection* se debe utilizar.
7976
8077   En el ejemplo siguiente se crea una tabla 'TBLNOMBRE' con los campos *NOMBRE* y *nID* e inserta dos registros. Las instrucciones SQL utilizadas no se explican. Para obtener más información acerca de las instrucciones SQL, su uso y su sintaxis, consulte la documentación del sistema de base de datos. El procedimiento *CreateConnection* se define en el ejemplo de código de ¿Cómo conectarse a un servidor de base de datos?.
8178
8279``` pascal
8380program CreateTable;
8481
8582 var AConnection : TSQLConnection;
8683 ATransaction : TSQLTransaction;
8784
8885 procedure CreateTransaction;
8986 begin
9087 ATransaction := TSQLTransaction.Create;
9188 ATransaction.Database := AConnection;
9289 end;
9390
9491 begin
9592 CreateConnection;
9693 CreateTransaction;
9794 AConnection.Transaction := ATransaction;
9895 AConnection.Open;
9996 ATransaction.StartTransaction;
10097 AConnection.ExecuteDirect('create table TBLNAMES (ID integer, NAME varchar(40));');
10198
10299 // Some database-server types need a commit before you can use a newly created table. (Firebird)
103100 // With .Commit you also close the transaction
104101 ATransaction.Commit;
105102
106103 ATransaction.StartTransaction;
107104 AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (1,'Name1');');
108105 AConnection.ExecuteDirect('insert into TBLNAMES (ID,NAME) values (2,'Name2');');
109106 ATransaction.Commit;
110107 AConnection.Close;
111108 AConnection.Free;
112109 ATransaction.Free;
113110 end.
114111```
115112
116113## ¿Cómo leer datos de una tabla?
117114
118115   Utiliza el componente TSQLQuery para leer datos de una tabla. Un componente *TSQLQuery* debe estar enlazado a un componente *TSQLConnection* y a un componente *TSQLTransaction* para hacer su trabajo. El ajuste de *TSQLConnection* y de *TSQLTransaction* se discute en ¿Cómo conectarse a un servidor de base de datos? y en ¿Cómo ejecutar consultas directas o crear una tabla?.
119116
120117   Cuando *TSQLConnection*, *TSQLTransaction* y *TSQLQuery* están conectados, entonces *TSQLQuery* necesita más ajustes. TSQLQuery tiene una propiedad *SQL* que contiene un objeto *TStrings*. La propiedad 'SQL' contiene la sentencia SQL que debe ejecutarse. Si todos los datos de una tabla debe ser leídos establece la propiedad *SQL* a *SELECT * FROM nombretabla;*. Utiliza *open* para leer la tabla desde el servidor y poner los datos en el conjunto de datos *TSQLQuery*. Los datos se pueden acceder a través de *TSQLQuery* hasta que la consulta se cierra con *close*.
121118
122119   *TSQLQuery* es una subclase de *TDataset*. *TDataset* tiene una colección *Fields* que contiene todas las columnas de la tabla. El *TDataset* también mantiene una marca del registro actual. Utiliza *First*, *Next*, *Prior* y *Last* para cambiar el registro actual. *Bof* devuelve *true* (verdadero) si se llegó al primer registro, y *Eof* devuelve *true* si se llegó al último registro. Para leer el valor de un campo en el registro actual, en primer lugar hayamos el objeto *TField* adecuado y luego usar 'AsString', 'AsInteger', etc.
123120
124121   A continuación se muestra un ejemplo que muestra todos los valores de la tabla como se hizo en ¿Cómo ejecutar consultas directas o crear una tabla?.
125122
126123``` pascal
127124Program ShowData;
128125
129126 var AConnection : TSQLConnection;
130127 ATransaction : TSQLTransaction;
131128
132129 procedure GetQuery : TSQLQuery;
133130 var AQuery : TSQLQuery;
134131 begin
135132 AQuery := TSQLQuery.Create;
136133 AQuery.Database := FConnection;
137134 AQuery.Transaction := FTransaction;
138135 Result := AQuery;
139136 end;
140137
141138 var Query : TSQLQuery;
142139
143140 begin
144141 CreateConnection;
145142 CreateTransaction;
146143 Query := GetQuery;
147144 Query.SQL.Text := 'select * from tblNames';
148145 AConnection.Open;
149146 Query.Open;
150147 while not Query.Eof do
151148 begin
152149 Writeln('ID: ', Query.FieldByName('Name').AsInteger, 'Name: ' +
153150 Query.FieldByName('Name').AsString);
154151 Query.Next;
155152 end;
156153 Query.Close;
157154 AConnection.Close;
158155 Query.Free;
159156 ATransaction.Free;
160157 AConnection.Free;
161158 end.
162159```
163160
164161   (El código anterior, por supuesto, no está terminado, se echa de menos bloques *try ... finally*. Sin embargo, el código anterior tiene la intención de mostrar el código para base de datos y por lo tanto los toques finales son dejados de lado.) Ten en cuenta que *TSQLTransaction.StartTransaction* no se utiliza. Esto no es necesario. Cuando *TSQLQuery* se abre, la instrucción SQL se ejecuta y si no hay ninguna transacción está disponible, esta se inicia automáticamente. El programador no necesita iniciar la transacción explícitamente. Lo mismo se aplica para la conexión gestionada por *TSQLConnection*. La conexión se abre según sea necesario, la línea *Aconnection.Open* no es realmente necesaria.
165162
166163   Si se destruye un *TSQLTransaction*, un *rollback* (deshacer) automático será ejecutado. Los posibles cambios a los datos contenidos en la transacción se perderán.
167164
168165### ¿Por qué *TSQLQuery.RecordCount* siempre devuelve 10?
169166
170167   Para contar los registros de un *dataset*, usaremos *RecordCount*. Sin embargo, observa que *RecordCount* muestra el número de registros que se ha cargado desde el servidor. SQLdb no lee todos los registros al abrir un *TSQLQuery* de forma predeterminada, sólo los 10 primeros. Sólo cuando se accede al undécimo registro entonces el siguiente conjunto de 10 registros se carga. Usando *.Last* todos los registros se cargarán.
171168
172169   Si desea conocer el número real de registros en el servidor hay que llamar primero '.Last' y luego llamar a *.RecordCount*. Hay una alternativa disponible. El número de registros devueltos por el servidor está determinado por el valor de la propiedad *PacketRecords*. El valor por defecto es 10, si se pone a -1 entonces todos los registros serán cargados a la vez.
173170
174171### Lazarus
175172
176173   Lazarus tiene diversos componentes para mostrar datos de un *TDataset* en un formulario. En lugar de un bucle *while* y declaraciones *Writeln* usados en el ejemplo, puedes utilizar componentes para mostrar los datos de una tabla. Coloca los adecuados componentes *TSQLConnection*, *TSQLTransaction* y *TSQLQuery* en un formulario, a continuación, se conectan y configuran correctamente. Además se necesita un *TDataSource*, ajusta la propiedad *TDatasource.Dataset* al componente *TSQLQuery* utilizado. (**Nota** no establecer la propiedad *TSQLQuery.Datasource* al componente *TDataSource*. La propiedad *TSQLQuery.Datasource* se utiliza solamente en tablas maestro/detalle) A continuación puedes poner un *TDBGrid* en el formulario y establece la propiedad *Datasource* de la rejill (*grid*) al componente TDataSource agregado antes.
177174
178175   Para ver si funciona todo, establece la propiedad *Connected* del *TSQLConnection* a *True* en el IDE de Lazarus. El IDE intenta conectar con el servidor de base de datos inmediatamente. Si funciona se puede establecer la propiedad *TSQLQuery.Active* a 'True'. Si todo está correcto, podrás ver -en el IDE- todos los datos de la tabla inmediatamente en la pantalla.
179176
180177## ¿Cómo cambiar los datos en una tabla?
181178
182179   Para cambiar datos en un registro, el *TDataset* (del que se deriva *TSQLQuery*) debe ponerse en modo de edición. Para activar el modo de edición podemos llamar a los métodos *.Edit*, *. Insert*o *.Append*. Utiliza el método *.Edita* para modificar el registro actual. Utiliza *.Insert* para crear un nuevo registro antes del registro actual. Utiliza *.Append* paara añadir un nuevo registro al final de la tabla. En modo edición puedes cambiar el valor de los campos a través de la propiedad *Fields*. Utiliza *Post* para validar los nuevos datos, si los datos son válidos entonces se abandona el modo de edición. Si se cambia a un nuevo registro -por ejemplo, utilizando *.Next*- y el conjunto de datos está en modo de edición, se llamará a *.Post* antes. Utiliza *.Cancel* para descartar todos los cambios realizados desde la última llamada a *.Post* y termina el modo de edición.
183180
184181``` pascal
185182 Query.Edit;
186183 Consulta.FieldByName('NOMBRE').AsString := 'Nombre editado';
187184 Consulta.Post;
188185```
189186
190187   Lo anterior no es la historia completa todavía. *TSQLQuery* se deriva de *TBufDataset* que hace uso de actualizaciones en un *buffer*. Actualización en *buffer* significa que después de llamado *Post* los cambios en el conjunto de datos son visibles de inmediato, pero no se envían al servidor de base de datos. Lo que sucede es que los cambios se mantienen en un registro de cambios. Cuando se llama al método *.ApplyUpdates* todos los cambios en el registro de cambios se envían al servidor de base de datos. Sólo entonces el servidor de base de datos conoce todos los cambios. Los cambios se envían al servidor en una transacción de *TSQLTransaction*. Asegúrese de establecer correctamente la transacción antes de *ApplyUpdates*. Después de aplicar las actualizaciones, se debe ejecutar *commit* para publicar o guardar los cambios.
191188
192189   El siguiente es un ejemplo de la cambio de datos en una tabla, envío de los cambios al servidor y confirmación de la transacción.
193190
194191``` pascal
195192 Program EditarDatos;
196193
197194 var unaConexion : TSQLConnection;
198195 unaTransaccion : TSQLTransaction;
199196 Consulta : TSQLQuery;
200197
201198 begin
202199 CrearConexion;
203200 CrearTransaccion;
204201 unaConexion.Transaction := unaTransaccion;
205202 Consulta := GetQuery;
206203 Consulta.SQL.Text := 'select * from tblNombres';
207204 Consulta.Open;
208205 Consulta.Edit;
209206 Consulta.FieldByName('NOMBRE').AsString := 'Nombre editado';
210207 Consulta.Post;
211208 Consulta.UpdateMode := upWhereAll;
212209 Consulta.ApplyUpdates;
213210 AConnection.Transaction.Commit;
214211 Consulta.Free;
215212 unaTransaccion.Free;
216213 unaConexion.Free;
217214 end.
218215```
219216
220217   Para una discusión de *UpdateMode* sigue leyendo.
221218
222219## ¿Cómo SQLdb envia los cambios al servidor de base de datos?
223220
224221   En el ejemplo de código de ¿Cómo cambiar los datos en una tabla?, se encuentra la línea.
225222
226223``` pascal
227224 Consulta.UpdateMode := upWhereAll;
228225```
229226
230227sin ninguna explicación de lo que hace. La mejor manera de averiguar lo que esa línea hace es quitarla. Si se omite la orden y se sigue esta guía con precisión, se recibirá el siguiente mensaje de error:
231228
232229``` pascal
233230 No update query specified and failed to generate one. (No fields for inclusion in where statement found)
234231```
235232
236233   Para entender lo que salió mal, debes entender cómo los cambios se envían al servidor de base de datos. La única manera de obtener datos en un servidor SQL es mediante la ejecución de consultas SQL. SQL tiene tres tipos de consultas para tres maneras diferentes de manipular un registro. Para crear un nuevo registro, cambiar o eliminar un registro las sentencias *insert*, *update* y *delete* se ejecutan, respectivamente. Una sentencia de actualización (*update*) puede ser así:
237234
238235``` pascal
239236 update TBLNAMES set NAME='Edited name' where ID=1;
240237```
241238
242239   Para enviar un cambio al servidor de base de datos, SQLdb debe crear una consulta de actualización. Para crearla consulta, se necesitan tres cosas:
243240
244241El nombre de la tabla
245242El nombre de la tabla se obtiene de analizar la consulta de selección, aunque esto no siempre funciona.
246243
247244Una clásula `UPDATE` o `INSERT`
248245Estas contienen los campos que se deben cambiar.
249246
250247Una clásula `WHERE`
251248Esta contiene los campos que determinan qué registros se deben cambiar.
252249
253250   Todos los campos (cada *TField* en *Fields*) tiene una propiedad *ProviderFlags*. Sólo los campos con *pfInUpdate* en *ProviderFlags* se utilizarán en la clásula de actualización o inserción de la consulta. Por defecto todos los campos tienen *pfInUpdate* puesto en su propiedad *ProviderFlags*.
254251
255252   Qué campos se utilizan en la clásula `WHERE` depende de la propiedad *UpdateMode* de la consulta y la propiedad *ProviderFlags* de los campos. Los campos con *pfInkey* en su *ProviderFlags* siempre se utilizan en la clásula`WHERE`. Un campo tendrá el indicador *pfInKey* establecido de forma automática si el campo es parte de la clave principal de la tabla y *TSQLQuery.UsePrimaryKeyAsKey* devuelve *True*.
256253
257254   El valor predeterminado para *UpdateMode* de la consulta es *upWhereKeyOnly*. En este modo se actualizan los campos sólo con *pfInkey* en su propiedad *ProviderFlags* 'se utilizan en la clásula `WHERE`. Si ninguno de los campos tienen el indicador *pfInKey* establecido, entonces no hay campos disponibles para la cláusula `WHERE` y el mensaje de error del principio de esta sección será devuelto. Puede resolver el problema así:
258255
259256- `Añadir una clave principal a la tabla y poner `*`TSQLQuery.UsePrimaryKeyAsKey`*` a 'True', o`
260257- `Poner el indicador `*`pfInkey`*` para uno o varios campos en el código.`
261258
262259   La propiedad *UpdateMode* puede tener dos posible valores más. *UpWhereAll* puede usarse para agregar todos los campos con el indicador *pfInWhere* establecido para la cláusula `WHERE`. Por defecto todos los campos tienen este indicador establecido. *UpWhereChanged* puede usarse para agregar sólo los campos que tienen el indicador *pfInWhere* establecido **y** que se han modificado del registro actual.
263260
264261## ¿Cómo ejecutar una consulta mediante TSQLQuery?
265262
266263   Junto a las declaraciones que devuelven un conjunto de datos (ver ¿Cómo leer datos de una tabla?) SQL tiene sentencias que no devuelven datos. Por ejemplo `INSERT`, `UPDATE` y `DELETE` no devuelven datos. Estas sentencias se pueden ejecutar mediante *TSQLConnection.ExecuteDirect*, pero *TSQLQuery* puede utilizarse también. Si no esperas devolver datos utiliza *TSQLQuery.ExecSQL* en lugar de *TSQLQuery.Open*. Utiliza *TSQLQuery.Ope*n para abrir el conjunto de datos devuelto por la consulta SQL.
267264
268265   El siguiente procedimiento crea una tabla y se insertan dos registros utilizando *TSQLQuery*.
269266
270267``` pascal
271268procedure CrearTabla;
272269
273270 var Consulta : TSQLConsulta;
274271
275272 begin
276273 Consulta := GetConsulta;
277274 Consulta.SQL.Text := 'create table TBLNOMBRES (ID integer, NOMBRE varchar(40));';
278275 Consulta.ExecSQL;
279276
280277 Consulta.SQL.Text := 'insert into TBLNOMBRES (ID,NOMBRE) values (1,'Nombre1');';
281278 Consulta.ExecSQL;
282279
283280 Consulta.SQL.Text := 'insert into TBLNOMBRES (ID,NOMBRE) values (2,'Nombre2');';
284281 Consulta.ExecSQL;
285282
286283 Consulta.Close;
287284 Consulta.Free;
288285 end;
289286```
290287
291288## ¿Cómo utilizar parámetros en una consulta?
292289
293290   En el código de ejemplo de ¿Cómo ejecutar una consulta mediante TSQLQuery? la misma consulta se utiliza dos veces, sólo difieren en los valores que se insertan. Una manera mejor de hacerlo es mediante el uso de parámetros en la consulta.
294291
295292   La sintaxis de los parámetros en las consultas es diferente en cada sistema de base de datos, pero las diferencias las maneja *TSQLQuery*. Coloca de nuevo los valores en la consulta con dos puntos precediendo al nombre del parámetro que desea utilizar. Por ejemplo:
296293
297294``` pascal
298295 Consulta.SQL.Text := 'insert into TBLNOMBRES (ID,NOMBRE) values (:ID,:NOMBRE);';
299296```
300297
301298   Esta consulta crea dos parámetros: 'ID' y 'NOMBRE'. Para determinar los parámetros, la consulta se analiza en el momento en que se asigna o modifica el texto de *TSQLQuery.SQL*. Todos los parámetros existentes se eliminarán y los nuevos parámetros se añadirán a la propiedad *TSQLQuery.Params*. Asignar un valor a un parámetro es similar a asignar un valor a un campo en el conjunto de datos:
302299
303300``` pascal
304301 Query.Params.ParamByName('Nombre').AsString := 'Name1';
305302```
306303
307304   No se puede saber desde consulta qué tipo de datos deben ser almacenados en el parámetro. El tipo de datos del parámetro se determina en el momento en que un valor se asigna al parámetro. Al asignar un valor utilizando *. AsString*, el parámetro se asigna al tipo de datos *ftString*. Puede determinar el tipo de datos directamente mediante el establecimiento de la propiedad *DataType*. Si un tipo de datos incorrecto se asigna al parámetro, entonces los problemas se producirán durante la apertura o ejecución de la consulta.
308305
309306   En el ejemplo siguiente se crea la misma tabla del ejemplo anterior, pero ahora se utilizan parámetros:
310307
311308``` pascal
312309 procedure CrearTablaUsandoParametros;
313310
314311 var Consulta : TSQLQuery;
315312
316313 begin
317314 Consulta := GetQuery;
318315 Consulta.SQL.Text := 'create table TBLNOMBRES (ID integer, NOMBRE varchar(40));';
319316 Consulta.ExecSQL;
320317
321318 Consulta.SQL.Text := 'insert into TBLNOMBRES (ID,NOMBRE) values (:ID,:NOMBRE);';
322319
323320 Consulta.Params.ParamByName('ID').AsInteger := 1;
324321 Consulta.Params.ParamByName('NOMBRE').AsString := 'Nombre1';
325322 Consulta.ExecSQL;
326323
327324 Consulta.Params.ParamByName('ID').AsInteger := 2;
328325 Consulta.Params.ParamByName('NOMBRE').AsString := 'Nombre2';
329326 Consulta.ExecSQL;
330327
331328 Consulta.Close;
332329 Consulta.Free;
333330 end;
334331```
335332
336333   Observa que este ejemplo requiere más código que el ejemplo sin parámetros. Entonces, ¿qué es el ventaja de la utilización de parámetros? La velocidad es una de las razones. El ejemplo con parámetros es más rápido porque la consulta se analiza solamente una vez. TSQLQuery sólo analiza la consulta una vez, pero también el servidor de base de datos analiza la consulta una sola vez. La mayoría de los sistemas de base de datos soportan parámetros. Siempre que una consulta se utiliza más de una vez con diferentes valores para el parámetro cada vez, entonces el servidor de base de datos sólo analiza la consulta y los planes de la consulta una sola vez haciendo la ejecución considerablemente más rápida.
337334
338335   Utiliza *TSQLQuery.Prepare* para determinar el momento en que se analiza y se planifica la consulta por el servidor de base de datos. Utiliza *TSQLQuery.UnPrepare* para asegurarse de que la consulta se analiza y se planifica cada vez por el servidor de datos.
339336
340337   Otra razón para usar sentencias preparadas es la prevención de [inyección de SQL](http://en.wikipedia.org/wiki/SQL_injection), pero en algunos casos únicamente simplifica la codificación.
341338
342339## Solución de problemas:
343340
344341### Registro de sucesos de *TSQLConnection*
345342
346343   Puedes hacer que TSQLConnection registre lo que está haciendo. Esto puede ser útil para ver exactamente lo que tu programa envía a la base de datos, para depurar los propios componentes de base de datos y también para optimizar las consultas.
347344
348345   Nota: si utilizas comandos preparados o consultas parametrizadas (ver la sección anterior), los parámetros son a menudo enviados en binario por el descendiente de *TSQLConnection* (por ejemplo, *TIBConnection*), por lo que no se puedes simplemente copiar o pegar el código SQL registrado en una herramienta de consulta de la base de datos.
349346
350347   En cualquier caso, el registro de la activad de la conexión puede dar una gran cantidad de información sobre lo que está haciendo tu programa.
351348
352349   Otras alternativas son:
353350
3543511. utilizar el depurador para recorrer el código base de datos si se ha construido el FPC o Lazarus con la depuración habilitada.
3553522. si utilizas controladores ODBC (al menos en Windows) puedes habilitar la salida *tracelog* en el panel de control de ODBC.
3563533. muchas bases de datos permiten controlar todas las ordennes que se le envían desde una determinada dirección IP o conexión.
357354
358355   Para utilizar el registro de actividad de *TSQLConnection*, se requieren dos cosas:
359356
3603571. indicar qué tipos de eventos del *TSQLConnection* deben registrarse
3613582. apuntar *TSQLConnection* a la función que recibe los eventos y los procesa (los registra en un archivo, que se imprima en la pantalla, etc)
362359
363360   Esta función debe ser de tipo *TDBLogNotifyEvent* (ver sqldb.pp), por lo que seguirá este patrón:
364361
365362``` pascal
366363 TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;
367364```
368365
369366   Este fragmento de código puede ilustrar esto:
370367
371368``` pascal
372369 uses
373370 ...//
374371 TSQLConnection, //o un objeto heredero tal que TIBConnection, TMSSQLConnection
375372 ...//
376373 var
377374 type
378375 TMyApplication = class(TCustomApplication); //esta es nuestra aplicación, la que utiliza la conexión
379376 ...//
380377 private
381378 // Este ejemplo guarda el registro en un stringlist:
382379 FConnectionLog: TStringList;
383380 ...//
384381 protected
385382 // Este procedimiento recibe los eventos que registra la conexión:
386383 procedure GetLogEvent(Sender: TSQLConnection; EventType: TDBEventType; Const Msg : String);
387384...
388385 procedure TMyApplication.GetLogEvent(Sender: TSQLConnection;
389386 EventType: TDBEventType; const Msg: String);
390387 // El procedimineto es llamado por TSQLConnection y guarda los mensajes recibidos
391388 // en la lista de cadenas FConnectionLog
392389 var
393390 Source: string;
394391 begin
395392 // Muy bien alineado a la derecha...
396393 case EventType of
397394 detCustom: Source:='Custom: ';
398395 detPrepare: Source:='Prepare: ';
399396 detExecute: Source:='Execute: ';
400397 detFetch: Source:='Fetch: ';
401398 detCommit: Source:='Commit: ';
402399 detRollBack: Source:='Rollback:';
403400 else Source:='Evento desconocido. Corrige el código del programa.';
404401 end;
405402 FConnectionLog.Add(Source + ' ' + Msg);
406403 end;
407404
408405...
409406 // Necesitamos decirle a nuestro TSQLConnection lo que debe registrar:
410407 FConnection.LogEvents:=LogAllEvents; //= [detCustom, detPrepare, detExecute, detFetch, detCommit, detRollBack]
411408 // ... y el procedimiento de la conexión que debe enviar los eventos:
412409 FConnection.OnLog:=@Self.GetLogEvent;
413410...
414411 // Ahora podemos usar la conexión y la lista de cadenas FConnectionLog se llenará con los mensajes de registro.
415412```
416413
417414   También podemos utilizar *GlobalDBLogHook* de *TSQLConnection* en lugar de registrar todo desde múltiples conexiones.
418415
419416   Por último, la descripción anterior es la manera de hacer las cosas en FPC como se indica en la introducción, si se utiliza Lazarus, una forma más rápida es asignar un controlador de eventos al evento *OnLog* de *TSQLConnection*.
420417
421418## See also
422419
423420`* `[[Working With TSQLQuery/es|Trabajando con TSQLQuery]]`.`
424421
425422---
426423*From the Free Pascal wiki, page "SqlDBHowto/es", as it stood on 2020-02-27 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
427424Category: Castellano
428425Category: Español

Back to history