Ruby Acceso a bases de datos - Tutorial DBI
En este capítulo se explicará cómo usar Ruby para acceder a bases de datos.Ruby DBIEl módulo DBI proporciona a los scripts de Ruby una interfaz independiente de la base de datos, similar al módulo Perl DBI.
DBI significa Database Independent Interface, que representa la interfaz independiente de la base de datos de Ruby. DBI proporciona una capa de abstracción entre el código Ruby y la base de datos subyacente, lo que le permite cambiar de base de datos fácilmente. Define una serie de métodos, variables y especificaciones, ofreciendo una interfaz de base de datos consistente e independiente de la base de datos.
DBI puede interactuar con lo siguiente:
- ADO (ActiveX Data Objects)
- DB2
- Frontbase
- mSQL
- MySQL
- ODBC
- Oracle
- OCI8 (Oracle)
- PostgreSQL
- Proxy/Server
- SQLite
- SQLRelay
Arquitectura de la aplicación DBI
DBI es independiente de cualquier base de datos disponible en segundo plano. Ya sea que use Oracle, MySQL o Informix, puede usar DBI. El siguiente diagrama de arquitectura lo ilustra claramente.
La arquitectura general de Ruby DBI utiliza dos capas:
- Capa de interfaz de base de datos (DBI). Esta capa es independiente de la base de datos y proporciona una serie de métodos de acceso públicos, cuyo uso no depende del tipo de servidor de base de datos.
- Capa de controlador de base de datos (DBD). Esta capa depende de la base de datos; diferentes controladores proporcionan acceso a diferentes motores de base de datos. MySQL, PostgreSQL, InterBase, Oracle, etc. usan controladores distintos. Cada controlador se encarga de interpretar las solicitudes de la capa DBI y mapear esas solicitudes a solicitudes adecuadas para un tipo determinado de servidor de base de datos.
Instalación
Si desea escribir scripts de Ruby para acceder a bases de datos MySQL, primero debe instalar el módulo MySQL de Ruby.
Instalar el paquete de desarrollo de MySQL
En Mac OS, debe modificar el archivo ~/.bash_profile o ~/.profile y agregar el siguiente código:
O usar un enlace simbólico:
Instalar DBI con RubyGems (recomendado)
RubyGems se creó alrededor de noviembre de 2003 y pasó a formar parte de la biblioteca estándar de Ruby desde la versión 1.9. Para más detalles, consulte:Ruby RubyGems
Use gem para instalar dbi y dbd-mysql:
Instalar desde el código fuente (usar este método para versiones de Ruby menores a 1.9)
Este módulo es un DBD, se puedehttp://tmtm.org/downloads/mysql/ruby/descargar desde.
Después de descargar el último paquete, descomprímalo y entre en el directorio, luego ejecute el siguiente comando para instalarlo:
Luego compile:
Obtener e instalar Ruby/DBI
Puede descargar e instalar el módulo Ruby DBI desde el siguiente enlace:
https://github.com/erikh/ruby-dbi
Antes de comenzar la instalación, asegúrese de tener privilegios de root. Ahora, siga los pasos a continuación para instalar:
Paso 1
O descargue directamente el paquete zip y descomprímalo.
Paso 2
Entre en el directorioruby-dbi-master, y en el directorio usesetup.rbscript para configurar. El comando de configuración más común es config sin ningún parámetro. Este comando, por defecto, se configura para instalar todos los controladores.
Más específicamente, puede usar la opción --with para listar las partes específicas que desea utilizar. Por ejemplo, si solo desea configurar el módulo DBI principal y el controlador de la capa MySQL DBD, introduzca el siguiente comando:
Paso 3
El último paso es construir el controlador. Use el siguiente comando para instalar:
Conexión a la base de datos
Suponiendo que usamos una base de datos MySQL, antes de conectarse a la base de datos, asegúrese de:
- Ha creado una base de datos TESTDB.
- Ha creado la tabla EMPLOYEE en TESTDB.
- La tabla tiene los campos FIRST_NAME, LAST_NAME, AGE, SEX e INCOME.
- Establezca el ID de usuario "testuser" y la contraseña "test123" para acceder a TESTDB
- Ha instalado correctamente el módulo Ruby DBI en su máquina.
- Ha leído el tutorial de MySQL y ha comprendido las operaciones básicas de MySQL.
A continuación se muestra un ejemplo de conexión a la base de datos MySQL "TESTDB":
Ejemplo
Al ejecutar este script, se producirá el siguiente resultado en una máquina Linux.
Server version: 5.0.45
Si la conexión se establece con una fuente de datos, se devuelve un manejador de base de datos (Database Handle) y se guarda endbhpara su uso posterior; de lo contrario,dbhse establecerá en nil,e.errye::errstrse devuelven el código de error y la cadena de error respectivamente.
Finalmente, antes de salir del programa, asegúrese de cerrar la conexión a la base de datos y liberar recursos.
Operación INSERT
Cuando desee crear registros en una tabla de base de datos, necesitará usar la operación INSERT.
Una vez establecida la conexión con la base de datos, podemos prepararnos para usardométodo oprepareyexecutemétodo para crear una tabla o insertar registros en la tabla de datos.
Usar la declaración do
Las declaraciones que no devuelven filas se pueden ejecutar llamando adométodo de procesamiento de base de datos. Este método toma un parámetro de cadena de declaración y devuelve el número de filas afectadas por la declaración.
De manera similar, puede ejecutar SQLINSERTdeclaración para crear registros e insertarlos en la tabla EMPLOYEE.
Ejemplo
Usoprepareyexecute
Puede usar el método de DBIprepareyexecutepara ejecutar declaraciones SQL en código Ruby.
Los pasos para crear un registro son los siguientes:
- Prepare una declaración SQL con una declaración INSERT. Esto se realizará usandoprepareel método.
- Ejecute la consulta SQL para seleccionar todos los resultados de la base de datos. Esto se realizará usandoexecuteel método.
- Libere el manejador de declaración. Esto se realizará usandofinishel API.
- Si todo va bien, entoncescommitla operación; de lo contrario, puederollbackconfirmar la transacción.
A continuación se muestra la sintaxis para usar estos dos métodos:
Ejemplo
Estos dos métodos se pueden usar para pasarbindvalores a declaraciones SQL. A veces, los valores ingresados pueden no estar dados de antemano; en este caso, se utilizan valores vinculados. Use un signo de interrogación (?) en lugar del valor real, y el valor real se pasa a través de la API execute().
El siguiente ejemplo crea dos registros en la tabla EMPLOYEE:
Ejemplo
Si se usan varios INSERT a la vez, preparar una sola declaración y luego ejecutarla varias veces en un bucle es mucho más eficiente que llamar a do cada vez en el bucle.
Operación READ
La operación READ en cualquier base de datos se refiere a obtener información útil de la base de datos.
Una vez establecida la conexión con la base de datos, podemos prepararnos para consultar la base de datos. Podemos usardométodo oprepareyexecutemétodo para obtener valores de las tablas de la base de datos.
Los pasos para obtener registros son los siguientes:
- Prepare la consulta SQL basada en las condiciones requeridas. Esto se hará mediante el uso delpreparemétodo para completar.
- Ejecute la consulta SQL y seleccione todos los resultados de la base de datos. Esto se hará mediante el uso delexecutemétodo para completar.
- Obtenga los resultados uno a uno y muéstrelos. Esto se hará mediante el uso delfetchmétodo para completar.
- Libere el manejador de sentencia. Esto se hará mediante el uso delfinishmétodo para completar.
El siguiente ejemplo consulta todos los registros de la tabla EMPLOYEE cuyo salario (salary) supera los 1000.
Ejemplo
Esto producirá el siguiente resultado:
First Name: Mac, Last Name : Mohan Age: 20, Sex : M Salary :2000 First Name: John, Last Name : Poul Age: 25, Sex : M Salary :2300
Hay muchos otros métodos para obtener registros de la base de datos. Si está interesado, puede consultarla operación Read de Ruby DBI。
Operación UPDATE
La operación UPDATE en cualquier base de datos consiste en actualizar uno o más registros existentes en la base de datos. El siguiente ejemplo actualiza todos los registros con SEX como 'M'. Aquí, incrementaremos la edad (AGE) de todos los varones en un año. Esto se divide en tres pasos:
- Prepare la consulta SQL basada en las condiciones requeridas. Esto se hará mediante el uso delpreparemétodo para completar.
- Ejecute la consulta SQL y seleccione todos los resultados de la base de datos. Esto se hará mediante el uso delexecutemétodo para completar.
- Libere el manejador de sentencia. Esto se hará mediante el uso delfinishmétodo para completar.
- Si todo va bien, entoncescommitdicha operación; de lo contrario, puederollbackcompletar la transacción.
Ejemplo
Operación DELETE
Cuando desee eliminar registros de la base de datos, necesitará la operación DELETE. El siguiente ejemplo elimina todos los registros de EMPLOYEE cuya edad (AGE) supere los 20. Los pasos de esta operación son los siguientes:
- Prepare la consulta SQL basada en las condiciones requeridas. Esto se hará mediante el uso delpreparemétodo para completar.
- Ejecute la consulta SQL para eliminar los registros deseados de la base de datos. Esto se hará mediante el uso delexecutemétodo para completar.
- Libere el manejador de sentencia. Esto se hará mediante el uso delfinishmétodo para completar.
- Si todo va bien, entoncescommitdicha operación; de lo contrario, puederollbackcompletar la transacción.
Ejemplo
Ejecutar transacciones
Una transacción es un mecanismo que garantiza la consistencia de las operaciones. Una transacción debe tener las siguientes cuatro propiedades:
- Atomicidad:La atomicidad de una transacción se refiere a que el programa incluido en la transacción actúa como una unidad lógica de trabajo de la base de datos; las operaciones de modificación de datos que realiza deben ejecutarse todas o no ejecutarse en absoluto.
- Consistencia:La consistencia de una transacción se refiere a que la base de datos debe estar en un estado consistente antes y después de la ejecución de una transacción. Si el estado de la base de datos satisface todas las restricciones de integridad, se dice que la base de datos es consistente.
- Aislamiento:El aislamiento de una transacción significa que las transacciones concurrentes están aisladas entre sí, es decir, las operaciones internas de una transacción y los datos que se están operando deben estar bloqueados y no ser visibles para otras transacciones que intenten modificarlos.
- Durabilidad:La durabilidad de una transacción significa que, cuando ocurre una falla en el sistema o en el medio, se garantiza que las actualizaciones de las transacciones confirmadas no se pierdan. Es decir, una vez que una transacción se confirma, los cambios que realiza en los datos de la base de datos deben ser permanentes y resistir cualquier falla del sistema de base de datos. La durabilidad se garantiza mediante la copia de seguridad y la recuperación de la base de datos.
DBI ofrece dos métodos para ejecutar transacciones. Uno es elcommitorollbackmétodo, que se utiliza para confirmar o revertir transacciones. El otro es eltransactionmétodo, que se puede utilizar para implementar transacciones. A continuación, presentaremos estos dos métodos simples para implementar transacciones:
Método I
El primer método utiliza elcommityrollbackmétodo de DBI para confirmar o cancelar explícitamente la transacción:
Ejemplo
Método II
El segundo método utiliza eltransactionmétodo. Este método es relativamente más simple, ya que requiere un bloque de código que contiene las sentencias que constituyen la transacción.transactionel método ejecuta el bloque y, según si el bloque se ejecutó correctamente, llama automáticamente acommitorollback:
Ejemplo
Operación COMMIT
Commit es una operación que indica que la base de datos ha completado los cambios; después de esta operación, todos los cambios son irreversibles.
A continuación se muestra un ejemplo simple de invocación delcommitmétodo.
Operación ROLLBACK
Si no está satisfecho con uno o varios cambios y desea revertirlos por completo, utilice elrollbackmétodo.
A continuación se muestra un ejemplo simple de invocación delrollbackmétodo.
Desconectar la base de datos
Para desconectar la conexión a la base de datos, utilice la API disconnect.
Si el usuario cierra la conexión a la base de datos mediante el método disconnect, DBI revertirá todas las transacciones pendientes. Sin embargo, no es necesario depender de ningún detalle de implementación de DBI; su aplicación puede llamar explícitamente a commit o rollback sin problemas.
Manejo de errores
Existen muchas fuentes diferentes de errores. Por ejemplo, errores de sintaxis al ejecutar sentencias SQL, fallos de conexión, o llamar al método fetch sobre un manejador de sentencia que ya ha sido cancelado o completado.
Si algún método de DBI falla, DBI lanza una excepción. Los métodos de DBI pueden lanzar cualquier tipo de excepción, pero las dos clases de excepción más importantes sonDBI::InterfaceErroryDBI::DatabaseError。
Los objetos Exception de estas clases tienenerr、errstrystatetres atributos, que representan respectivamente el número de error, una cadena descriptiva de error y un código de error estándar. La descripción detallada de los atributos es la siguiente:
- err:Devuelve la representación entera del error ocurrido; si DBD no lo admite, devuelvenil. Por ejemplo, Oracle DBD devuelveORA-XXXXla parte numérica del mensaje de error.
- errstr:Devuelve la representación de cadena del error ocurrido.
- state:Devuelve el código SQLSTATE del error ocurrido. SQLSTATE es una cadena de cinco caracteres de longitud. La mayoría de los DBD no lo admiten, por lo que devuelven nil.
En los ejemplos anteriores ya ha visto el siguiente código:
Para obtener información de depuración sobre lo que se ejecuta durante la ejecución del script, puede habilitar el rastreo. Para ello, primero debe descargar el módulo dbi/trace y luego llamar al método que controla el modo de rastreo y el destino de salida:tracemétodo:
El valor de mode puede ser 0 (off), 1, 2 o 3; el valor de destination debe ser un objeto IO. Los valores predeterminados son 2 y STDERR, respectivamente.
Bloques de código de métodos
Hay algunos métodos para crear manejadores. Estos métodos se invocan mediante bloques de código. La ventaja de usar bloques de código con métodos es que proporcionan el manejador como parámetro al bloque y automáticamente limpian el manejador al finalizar el bloque. A continuación se presentan algunos ejemplos que ayudan a entender este concepto.
- DBI.connect :Este método genera un manejador de base de datos; se recomienda llamar al final del bloquedisconnectpara desconectar la base de datos.
- dbh.prepare :Este método genera un manejador de sentencia; se recomienda llamar al final del bloque. Dentro del bloque, debe llamar alfinishDentro del bloque, debe llamar alexecutemétodo para ejecutar la sentencia.
- dbh.execute :Este método es similar a dbh.prepare, pero con dbh.execute no se necesita llamar al método execute dentro del bloque. El manejador de sentencia se ejecuta automáticamente.
Ejemplo 1
DBI.connectPuede llevar un bloque de código al que se le pasa el manejador de base de datos, y al final del bloque se desconecta automáticamente el manejador.
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost",
"testuser", "test123") do |dbh|
Ejemplo 2
dbh.preparePuede llevar un bloque de código al que se le pasa el manejador de sentencia, y al final del bloque se llama automáticamente a finish.
Ejemplo 3
dbh.executePuede llevar un bloque de código al que se le pasa el manejador de sentencia, y al final del bloque se llama automáticamente a finish.
DBI transactionEl método también puede llevar un bloque de código, como ya se explicó en los capítulos anteriores.
Funciones y atributos de controladores específicos
DBI permite que los controladores de base de datos proporcionen funciones adicionales específicas de la base de datos; los usuarios pueden invocarlas a través delfuncmétodo de cualquier objeto Handle para invocarlas.
Se pueden establecer u obtener atributos específicos del controlador usando el[]= or []método.
DBD::Mysql implementa las siguientes funciones específicas del controlador:
| No. | Función y descripción |
|---|---|
| 1 | dbh.func(:createdb, db_name) Crea una nueva base de datos. |
| 2 | dbh.func(:dropdb, db_name) Elimina una base de datos. |
| 3 | dbh.func(:reload) Ejecuta una operación de recarga. |
| 4 | dbh.func(:shutdown) Cierra el servidor. |
| 5 | dbh.func(:insert_id) => Fixnum Devuelve el valor AUTO_INCREMENT más reciente de esa conexión. |
| 6 | dbh.func(:client_info) => String Devuelve información del cliente MySQL según la versión. |
| 7 | dbh.func(:client_version) => Fixnum Devuelve información del cliente según la versión. Esto es similar a :client_info, pero devuelve un fixnum en lugar de una cadena. |
| 8 | dbh.func(:host_info) => String Devuelve la información del host. |
| 9 | dbh.func(:proto_info) => Fixnum Devuelve el protocolo utilizado para la comunicación. |
| 10 | dbh.func(:server_info) => String Devuelve la información del lado del servidor MySQL según la versión. |
| 11 | dbh.func(:stat) => Stringb> Devuelve el estado actual de la base de datos. |
| 12 | dbh.func(:thread_id) => Fixnum Devuelve el ID del hilo actual. |
#!/usr/bin/ruby
require "dbi"
begin
#Conectar al servidor MySQL
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost",
"testuser", "test123")
puts dbh.func(:client_info)
puts dbh.func(:client_version)
puts dbh.func(:host_info)
puts dbh.func(:proto_info)
puts dbh.func(:server_info)
puts dbh.func(:thread_id)
puts dbh.func(:stat)
rescue DBI::DatabaseError => e
puts "An error occurred"
puts "Error code: #{e.err}"
puts "Error message: #{e.errstr}"
ensure
dbh.disconnect if dbh
end
Esto producirá el siguiente resultado:
5.0.45 50045 Localhost via UNIX socket 10 5.0.45 150621 Uptime: 384981 Threads: 1 Questions: 1101078 Slow queries: 4 \ Opens: 324 Flush tables: 1 Open tables: 64 \ Queries per second avg: 2.860