Ruby / DBI 튜토리얼

이 장에서는 Ruby를 사용하여 데이터베이스에 액세스하는 방법을 설명합니다. 루비 DBI의 모듈은 펄 DBI 모듈의 그것과 유사 루비 스크립트를 데이터베이스에 독립적 인 인터페이스를 제공합니다.

DBI는 Ruby 용 Database Independent Interface의 약자입니다. 즉, DBI는 Ruby 코드와 기본 데이터베이스 사이에 추상화 계층을 제공하므로 데이터베이스 구현을 정말 쉽게 전환 할 수 있습니다. 사용중인 실제 데이터베이스에 관계없이 일관된 데이터베이스 인터페이스를 제공하는 메서드, 변수 및 규칙 집합을 정의합니다.

DBI는 다음과 인터페이스 할 수 있습니다-

  • ADO (ActiveX 데이터 개체)
  • DB2
  • Frontbase
  • mSQL
  • MySQL
  • ODBC
  • Oracle
  • OCI8 (Oracle)
  • PostgreSQL
  • Proxy/Server
  • SQLite
  • SQLRelay

DBI 애플리케이션의 아키텍처

DBI는 백엔드에서 사용 가능한 모든 데이터베이스와 독립적입니다. Oracle, MySQL 또는 Informix 등으로 작업하든 상관없이 DBI를 사용할 수 있습니다. 이것은 다음 아키텍처 다이어그램에서 분명합니다.

Ruby DBI의 일반적인 아키텍처는 두 개의 레이어를 사용합니다.

  • 데이터베이스 인터페이스 (DBI) 계층. 이 계층은 데이터베이스에 독립적이며 통신하는 데이터베이스 서버 유형에 관계없이 동일한 방식으로 사용되는 공통 액세스 방법 세트를 제공합니다.

  • 데이터베이스 드라이버 (DBD) 계층. 이 계층은 데이터베이스에 따라 다릅니다. 다른 드라이버는 다른 데이터베이스 엔진에 대한 액세스를 제공합니다. MySQL 용 드라이버, PostgreSQL 용 드라이버, InterBase 용 드라이버, Oracle 용 드라이버 등이 있습니다. 각 드라이버는 DBI 계층의 요청을 해석하여 주어진 유형의 데이터베이스 서버에 적합한 요청에 매핑합니다.

전제 조건

MySQL 데이터베이스에 액세스하기 위해 Ruby 스크립트를 작성하려면 Ruby MySQL 모듈이 설치되어 있어야합니다.

이 모듈은 위에서 설명한대로 DBD 역할을하며 다음에서 다운로드 할 수 있습니다. https://www.tmtm.org/en/mysql/ruby/

Ruby / DBI 구하기 및 설치

다음 위치에서 Ruby DBI 모듈을 다운로드하여 설치할 수 있습니다.

https://imgur.com/NFEuWe4/embed

이 설치를 시작하기 전에 루트 권한이 있는지 확인하십시오. 이제 아래 단계를 따르십시오-

1 단계

$ tar zxf dbi-0.2.0.tar.gz

2 단계

배포 디렉토리 dbi-0.2.0으로 이동하고 해당 디렉토리 의 setup.rb 스크립트를 사용하여 구성하십시오 . 가장 일반적인 구성 명령은 다음과 같으며 config 인수 뒤에 인수가 없습니다. 이 명령은 기본적으로 모든 드라이버를 설치하도록 배포를 구성합니다.

$ ruby setup.rb config

보다 구체적으로 사용하려는 배포판의 특정 부분을 나열하는 --with 옵션을 제공하십시오. 예를 들어, 기본 DBI 모듈과 MySQL DBD 수준 드라이버 만 구성하려면 다음 명령을 실행하십시오.

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

3 단계

마지막 단계는 드라이버를 빌드하고 다음 명령을 사용하여 설치하는 것입니다.

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

데이터베이스 연결

MySQL 데이터베이스로 작업한다고 가정하고 데이터베이스에 연결하기 전에 다음을 확인하십시오.

  • TESTDB 데이터베이스를 만들었습니다.

  • TESTDB에서 EMPLOYEE를 만들었습니다.

  • 이 테이블에는 FIRST_NAME, LAST_NAME, AGE, SEX 및 INCOME 필드가 있습니다.

  • 사용자 ID "testuser"및 비밀번호 "test123"은 TESTDB에 액세스하도록 설정됩니다.

  • Ruby Module DBI가 컴퓨터에 올바르게 설치되었습니다.

  • MySQL 기본 사항을 이해하기 위해 MySQL 자습서를 살펴 보았습니다.

다음은 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

이 스크립트를 실행하는 동안 Linux 시스템에서 다음과 같은 결과가 생성됩니다.

Server version: 5.0.45

데이터 소스와 연결이 설정되면 데이터베이스 핸들이 반환되어 dbh 추가 사용을 위해 dbhnil 값으로 설정되고 e.erre :: errstr 은 각각 오류 코드와 오류 문자열을 반환합니다.

마지막으로, 나오기 전에 데이터베이스 연결이 닫히고 리소스가 해제되었는지 확인하십시오.

INSERT 작업

데이터베이스 테이블에 레코드를 만들려면 INSERT 작업이 필요합니다.

데이터베이스 연결이 설정되면 다음을 사용하여 데이터베이스 테이블에 테이블 또는 레코드를 만들 준비가 된 것입니다. do 방법 또는 prepareexecute 방법.

do 문 사용

행을 리턴하지 않는 명령문은 다음을 호출하여 발행 할 수 있습니다. do데이터베이스 핸들 방법. 이 메소드는 명령문 문자열 인수를 사용하고 명령문의 영향을받는 행 수를 리턴합니다.

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 )" );

마찬가지로 SQL INSERT 문을 실행 하여 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

준비 및 실행 사용

DBI 클래스의 준비실행 메소드를 사용 하여 Ruby 코드를 통해 SQL 문을 실행할 수 있습니다.

레코드 생성은 다음 단계를 따릅니다.

  • INSERT 문으로 SQL 문을 준비합니다. 이것은prepare 방법.

  • SQL 쿼리를 실행하여 데이터베이스에서 모든 결과를 선택합니다. 이것은execute 방법.

  • 릴리스 문 핸들입니다. 이것은 사용하여 수행됩니다finish API

  • 모든 것이 잘되면 commit 그렇지 않으면이 작업을 수행 할 수 있습니다. rollback 완전한 거래.

다음은이 두 가지 방법을 사용하는 구문입니다.

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

이 두 가지 방법을 사용하여 bindSQL 문에 대한 값. 입력 할 값을 미리 제공하지 않는 경우가 있습니다. 이러한 경우 바인딩 값이 사용됩니다. 물음표 (?)는 실제 값 대신 사용되며 실제 값은 execute () API를 통해 전달됩니다.

다음은 EMPLOYEE 테이블에 두 개의 레코드를 만드는 예입니다.

#!/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

한 번에 여러 INSERT가있는 경우 먼저 문을 준비한 다음 루프 내에서 여러 번 실행하는 것이 루프를 통해 매번 do를 호출하는 것보다 효율적입니다.

읽기 작업

모든 데이터베이스에 대한 읽기 작업은 데이터베이스에서 유용한 정보를 가져 오는 것을 의미합니다.

데이터베이스 연결이 설정되면이 데이터베이스에 쿼리 할 준비가 된 것입니다. 우리는 둘 중 하나를 사용할 수 있습니다do 방법 또는 prepareexecute 데이터베이스 테이블에서 값을 가져 오는 메소드.

레코드 가져 오기는 다음 단계를 따릅니다.

  • 필수 조건에 따라 SQL 쿼리를 준비합니다. 이것은prepare 방법.

  • SQL 쿼리를 실행하여 데이터베이스에서 모든 결과를 선택합니다. 이것은execute 방법.

  • 모든 결과를 하나씩 가져와 그 결과를 인쇄합니다. 이것은fetch 방법.

  • 릴리스 문 핸들입니다. 이것은finish 방법.

다음은 급여가 1000 이상인 EMPLOYEE 테이블의 모든 레코드를 쿼리하는 절차입니다.

#!/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

이것은 다음 결과를 생성합니다-

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

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

데이터베이스에서 레코드를 가져 오는 더 많은 바로 가기 방법이 있습니다. 관심이있는 경우 결과 가져 오기를 진행하고 그렇지 않으면 다음 섹션으로 진행하십시오.

업데이트 작업

모든 데이터베이스에 대한 UPDATE 작업은 데이터베이스에서 이미 사용 가능한 하나 이상의 레코드를 업데이트하는 것을 의미합니다. 다음은 SEX가 'M'인 모든 레코드를 업데이트하는 절차입니다. 여기서 우리는 모든 남자의 나이를 1 년 늘릴 것입니다. 세 단계가 필요합니다.

  • 필수 조건에 따라 SQL 쿼리를 준비합니다. 이것은prepare 방법.

  • SQL 쿼리를 실행하여 데이터베이스에서 모든 결과를 선택합니다. 이것은execute 방법.

  • 릴리스 문 핸들입니다. 이것은finish 방법.

  • 모든 것이 잘되면 commit 그렇지 않으면이 작업을 수행 할 수 있습니다. rollback 완전한 거래.

#!/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

작업 삭제

데이터베이스에서 일부 레코드를 삭제하려면 DELETE 작업이 필요합니다. 다음은 AGE가 20 이상인 EMPLOYEE에서 모든 레코드를 삭제하는 절차입니다.이 작업은 다음 단계를 수행합니다.

  • 필수 조건에 따라 SQL 쿼리를 준비합니다. 이것은prepare 방법.

  • 데이터베이스에서 필요한 레코드를 삭제하기 위해 SQL 쿼리를 실행합니다. 이것은execute 방법.

  • 릴리스 문 핸들입니다. 이것은finish 방법.

  • 모든 것이 잘되면 commit 그렇지 않으면이 작업을 수행 할 수 있습니다. rollback 완전한 거래.

#!/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

거래 수행

트랜잭션은 데이터 일관성을 보장하는 메커니즘입니다. 거래는 다음 네 가지 속성을 가져야합니다-

  • Atomicity − 거래가 완료되거나 아무 일도 일어나지 않습니다.

  • Consistency − 트랜잭션은 일관된 상태에서 시작해야하며 시스템은 일관된 상태를 유지해야합니다.

  • Isolation − 거래의 중간 결과는 현재 거래 외부에서 볼 수 없습니다.

  • Durability − 일단 트랜잭션이 커밋되면 시스템 장애 후에도 효과가 지속됩니다.

DBI는 트랜잭션을 커밋 하거나 롤백 하는 두 가지 방법을 제공 합니다. 트랜잭션 을 구현하는 데 사용할 수있는 트랜잭션 이라는 메서드가 하나 더 있습니다. 트랜잭션을 구현하는 두 가지 간단한 접근 방식이 있습니다.

접근 I

첫 번째 접근 방식은 DBI의 커밋롤백 방법을 사용하여 트랜잭션을 명시 적으로 커밋하거나 취소합니다.

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

접근 II

두 번째 접근 방식은 트랜잭션 방법을 사용합니다 . 트랜잭션을 구성하는 문이 포함 된 코드 블록을 사용하기 때문에 더 간단합니다. 거래 방법은 원용이 블록을 실행 커밋 또는 롤백 블록이 성공 또는 실패 여부에 따라 자동으로 -

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

COMMIT 작업

커밋은 변경 사항을 완료하기 위해 데이터베이스에 녹색 신호를 제공하는 작업이며,이 작업 후에는 변경 사항을 되돌릴 수 없습니다.

다음은 호출하는 간단한 예입니다. commit 방법.

dbh.commit

ROLLBACK 작업

하나 이상의 변경 사항에 만족하지 않고 해당 변경 사항을 완전히 되돌리려면 다음을 사용하십시오. rollback 방법.

다음은 호출하는 간단한 예입니다. rollback 방법.

dbh.rollback

데이터베이스 연결 해제

데이터베이스 연결을 끊으려면 disconnect API를 사용하십시오.

dbh.disconnect

연결 끊기 방법을 사용하여 사용자가 데이터베이스에 대한 연결을 닫으면 처리중인 트랜잭션이 DBI에 의해 롤백됩니다. 그러나 DBI의 구현 세부 사항에 의존하는 대신 응용 프로그램이 커밋 또는 롤백을 명시 적으로 호출하는 것이 좋습니다.

오류 처리

오류의 원인은 다양합니다. 몇 가지 예는 실행 된 SQL 문의 구문 오류, 연결 실패 또는 이미 취소되었거나 완료된 명령문 핸들에 대한 fetch 메소드 호출입니다.

DBI 메서드가 실패하면 DBI는 예외를 발생시킵니다. DBI 메서드는 여러 유형의 예외를 발생시킬 수 있지만 가장 중요한 두 가지 예외 클래스는 DBI :: InterfaceErrorDBI :: DatabaseError 입니다.

이러한 클래스의 예외 객체 에는 오류 번호, 설명 오류 문자열 및 표준 오류 코드를 나타내는 err , errstrstate 라는 세 가지 속성이 있습니다 . 속성은 아래에 설명되어 있습니다.

  • err− 발생한 오류의 정수 표현을 반환하거나 DBD에서 지원하지 않는 경우 nil을 반환합니다. 예를 들어 Oracle DBD는 ORA-XXXX 오류 메시지 의 숫자 부분을 반환합니다 .

  • errstr − 발생한 오류의 문자열 표현을 반환합니다.

  • state− 발생한 오류의 SQLSTATE 코드를 반환합니다. SQLSTATE는 5 자 길이의 문자열입니다. 대부분의 DBD는이를 지원하지 않고 대신 nil을 반환합니다.

대부분의 예제에서 위의 다음 코드를 보았습니다.

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

스크립트가 실행될 때 수행하는 작업에 대한 디버깅 정보를 얻으려면 추적을 활성화 할 수 있습니다. 이 작업을 수행하려면 먼저 DBI / 추적 모듈을로드 한 후 호출해야합니다 추적 방법을 그 제어 추적 모드와 출력 대상 -

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

trace(mode, destination)

모드 값은 0 (꺼짐), 1, 2 또는 3 일 수 있으며 대상은 IO 개체 여야합니다. 기본값은 각각 2 및 STDERR입니다.

메서드가있는 코드 블록

핸들을 만드는 몇 가지 방법이 있습니다. 이러한 메서드는 코드 블록으로 호출 할 수 있습니다. 메서드와 함께 코드 블록을 사용할 때의 장점은 코드 블록에 대한 핸들을 매개 변수로 제공하고 블록이 종료 될 때 핸들을 자동으로 정리한다는 것입니다. 개념을 이해하기위한 몇 가지 예가 있습니다.

  • DBI.connect−이 방법은 데이터베이스 핸들을 생성하며 블록 끝에서 disconnect 를 호출 하여 데이터베이스 연결을 해제하는 것이 좋습니다 .

  • dbh.prepare−이 방법은 문 핸들을 생성하며 블록 끝에서 완료 하는 것이 좋습니다 . 블록 내에서 명령문을 실행하려면 execute 메소드를 호출해야합니다 .

  • dbh.execute−이 방법은 블록 내에서 실행을 호출 할 필요가 없다는 점을 제외하면 유사합니다. 명령문 핸들이 자동으로 실행됩니다.

예 1

DBI.connect 다음과 같이 코드 블록을 가져 와서 데이터베이스 핸들을 전달하고 블록 끝에서 자동으로 핸들 연결을 끊을 수 있습니다.

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

예 2

dbh.prepare 다음과 같이 코드 블록을 가져 와서 문 핸들을 전달하고 블록 끝에서 자동으로 finish를 호출 할 수 있습니다.

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

예제 3

dbh.execute 코드 블록을 가져 와서 명령문 핸들을 전달하고 다음과 같이 블록 끝에서 자동으로 finish를 호출 할 수 있습니다.

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

DBI 트랜잭션 방법도 위에서 설명한 코드 블록을 사용합니다.

드라이버 별 기능 및 속성

DBI를 사용하면 데이터베이스 드라이버가 추가 데이터베이스 특정 함수를 제공 할 수 있습니다.이 함수 는 모든 Handle 개체 의 func 메서드를 통해 사용자가 호출 할 수 있습니다 .

드라이버 별 속성이 지원되며 다음을 사용하여 설정하거나 가져올 수 있습니다. []= 또는 [] 행동 양식.

Sr. 아니. 기능 및 설명
1

dbh.func(:createdb, db_name)

새 데이터베이스를 만듭니다.

2

dbh.func(:dropdb, db_name)

데이터베이스를 삭제합니다.

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와 비슷하지만 sting 대신 fixnum을 반환합니다.

8

dbh.func(:host_info) => String

호스트 정보를 반환합니다.

9

dbh.func(:proto_info) => Fixnum

통신에 사용중인 프로토콜을 반환합니다.

10

dbh.func(:server_info) => String

버전 측면에서 MySQL 서버 정보를 반환합니다.

11

dbh.func(:stat) => String

데이터베이스의 현재 상태를 반환합니다.

12

dbh.func(:thread_id) => Fixnum

현재 스레드 ID를 반환합니다.

#!/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

이것은 다음 결과를 생성합니다-

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