Samouczek dotyczący języka Ruby / DBI

W tym rozdziale dowiesz się, jak uzyskać dostęp do bazy danych za pomocą Rubiego. Moduł Ruby DBI zapewnia interfejs niezależny od bazy danych dla skryptów Ruby, podobny do modułu Perl DBI.

DBI to skrót od Database Independent Interface for Ruby, co oznacza, że ​​DBI zapewnia warstwę abstrakcji między kodem Ruby a bazową bazą danych, umożliwiając naprawdę łatwe przełączanie implementacji bazy danych. Definiuje zestaw metod, zmiennych i konwencji, które zapewniają spójny interfejs bazy danych, niezależnie od aktualnie używanej bazy danych.

DBI może współpracować z następującymi -

  • ADO (obiekty danych ActiveX)
  • DB2
  • Frontbase
  • mSQL
  • MySQL
  • ODBC
  • Oracle
  • OCI8 (Oracle)
  • PostgreSQL
  • Proxy/Server
  • SQLite
  • SQLRelay

Architektura aplikacji DBI

DBI jest niezależne od jakiejkolwiek bazy danych dostępnej na zapleczu. Możesz używać DBI niezależnie od tego, czy pracujesz z Oracle, MySQL czy Informix, itp. Wynika to jasno z poniższego diagramu architektury.

Ogólna architektura Ruby DBI wykorzystuje dwie warstwy -

  • Warstwa interfejsu bazy danych (DBI). Ta warstwa jest niezależna od bazy danych i zapewnia zestaw typowych metod dostępu, które są używane w ten sam sposób, niezależnie od typu serwera bazy danych, z którym się komunikujesz.

  • Warstwa sterownika bazy danych (DBD). Ta warstwa jest zależna od bazy danych; różne sterowniki zapewniają dostęp do różnych silników baz danych. Jest jeden sterownik dla MySQL, inny dla PostgreSQL, inny dla InterBase, inny dla Oracle i tak dalej. Każdy sterownik interpretuje żądania z warstwy DBI i mapuje je na żądania właściwe dla danego typu serwera bazy danych.

Wymagania wstępne

Jeśli chcesz pisać skrypty Ruby, aby uzyskać dostęp do baz danych MySQL, musisz mieć zainstalowany moduł Ruby MySQL.

Ten moduł działa jako DBD, jak wyjaśniono powyżej i można go pobrać z witryny https://www.tmtm.org/en/mysql/ruby/

Pozyskiwanie i instalacja Ruby / DBI

Możesz pobrać i zainstalować moduł Ruby DBI z następującej lokalizacji -

https://imgur.com/NFEuWe4/embed

Przed rozpoczęciem instalacji upewnij się, że masz uprawnienia roota. Teraz wykonaj kroki podane poniżej -

Krok 1

$ tar zxf dbi-0.2.0.tar.gz

Krok 2

Przejdź do katalogu dystrybucyjnego dbi-0.2.0 i skonfiguruj go za pomocą skryptu setup.rb w tym katalogu. Najbardziej ogólne polecenie konfiguracyjne wygląda następująco, bez argumentów po argumencie config. To polecenie konfiguruje dystrybucję tak, aby domyślnie instalowała wszystkie sterowniki.

$ ruby setup.rb config

Aby być bardziej szczegółowym, podaj opcję --with, która wyświetla listę poszczególnych części dystrybucji, których chcesz użyć. Na przykład, aby skonfigurować tylko główny moduł DBI i sterownik poziomu MySQL DBD, wydaj następujące polecenie -

$ ruby setup.rb config --with = dbi,dbd_mysql

Krok 3

Ostatnim krokiem jest zbudowanie sterownika i zainstalowanie go za pomocą następujących poleceń -

$ ruby setup.rb setup
$ ruby setup.rb install

Połączenie z bazą danych

Zakładając, że będziemy pracować z bazą danych MySQL, przed połączeniem się z bazą danych upewnij się, że:

  • Utworzyłeś bazę danych TESTDB.

  • Utworzyłeś PRACOWNIKA w TESTDB.

  • Ta tabela zawiera pola FIRST_NAME, LAST_NAME, AGE, SEX i INCOME.

  • ID użytkownika „testuser” i hasło „test123” są ustawione na dostęp do bazy danych TESTDB.

  • Ruby Module DBI jest poprawnie zainstalowany na twoim komputerze.

  • Przeszedłeś przez samouczek MySQL, aby zrozumieć podstawy MySQL.

Poniżej znajduje się przykład połączenia z bazą danych MySQL „TESTDB”

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   # get server version string and display it
   row = dbh.select_one("SELECT VERSION()")
   puts "Server version: " + row[0]
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

Podczas uruchamiania tego skryptu na naszej maszynie z systemem Linux daje on następujący wynik.

Server version: 5.0.45

Jeśli zostanie nawiązane połączenie ze źródłem danych, zostanie zwrócony uchwyt bazy danych i zapisany w dbh do dalszego wykorzystania w inny sposób dbhjest ustawiona na wartość nil, a e.err i e :: errstr zwracają odpowiednio kod błędu i ciąg błędu.

Wreszcie, przed wydaniem, upewnij się, że połączenie z bazą danych jest zamknięte, a zasoby są zwolnione.

Operacja INSERT

Operacja INSERT jest wymagana, gdy chcesz utworzyć rekordy w tabeli bazy danych.

Po nawiązaniu połączenia z bazą danych jesteśmy gotowi do tworzenia tabel lub rekordów w tabelach bazy danych za pomocą do metoda lub prepare i execute metoda.

Korzystanie z instrukcji do

Instrukcje, które nie zwracają wierszy, można wydawać, wywołując metodę dometoda uchwytu bazy danych. Ta metoda przyjmuje argument będący ciągiem instrukcji i zwraca liczbę wierszy, na które ma wpływ instrukcja.

dbh.do("DROP TABLE IF EXISTS EMPLOYEE")
dbh.do("CREATE TABLE EMPLOYEE (
   FIRST_NAME  CHAR(20) NOT NULL,
   LAST_NAME  CHAR(20),
   AGE INT,  
   SEX CHAR(1),
   INCOME FLOAT )" );

Podobnie można wykonać instrukcję SQL INSERT , aby utworzyć rekord w tabeli EMPLOYEE.

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   dbh.do( "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME)
      VALUES ('Mac', 'Mohan', 20, 'M', 2000)" )
   puts "Record has been created"
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

Korzystanie z przygotowania i wykonania

Do wykonania instrukcji SQL za pośrednictwem kodu Ruby można użyć metod przygotowania i wykonania klasy DBI.

Tworzenie rekordu obejmuje następujące kroki -

  • Przygotowanie instrukcji SQL z instrukcją INSERT. Zostanie to zrobione za pomocąprepare metoda.

  • Wykonywanie zapytania SQL w celu wybrania wszystkich wyników z bazy danych. Zostanie to zrobione za pomocąexecute metoda.

  • Uchwyt instrukcji zwalniania. Zostanie to zrobione za pomocąfinish API

  • Jeśli wszystko pójdzie dobrze, to commit ta operacja inaczej możesz rollback całą transakcję.

Poniżej znajduje się składnia użycia tych dwóch metod -

sth = dbh.prepare(statement)
sth.execute
   ... zero or more SQL operations ...
sth.finish

Te dwie metody mogą być użyte do zaliczenia bindwartości do instrukcji SQL. Może się zdarzyć, że wartości do wprowadzenia nie zostaną podane z góry. W takim przypadku używane są wartości wiążące. Znak zapytania (?) jest używany zamiast rzeczywistych wartości, a następnie rzeczywiste wartości są przekazywane przez funkcję API execute ().

Poniżej znajduje się przykład tworzenia dwóch rekordów w tabeli PRACOWNIK -

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare( "INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME)
      VALUES (?, ?, ?, ?, ?)" )
   sth.execute('John', 'Poul', 25, 'M', 2300)
   sth.execute('Zara', 'Ali', 17, 'F', 1000)
   sth.finish
   dbh.commit
   puts "Record has been created"
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

Jeśli jednocześnie występuje wiele instrukcji INSERT, przygotowanie instrukcji najpierw, a następnie wielokrotne jej wykonanie w pętli jest bardziej wydajne niż wywoływanie za każdym razem w pętli.

Operacja READ

READ Operacja na dowolnej bazie danych oznacza pobranie przydatnych informacji z bazy danych.

Po nawiązaniu połączenia z bazą danych jesteśmy gotowi do wysłania zapytania do tej bazy danych. Możemy użyć albodo metoda lub prepare i execute metody pobierania wartości z tabeli bazy danych.

Pobieranie rekordów obejmuje następujące kroki -

  • Przygotowanie zapytania SQL na podstawie wymaganych warunków. Zostanie to zrobione za pomocąprepare metoda.

  • Wykonywanie zapytania SQL w celu wybrania wszystkich wyników z bazy danych. Zostanie to zrobione za pomocąexecute metoda.

  • Pobieranie wszystkich wyników jeden po drugim i drukowanie tych wyników. Zostanie to zrobione za pomocąfetch metoda.

  • Uchwyt instrukcji zwalniania. Zostanie to zrobione za pomocąfinish metoda.

Poniżej znajduje się procedura odpytywania wszystkich rekordów z tabeli PRACOWNIK z wynagrodzeniem powyżej 1000.

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare("SELECT * FROM EMPLOYEE WHERE INCOME > ?")
   sth.execute(1000)

   sth.fetch do |row|
   printf "First Name: %s, Last Name : %s\n", row[0], row[1]
   printf "Age: %d, Sex : %s\n", row[2], row[3]
   printf "Salary :%d \n\n", row[4]
end
   sth.finish
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

To da następujący wynik -

First Name: Mac, Last Name : Mohan
Age: 20, Sex : M
Salary :2000

First Name: John, Last Name : Poul
Age: 25, Sex : M
Salary :2300

Istnieje więcej skrótowych metod pobierania rekordów z bazy danych. Jeśli jesteś zainteresowany, przejdź przez Pobieranie wyników, w przeciwnym razie przejdź do następnej sekcji.

Operacja aktualizacji

UPDATE Operacja na dowolnej bazie danych oznacza aktualizację jednego lub więcej rekordów, które są już dostępne w bazie danych. Poniżej przedstawiono procedurę aktualizacji wszystkich rekordów, które mają PŁEĆ jako „M”. Tutaj zwiększymy WIEK wszystkich samców o jeden rok. To zajmie trzy kroki -

  • Przygotowanie zapytania SQL na podstawie wymaganych warunków. Zostanie to zrobione za pomocąprepare metoda.

  • Wykonywanie zapytania SQL w celu wybrania wszystkich wyników z bazy danych. Zostanie to zrobione za pomocąexecute metoda.

  • Uchwyt instrukcji zwalniania. Zostanie to zrobione za pomocąfinish metoda.

  • Jeśli wszystko pójdzie dobrze commit ta operacja inaczej możesz rollback całą transakcję.

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare("UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = ?")
   sth.execute('M')
   sth.finish
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

Operacja USUŃ

Operacja DELETE jest wymagana, gdy chcesz usunąć niektóre rekordy z bazy danych. Poniżej znajduje się procedura usuwania wszystkich zapisów od PRACOWNIKA, w którym WIEK jest większy niż 20. Ta operacja obejmuje następujące kroki.

  • Przygotowanie zapytania SQL na podstawie wymaganych warunków. Zostanie to zrobione za pomocąprepare metoda.

  • Wykonywanie zapytania SQL w celu usunięcia wymaganych rekordów z bazy danych. Zostanie to zrobione za pomocąexecute metoda.

  • Uchwyt instrukcji zwalniania. Zostanie to zrobione za pomocąfinish metoda.

  • Jeśli wszystko pójdzie dobrze commit ta operacja inaczej możesz rollback całą transakcję.

#!/usr/bin/ruby -w

require "dbi"

begin
   # connect to the MySQL server
   dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123")
   sth = dbh.prepare("DELETE FROM EMPLOYEE WHERE AGE > ?")
   sth.execute(20)
   sth.finish
   dbh.commit
rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

Wykonywanie transakcji

Transakcje to mechanizm zapewniający spójność danych. Transakcje powinny mieć następujące cztery właściwości -

  • Atomicity - Albo transakcja zostaje zakończona, albo nic się nie dzieje.

  • Consistency - Transakcja musi rozpocząć się w stanie zgodnym i opuścić system w stanie zgodnym.

  • Isolation - Pośrednie wyniki transakcji nie są widoczne poza bieżącą transakcją.

  • Durability - Po zatwierdzeniu transakcji efekty są trwałe, nawet po awarii systemu.

DBI udostępnia dwie metody zatwierdzania lub wycofywania transakcji. Jest jeszcze jedna metoda zwana transakcją, której można użyć do realizacji transakcji. Istnieją dwa proste podejścia do realizacji transakcji -

Podejście I

Pierwsze podejście wykorzystuje metody zatwierdzania i wycofywania DBI do jawnego zatwierdzania lub anulowania transakcji -

dbh['AutoCommit'] = false # Set auto commit to false.
begin
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'John'")
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'Zara'")
   dbh.commit
rescue
   puts "transaction failed"
   dbh.rollback
end
dbh['AutoCommit'] = true

Podejście II

Drugie podejście wykorzystuje metodę transakcyjną . Jest to prostsze, ponieważ wymaga bloku kodu zawierającego instrukcje składające się na transakcję. Metoda transakcji wykonuje blok, a następnie automatycznie wywołuje zatwierdzenie lub wycofanie , w zależności od tego, czy blok się powiedzie, czy nie -

dbh['AutoCommit'] = false # Set auto commit to false.
dbh.transaction do |dbh|
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'John'")
   dbh.do("UPDATE EMPLOYEE SET AGE = AGE+1 WHERE FIRST_NAME = 'Zara'")
end
dbh['AutoCommit'] = true

Operacja COMMIT

Commit to operacja, która daje zielony sygnał do bazy danych w celu sfinalizowania zmian, a po tej operacji nie można cofnąć żadnej zmiany.

Oto prosty przykład wywołania commit metoda.

dbh.commit

Operacja ROLLBACK

Jeśli nie jesteś zadowolony z co najmniej jednej zmiany i chcesz całkowicie cofnąć te zmiany, użyj rozszerzenia rollback metoda.

Oto prosty przykład wywołania rollback metoda.

dbh.rollback

Odłączanie bazy danych

Aby rozłączyć połączenie z bazą danych, użyj interfejsu API odłączania.

dbh.disconnect

Jeśli połączenie z bazą danych zostanie zamknięte przez użytkownika metodą rozłączenia, wszelkie oczekujące transakcje są wycofywane przez DBI. Jednak zamiast polegać na jakichkolwiek szczegółach implementacji DBI, lepiej byłoby, gdyby Twoja aplikacja wywoływała jawne zatwierdzanie lub wycofywanie zmian.

Obsługa błędów

Istnieje wiele źródeł błędów. Kilka przykładów to błąd składni w wykonywanej instrukcji SQL, błąd połączenia lub wywołanie metody pobierania dla już anulowanego lub zakończonego uchwytu instrukcji.

Jeśli metoda DBI zawiedzie, DBI zgłasza wyjątek. Metody DBI mogą wywoływać dowolny z kilku typów wyjątków, ale dwie najważniejsze klasy wyjątków to DBI :: InterfaceError i DBI :: DatabaseError .

Obiekty wyjątków tych klas mają trzy atrybuty o nazwach err , errstr i state , które reprezentują numer błędu, opisowy ciąg błędu i standardowy kod błędu. Atrybuty wyjaśniono poniżej -

  • err- Zwraca całkowitą reprezentację zaistniałego błędu lub zero, jeśli nie jest to obsługiwane przez DBD. Oracle DBD na przykład zwraca numeryczną część komunikatu o błędzie ORA-XXXX .

  • errstr - Zwraca ciąg znaków reprezentujący występujący błąd.

  • state- Zwraca kod SQLSTATE zaistniałego błędu. SQLSTATE jest łańcuchem o długości pięciu znaków. Większość DBD nie obsługuje tego i zamiast tego zwraca nil.

W większości przykładów widzieliście następujący kod -

rescue DBI::DatabaseError => e
   puts "An error occurred"
   puts "Error code:    #{e.err}"
   puts "Error message: #{e.errstr}"
   dbh.rollback
ensure
   # disconnect from server
   dbh.disconnect if dbh
end

Aby uzyskać informacje o debugowaniu dotyczące działania skryptu podczas jego wykonywania, można włączyć śledzenie. Aby to zrobić, musisz najpierw załadować moduł dbi / trace, a następnie wywołać metodę śledzenia , która kontroluje tryb śledzenia i miejsce docelowe danych wyjściowych -

require "dbi/trace"
..............

trace(mode, destination)

Wartość trybu może wynosić 0 (wyłączone), 1, 2 lub 3, a miejscem docelowym powinien być obiekt we / wy. Wartości domyślne to odpowiednio 2 i STDERR.

Bloki kodu z metodami

Istnieje kilka metod tworzenia uchwytów. Te metody można wywołać za pomocą bloku kodu. Zaletą używania bloku kodu wraz z metodami jest to, że dostarczają one uchwyt do bloku kodu jako jego parametr i automatycznie czyści uchwyt po zakończeniu bloku. Istnieje kilka przykładów, które pozwalają zrozumieć tę koncepcję.

  • DBI.connect- Ta metoda generuje uchwyt bazy danych i zaleca się wywołanie rozłączenia na końcu bloku w celu rozłączenia bazy danych.

  • dbh.prepare- Ta metoda generuje uchwyt instrukcji i zaleca się zakończenie na końcu bloku. W bloku należy wywołać metodę execute , aby wykonać instrukcję.

  • dbh.execute- Ta metoda jest podobna, z wyjątkiem tego, że nie musimy wywoływać wykonania w obrębie bloku. Uchwyt instrukcji jest wykonywany automatycznie.

Przykład 1

DBI.connect może pobrać blok kodu, przekazać do niego uchwyt bazy danych i automatycznie rozłączyć uchwyt na końcu bloku w następujący sposób.

dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") do |dbh|

Przykład 2

dbh.prepare może wziąć blok kodu, przekazuje do niego uchwyt instrukcji i automatycznie wywołuje zakończenie na końcu bloku w następujący sposób.

dbh.prepare("SHOW DATABASES") do |sth|
   sth.execute
   puts "Databases: " + sth.fetch_all.join(", ")
end

Przykład 3

dbh.execute może wziąć blok kodu, przekazuje do niego uchwyt instrukcji i automatycznie wywołuje zakończenie na końcu bloku w następujący sposób -

dbh.execute("SHOW DATABASES") do |sth|
   puts "Databases: " + sth.fetch_all.join(", ")
end

Metoda transakcji DBI przyjmuje również blok kodu, który został opisany powyżej.

Funkcje i atrybuty specyficzne dla kierowcy

DBI umożliwia sterownikom bazy danych udostępnianie dodatkowych funkcji specyficznych dla bazy danych, które mogą być wywoływane przez użytkownika za pomocą metody func dowolnego obiektu Handle.

Atrybuty specyficzne dla sterownika są obsługiwane i można je ustawić lub pobrać za pomocą []= lub [] metody.

Sr.No. Funkcje i opis
1

dbh.func(:createdb, db_name)

Tworzy nową bazę danych.

2

dbh.func(:dropdb, db_name)

Upuszcza bazę danych.

3

dbh.func(:reload)

Wykonuje operację przeładowania.

4

dbh.func(:shutdown)

Wyłącza serwer.

5

dbh.func(:insert_id) => Fixnum

Zwraca najnowszą wartość AUTO_INCREMENT dla połączenia.

6

dbh.func(:client_info) => String

Zwraca informacje o kliencie MySQL w postaci wersji.

7

dbh.func(:client_version) => Fixnum

Zwraca informacje o kliencie w postaci wersji. Jest podobny do: client_info, ale zwraca fixnum zamiast żądać.

8

dbh.func(:host_info) => String

Zwraca informacje o hoście.

9

dbh.func(:proto_info) => Fixnum

Zwraca protokół używany do komunikacji.

10

dbh.func(:server_info) => String

Zwraca informacje o serwerze MySQL w postaci wersji.

11

dbh.func(:stat) => String

Zwraca aktualny stan bazy danych.

12

dbh.func(:thread_id) => Fixnum

Zwraca bieżący identyfikator wątku.

Przykład

#!/usr/bin/ruby

require "dbi"
begin
   # connect to the MySQL server
   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

To da następujący wynik -

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