Ruby Доступ к базе данных - Учебник по DBI
В этой главе будет объяснено, как использовать Ruby для доступа к базам данных.Ruby DBIМодуль предоставляет Ruby-скриптам интерфейс, не зависящий от базы данных, аналогичный модулю Perl DBI.
DBI расшифровывается как Database Independent Interface, представляющий независимый от базы данных интерфейс Ruby. DBI обеспечивает уровень абстракции между кодом Ruby и нижележащей базой данных, позволяя легко переключаться между базами данных. Он определяет ряд методов, переменных и спецификаций, предоставляя согласованный интерфейс базы данных, не зависящий от базы данных.
DBI может взаимодействовать со следующим:
- ADO (ActiveX Data Objects)
- DB2
- Frontbase
- mSQL
- MySQL
- ODBC
- Oracle
- OCI8 (Oracle)
- PostgreSQL
- Прокси/Сервер
- SQLite
- SQLRelay
Архитектура приложений DBI
DBI не зависит от любой базы данных, доступной в фоновом режиме. Используете ли вы Oracle, MySQL или Informix, вы можете использовать DBI. Следующая схема архитектуры наглядно это иллюстрирует.
Ruby DBI обычно использует двухуровневую архитектуру:
- Уровень интерфейса базы данных (DBI). Этот уровень не зависит от базы данных и предоставляет ряд публичных методов доступа, которые можно использовать независимо от типа сервера базы данных.
- Уровень драйвера базы данных (DBD). Этот уровень зависит от базы данных; разные драйверы обеспечивают доступ к разным движкам баз данных. MySQL, PostgreSQL, InterBase, Oracle и т. д. используют разные драйверы. Каждый драйвер отвечает за интерпретацию запросов из уровня DBI и сопоставление этих запросов с запросами, подходящими для данного типа сервера базы данных.
Установка
Если вы хотите писать скрипты на Ruby для доступа к базе данных MySQL, сначала необходимо установить модуль MySQL для Ruby.
Установка пакета разработки MySQL
В Mac OS необходимо изменить файл ~/.bash_profile или ~/.profile и добавить следующий код:
Или используйте символическую ссылку:
Установка DBI с помощью RubyGems (рекомендуется)
RubyGems был создан примерно в ноябре 2003 года и входит в стандартную библиотеку Ruby начиная с Ruby 1.9. Для получения дополнительных сведений см.:Ruby RubyGems
Используйте gem для установки dbi и dbd-mysql:
Установка из исходного кода (используйте этот метод для версий Ruby до 1.9)
Этот модуль является DBD, и его можно загрузить сhttp://tmtm.org/downloads/mysql/ruby/.
После загрузки последнего пакета распакуйте его, войдите в каталог и выполните следующие команды для установки:
Затем скомпилируйте:
Получение и установка Ruby/DBI
Вы можете скачать и установить модуль Ruby DBI по ссылке ниже:
https://github.com/erikh/ruby-dbi
Перед началом установки убедитесь, что у вас есть права root. Теперь выполните следующие шаги для установки:
Шаг 1
Или напрямую скачайте zip-архив и распакуйте его.
Шаг 2
Войдите в каталогruby-dbi-masterи в этом каталоге используйте скриптsetup.rbдля настройки. Самая распространённая команда настройки — 'config' без параметров. По умолчанию эта команда устанавливает все драйверы.
Точнее, вы можете использовать опцию --with, чтобы перечислить конкретные части, которые хотите использовать. Например, если вы хотите настроить только основной модуль DBI и драйвер слоя MySQL DBD, введите следующую команду:
Шаг 3
Последний шаг — собрать драйверы и установить их с помощью следующей команды:
Подключение к базе данных
Предполагая, что мы используем базу данных MySQL, перед подключением к базе данных убедитесь:
- Вы создали базу данных TESTDB.
- Вы создали таблицу EMPLOYEE в TESTDB.
- Таблица содержит поля FIRST_NAME, LAST_NAME, AGE, SEX и INCOME.
- Установите идентификатор пользователя "testuser" и пароль "test123" для доступа к TESTDB.
- Модуль DBI для Ruby был корректно установлен на вашем компьютере.
- Вы прочитали руководство по MySQL и понимаете основные операции MySQL.
Ниже приведён пример подключения к базе данных MySQL "TESTDB":
Пример
При запуске этого скрипта на машине Linux будут получены следующие результаты.
Server version: 5.0.45
Если соединение установлено с источником данных, возвращается дескриптор базы данных и сохраняется вdbhдля дальнейшего использования, в противном случаеdbhбудет установлен в nil,e.errиe::errstrвозвращает код ошибки и строку ошибки соответственно.
Наконец, перед выходом из этой программы обязательно закройте соединение с базой данных и освободите ресурсы.
Операция INSERT
Когда вы хотите создать записи в таблице базы данных, вам нужно использовать операцию INSERT.
После установки соединения с базой данных мы можем подготовиться к использованию методаdoилиprepareиexecuteметод для создания таблиц или создания записей для вставки в таблицы базы данных.
Использование оператора do
Инструкции, которые не возвращают строки, можно выполнить, вызвав методdoобработки базы данных. Этот метод принимает строковый параметр инструкции и возвращает количество строк, затронутых инструкцией.
Аналогично вы можете выполнять SQLINSERTинструкции, чтобы создавать записи и вставлять их в таблицу EMPLOYEE.
Пример
Использованиеprepareиexecute
Вы можете использовать методы DBI:prepareиexecuteдля выполнения SQL-запросов в коде Ruby.
Шаги по созданию записей следующие:
- Подготовьте SQL-запрос с помощью инструкции INSERT. Это будет сделано с использованием методаprepare.
- Выполните SQL-запрос, чтобы выбрать все результаты из базы данных. Это будет сделано с использованием методаexecute.
- Освободите дескриптор запроса. Это будет сделано с использованиемfinishAPI.
- Если всё идет гладко, тоcommitэту операцию, иначе вы можетеrollbackзавершить транзакцию.
Ниже приведен синтаксис использования этих двух методов:
Пример
Эти два метода можно использовать для передачиbindзначений в SQL-запросы. Иногда значения для ввода могут быть не заданы заранее; в этом случае используются связанные значения. Используйте вопросительный знак (?) вместо фактического значения, а фактическое значение передается через API execute().
В следующем примере создаются две записи в таблице EMPLOYEE:
Пример
Если вы используете несколько INSERTs, подготовка одного оператора и его многократное выполнение в цикле гораздо эффективнее, чем вызов do при каждом проходе цикла.
Операция READ
Операция READ в любой базе данных означает извлечение полезной информации из базы данных.
После установления соединения с базой данных мы можем подготовиться к запросу к базе данных. Мы можем использовать методdoилиprepareиexecuteметод для извлечения значений из таблиц базы данных.
Шаги для извлечения записей следующие:
- На основе требуемых условий подготовьте SQL-запрос. Это делается с помощью методаprepare.
- Выполните SQL-запрос, чтобы выбрать все результаты из базы данных. Это делается с помощью методаexecute.
- Извлекайте результаты по одному и выводите эти результаты. Это делается с помощью методаfetch.
- Освободите дескриптор оператора. Это делается с помощью методаfinish.
В следующем примере из таблицы EMPLOYEE извлекаются все записи с зарплатой больше 1000.
Пример
Это даст следующий результат:
First Name: Mac, Last Name : Mohan Age: 20, Sex : M Salary :2000 First Name: John, Last Name : Poul Age: 25, Sex : M Salary :2300
Существует много других методов для извлечения записей из базы данных. Если вам интересно, вы можете ознакомиться сОперацией чтения Ruby DBI。
Операция обновления
Операция UPDATE в любой базе данных означает обновление одной или нескольких существующих записей в базе данных. В следующем примере обновляются все записи с SEX = 'M'. Здесь мы увеличим AGE всех мужчин на один год. Это разделено на три шага:
- На основе требуемых условий подготовьте SQL-запрос. Это делается с помощью методаprepare.
- Выполните SQL-запрос, чтобы выбрать все результаты из базы данных. Это делается с помощью методаexecute.
- Освободите дескриптор оператора. Это делается с помощью методаfinish.
- Если всё пройдёт хорошо, тоcommitоперацию, иначе вы можетеrollbackзавершить транзакцию.
Пример
Операция DELETE
Когда вы хотите удалить записи из базы данных, необходимо использовать операцию DELETE. Следующий пример удаляет все записи из EMPLOYEE, у которых AGE превышает 20. Шаги этой операции следующие:
- На основе требуемых условий подготовьте SQL-запрос. Это делается с помощью методаprepare.
- Выполните SQL-запрос для удаления нужных записей из базы данных. Это делается с помощью методаexecute.
- Освободите дескриптор оператора. Это делается с помощью методаfinish.
- Если всё пройдёт хорошо, тоcommitоперацию, иначе вы можетеrollbackзавершить транзакцию.
Пример
Выполнение транзакций
Транзакция — это механизм, обеспечивающий согласованность транзакций. Транзакция должна обладать следующими четырьмя свойствами:
- Атомарность:Атомарность транзакции означает, что программы, входящие в транзакцию, представляют собой логическую единицу работы с базой данных; выполняемые ими операции модификации данных выполняются либо все, либо ни одна.
- Согласованность:Согласованность транзакции означает, что база данных должна находиться в согласованном состоянии до и после выполнения транзакции. Если состояние базы данных удовлетворяет всем ограничениям целостности, говорят, что база данных согласована.
- Изоляция:Изоляция транзакций означает, что параллельные транзакции изолированы друг от друга, то есть операции внутри транзакции и данные, с которыми они работают, должны быть заблокированы и невидимы для других транзакций, пытающихся их изменить.
- Долговечность:Долговечность транзакции означает, что при сбое системы или носителя гарантируется, что обновления зафиксированных транзакций не будут потеряны. То есть, как только транзакция зафиксирована, её изменения данных в базе данных должны быть постоянными и выдерживать любой сбой системы базы данных. Долговечность обеспечивается за счёт резервного копирования и восстановления базы данных.
DBI предоставляет два метода для выполнения транзакций. Один —commitилиrollbackметод, используемый для фиксации или отката транзакций. Другой —transactionметод, который можно использовать для реализации транзакций. Далее давайте рассмотрим эти два простых метода реализации транзакций:
Метод I
Первый метод использует DBIcommitиrollbackметод для явной фиксации или отмены транзакции:
Пример
Метод II
Второй метод используетtransactionметод. Этот метод относительно проще, потому что он требует блок кода, содержащий инструкции, составляющие транзакцию.transactionМетод выполняет блок, а затем, в зависимости от того, успешно ли выполнился блок, автоматически вызываетcommitилиrollback:
Пример
Операция COMMIT
Commit — это операция, которая помечает базу данных как завершившую изменения. После этой операции все изменения необратимы.
Ниже приведён простой пример вызова методаcommit.
Операция ROLLBACK
Если вас не устраивают одно или несколько изменений и вы хотите полностью отменить эти изменения, используйте методrollback.
Ниже приведён простой пример вызова методаrollback.
Отключение от базы данных
Чтобы отключиться от базы данных, используйте API disconnect.
Если пользователь закрывает соединение с базой данных через метод disconnect, DBI откатит все незавершённые транзакции. Однако, не полагаясь на какие-либо детали реализации DBI, ваше приложение может корректно явно вызвать commit или rollback.
Обработка ошибок
Существует много разных источников ошибок. Например, синтаксические ошибки при выполнении SQL-инструкций, сбои соединения или вызов метода fetch для отменённого или завершённого дескриптора оператора.
Если метод DBI завершается с ошибкой, DBI возбуждает исключение. Методы DBI могут возбуждать исключения любого типа, но два наиболее важных класса исключений — этоDBI::InterfaceErrorиDBI::DatabaseError。
Объекты исключений этих классов имеютerr、errstrиstateтри атрибута, соответственно представляющих номер ошибки, описательную строку ошибки и стандартный код ошибки. Атрибуты подробно описаны ниже:
- err:Возвращает целочисленное представление возникшей ошибки; если DBD это не поддерживает, он возвращаетnil. Например, Oracle DBD возвращаетORA-XXXXчисловую часть сообщения об ошибке.
- errstr:Возвращает строковое представление возникшей ошибки.
- state:Возвращает код SQLSTATE возникшей ошибки. SQLSTATE — строка из пяти символов. Большинство DBD не поддерживают его, поэтому возвращают nil.
В приведённых выше примерах вы уже видели следующий код:
Чтобы получать отладочную информацию о том, что делает скрипт во время выполнения, можно включить трассировку. Для этого нужно сначала загрузить модуль dbi/trace, а затем вызвать методtrace:
Значение mode может быть 0 (выкл.), 1, 2 или 3, а значение destination должно быть объектом IO. Значения по умолчанию — 2 и STDERR соответственно.
Блоки кода методов
Есть методы, которые создают дескрипторы. Эти методы вызываются с блоком кода. Преимущество использования блоков кода с методами состоит в том, что они передают дескриптор блоку в качестве аргумента, а дескриптор автоматически очищается при завершении блока. Ниже приведены некоторые примеры, помогающие понять эту концепцию.
- DBI.connect :Этот метод создаёт дескриптор базы данных. Рекомендуется вызывать в конце блокаdisconnect, чтобы отключиться от базы данных.
- dbh.prepare :Этот метод создаёт дескриптор оператора. Рекомендуется вызывать в конце блокаfinish. Внутри блока необходимо вызвать методexecute, чтобы выполнить оператор.
- dbh.execute :Этот метод похож на dbh.prepare, но при использовании dbh.execute не нужно вызывать метод execute внутри блока. Дескриптор оператора выполняется автоматически.
Пример 1
DBI.connectОн может принимать блок кода, передавать ему дескриптор базы данных и автоматически отключать дескриптор в конце блока.
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost",
"testuser", "test123") do |dbh|
Пример 2
dbh.prepareОн может принимать блок кода, передавать ему дескриптор оператора и автоматически вызывать finish в конце блока.
Пример 3
dbh.executeОн может принимать блок кода, передавать ему дескриптор оператора и автоматически вызывать finish в конце блока.
DBI transactionМетод также может принимать блок кода, как уже объяснялось в предыдущих главах.
Функции и атрибуты, специфичные для драйвера
DBI позволяет драйверам баз данных предоставлять дополнительные функции, специфичные для базы данных, которые пользователь может вызывать через методfuncлюбого объекта Handle.
Используйте метод[]= или []для установки или получения атрибутов, специфичных для драйвера.
DBD::Mysql реализует следующие функции, специфичные для драйвера:
| Нет. | Функция и описание |
|---|---|
| 1 | dbh.func(:createdb, db_name) Создаёт новую базу данных. |
| 2 | dbh.func(:dropdb, db_name) Удаляет базу данных. |
| 3 | dbh.func(:reload) Выполняет операцию перезагрузки. |
| 4 | dbh.func(:shutdown) Выключает сервер. |
| 5 | dbh.func(:insert_id) => Fixnum Возвращает последнее значение AUTO_INCREMENT для этого соединения. |
| 6 | dbh.func(:client_info) => String Возвращает информацию о клиенте MySQL на основе версии. |
| 7 | dbh.func(:client_version) => Fixnum Возвращает информацию о клиенте на основе версии. Это похоже на :client_info, но возвращает fixnum вместо строки. |
| 8 | dbh.func(:host_info) => String Возвращает информацию о хосте. |
| 9 | dbh.func(:proto_info) => Fixnum Возвращает протокол, используемый для связи. |
| 10 | dbh.func(:server_info) => String Возвращает информацию о серверной части MySQL в зависимости от версии. |
| 11 | dbh.func(:stat) => Stringb> Возвращает текущий статус базы данных. |
| 12 | dbh.func(:thread_id) => Fixnum Возвращает ID текущего потока. |
#!/usr/bin/ruby
require "dbi"
begin
#Подключение к серверу 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 "Произошла ошибка"
puts "Код ошибки: #{e.err}"
puts "Сообщение об ошибке: #{e.errstr}"
ensure
dbh.disconnect if dbh
end
Это даст следующий результат:
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