English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في هذا الفصل سنشرح لك كيفية الوصول إلى قاعدة البيانات باستخدام Ruby.Ruby DBI تقدم الوحدة البرمجية واجهة مستقلة للقاعدة البيانات لسكريبتات Ruby بنمط وحدة Perl DBI.
DBI تعني واجهة مستقلة للقاعدة البيانات، وتعبر عن استقلالية Ruby عن قاعدة البيانات. توفر DBI طبقة تعريفي بين رمز Ruby وقاعدة البيانات الأساسية، مما يسمح بتبديل قاعدة البيانات بسهولة. يحدد DBI مجموعة من الطرق والمتغيرات والمعايير، مما يقدم واجهة قاعدة البيانات الموحدة المستقلة عن قاعدة البيانات.
يمكن أن يتفاعل DBI مع ما يلي:
ADO (ActiveX Data Objects)
DB2
Frontbase
mSQL
MySQL
ODBC
Oracle
OCI8 (Oracle)
PostgreSQL
Proxy/Server
SQLite
SQLRelay
DBI مستقلة عن أي قاعدة بيانات متاحة في الخلفية. مهما كان النوع الذي تستخدمه، سواء كان Oracle، MySQL، Informix، يمكنك استخدام DBI. يوضح الشكل التالي هذا النقطة بوضوح.
يستخدم Ruby DBI عادةً طبقتين:
طبقة واجهة قاعدة البيانات (DBI). هذه الطبقة مستقلة عن قاعدة البيانات وتقدم مجموعة من الطرق العامة للوصول، ويكون استخدام هذه الطرق مستقلاً عن نوع خادم قاعدة البيانات.
طبقة محرك قاعدة البيانات (DBD). هذه الطبقة تعتمد على قاعدة البيانات، وتقدم مختلف المحركات الداعمة للوصول إلى محركات قواعد البيانات المختلفة.MySQL، PostgreSQL، InterBase، Oracle وما إلى ذلك يستخدمون محركات مختلفة. تقوم كل محرك بتفسير الطلبات القادمة من طبقة DBI وتحويلها إلى طلبات تناسب خادم قاعدة البيانات من النوع المحدد.
إذا كنت ترغب في كتابة سكربتات Ruby لتحصل على بيانات قاعدة بيانات MySQL، يجب عليك أولاً تثبيت مكتبة Ruby MySQL.
# Ubuntu sudo apt-get install mysql-client sudo apt-get install libmysqlclient15-dev # CentOS yum install mysql-devel
يحتاج نظام Mac OS إلى تعديل ملف ~/.bash_profile أو ~/.profile، وإضافة الكود التالي:
MYSQL=/usr/local/mysql/bin export PATH=$PATH:$MYSQL export DYLD_LIBRARY_PATH=/usr/local/mysql/lib:$DYLD_LIBRARY_PATH
أو استخدم رابطًا بسيطًا:
sudo ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib/libmysqlclient.18.dylib
تم إنشاء RubyGems حوالي نوفمبر 2003، وأصبح جزءًا من مكتبة Ruby القياسية منذ إصدار Ruby 1.9. لمزيد من التفاصيل، راجع:RubyGems في Ruby
تثبيت dbi و dbd-mysql باستخدام gem:
sudo gem install dbi sudo gem install mysql sudo gem install dbd-mysql
هذه المكتبة هي DBD، يمكن الحصول عليها من http://tmtm.org/downloads/mysql/ruby/ تحميل
تنزيل أحدث حزمة، قم بإخراجها إلى الدليل، ثم قم بتنفيذ الأوامر التالية لتثبيتها:
ruby extconf.rb أو ruby extconf.rb --with-mysql-dir=/usr/local/mysql أو ruby extconf.rb --with-mysql-config
ثم قم بترميزها:
توليد
الحصول وتثبيت Ruby/DBI
يمكنك تنزيل وتثبيت مكتبة Ruby DBI من الرابط التالي:
https://github.com/erikh/ruby-dbi
قبل البدء في التثبيت، تأكد من أن لديك صلاحيات root. الآن، قم بتثبيت الخطوات التالية للتنصيب:
الخطوة 1
git clone https://github.com/erikh/ruby-dbi.git
أو قم بتنزيل zip package وأفصله.
الخطوة 2
دخل الدليل ruby-dbi-master، في الدليل باستخدام setup.rb النص يقوم بالتكوين. أمر التكوين الأكثر شيوعًا هو استخدام param config بدون أي معلمات. يكوّن هذا الأمر افتراضيًا جميع المحركات.
ruby setup.rb config
بصورة أكثر تفصيلاً، يمكنك استخدام خيار --with لتحديد الأجزاء المحددة التي تريد استخدامها. على سبيل المثال، إذا كنت تريد فقط تكوين مكتبة DBI الرئيسية وطبقة محرك DBD MySQL، اكتب الأمر التالي:
ruby setup.rb config --with=dbi,dbd_mysql
الخطوة 3
الخطوة الأخيرة هي إنشاء محرك، استخدم الأمر التالي للتنصيب:
ruby setup.rb setup ruby setup.rb install
افترض أننا نستخدم قاعدة بيانات MySQL، تأكد من التالي قبل الاتصال بالقاعدة البيانات:
لقد أنشأت قاعدة بيانات TESTDB.
لقد أنشأت جدول EMPLOYEE في TESTDB.
يحتوي هذا الجدول على الحقول FIRST_NAME،LAST_NAME،AGE،SEX و INCOME.
تم تعيين معرف المستخدم "testuser" وكلمة المرور "test123" لزيارة TESTDB
تم تثبيت مكتبة Ruby DBI بشكل صحيح على جهازك.
لقد شاهدت تعليمات MySQL وفهمت العمليات الأساسية.
إليك مثال على الاتصال بقاعدة بيانات MySQL "TESTDB":
#!/usr/bin/ruby -w require "dbi" begin # 连接到 MySQL 服务器 dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") # الحصول على نص إصدار الخادم وعرضه row = dbh.select_one("SELECT VERSION()") puts "إصدار الخادم: " + row[0] rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
عند تشغيل هذا النص، سيتم إنتاج النتائج التالية على جهاز Linux.
إصدار الخادم: 5.0.45
إذا كان هناك مصدر بيانات مع الاتصال، فإنه يرجع ملف تعريف قاعدة البيانات (Database Handle) ويتم حفظه في dbh بغرض الاستخدام اللاحق، وإلا dbh سيتم تعيينه إلى قيمة nil،e.err و e::errstr يُرجع رمز الخطأ والنصوص الخاصة بالخطأ.
最后,在退出这段程序之前,请确保关闭数据库连接,释放资源。
当您想要在数据库表中创建记录时,需要用到 INSERT 操作。
一旦建立了数据库连接,我们就可以准备使用 do طريقة أو prepare و execute 方法创建表或创建插入数据表中的记录。
不返回行的语句可通过调用 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 # 连接到 MySQL 服务器 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 "تم إنشاء السجل" COMMIT هو عملية تعرف أن قاعدة البيانات قد تم إكمال التغييرات، حيث لا يمكن استعادة جميع التغييرات بعد هذه العملية. rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" dbh.rollback تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
您可以使用 DBI 的 prepare و execute 方法来执行 Ruby 代码中的 SQL 语句。
创建记录的步骤如下:
准备带有 INSERT 语句的 SQL 语句。这将通过使用 prepare 方法来完成。
لإجراء استعلام SQL، اختر جميع النتائج من قاعدة البيانات. سيتم هذا من خلال استخدام execute 方法来完成。
释放语句句柄。这将通过使用 finish API 来完成。
如果一切进展顺利,则 COMMIT العملية 该操作,否则您可以 إليك مثال على طريقة استدعاء 完成交易。
下面是使用这两种方法的语法:
sth = dbh.prepare(statement) sth.execute ... أو أكثر عمليات SQL ... sth.finish
这两种方法可用于传 bind 值给 SQL 语句。有时候被输入的值可能未事先给出,在这种情况下,则会用到绑定值。使用问号(?)代替实际值,实际值通过 execute() API 来传递。
下面的示例在 EMPLOYEE 表中创建了两个记录:
#!/usr/bin/ruby -w require "dbi" begin # 连接到 MySQL 服务器 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 COMMIT هو عملية تعرف أن قاعدة البيانات قد تم إكمال التغييرات، حيث لا يمكن استعادة جميع التغييرات بعد هذه العملية. puts "تم إنشاء السجل" rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" dbh.rollback تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
إذا تم استخدام العديد من INSERT في وقت واحد، فإن إعداد جملة واحدة وتنفيذها عدة مرات في دورة متكررة يبدو أكثر فعالية من تنفيذ do في كل دورة.
عملية READ لأي قاعدة بيانات تشير إلى الحصول على معلومات مفيدة من قاعدة البيانات.
بمجرد إنشاء اتصال بقاعدة البيانات، يمكننا إعداد استعلام قاعدة البيانات. يمكننا استخدام do طريقة أو prepare و execute طريقة للحصول على القيم من جدول قاعدة البيانات.
خطوات الحصول على السجلات كالتالي:
基于所需的条件准备 SQL 查询。这将通过使用 prepare 方法来完成。
لإجراء استعلام SQL، اختر جميع النتائج من قاعدة البيانات. سيتم هذا من خلال استخدام execute 方法来完成。
الحصول على النتائج بشكل فردي، وأخرج هذه النتائج. سيتم هذا من خلال استخدام fetch 方法来完成。
释放语句句柄。这将通过使用 finish 方法来完成。
في المثال التالي، يتم استعلام جميع السجلات التي تحتوي على工资 (salary) أكثر من 1000 من جدول EMPLOYEE.
#!/usr/bin/ruby -w require "dbi" begin # 连接到 MySQL 服务器 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] fin sth.finish rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
سيكون هناك النتيجة التالية:
First Name: Mac, Last Name: Mohan Age: 20, Sex: M Salary:2000 First Name: John, Last Name: Poul Age: 25, Sex: M Salary:2300
تحديث سجلات قاعدة البيانات يشير إلى تحديث سجلات واحدة أو أكثر في قاعدة البيانات. في المثال التالي، يتم تحديث جميع السجلات التي تحتوي على SEX 'M'. هنا، سنزيد سن جميع الرجال بسنوات واحدة. سيتم هذا في ثلاث خطوات:
基于所需的条件准备 SQL 查询。这将通过使用 prepare 方法来完成。
لإجراء استعلام SQL، اختر جميع النتائج من قاعدة البيانات. سيتم هذا من خلال استخدام execute 方法来完成。
释放语句句柄。这将通过使用 finish 方法来完成。
如果一切进展顺利,则 COMMIT العملية 该操作,否则您可以 إليك مثال على طريقة استدعاء 完成交易。
#!/usr/bin/ruby -w require "dbi" begin # 连接到 MySQL 服务器 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 COMMIT هو عملية تعرف أن قاعدة البيانات قد تم إكمال التغييرات، حيث لا يمكن استعادة جميع التغييرات بعد هذه العملية. rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" dbh.rollback تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
عندما تريد حذف سجلات من قاعدة البيانات، تحتاج إلى استخدام عملية DELETE. في المثال التالي، يتم حذف جميع السجلات من EMPLOYEE التي تحتوي على AGE أكثر من 20. خطوات هذه العملية كالتالي:
基于所需的条件准备 SQL 查询。这将通过使用 prepare 方法来完成。
执行 SQL 查询,从数据库中删除所需的记录。这将通过使用 execute 方法来完成。
释放语句句柄。这将通过使用 finish 方法来完成。
如果一切进展顺利,则 COMMIT العملية 该操作,否则您可以 إليك مثال على طريقة استدعاء 完成交易。
#!/usr/bin/ruby -w require "dbi" begin # 连接到 MySQL 服务器 dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") sth = dbh.prepare("DELETE FROM EMPLOYEE WHERE AGE > ?") sth.execute(20) sth.finish COMMIT هو عملية تعرف أن قاعدة البيانات قد تم إكمال التغييرات، حيث لا يمكن استعادة جميع التغييرات بعد هذه العملية. rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" dbh.rollback تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
事务是一种确保交易一致性的机制。事务应具有下列四种属性:
原子性(Atomicity):事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行。
一致性(Consistency):事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。
隔离性(Isolation):事务的隔离性指并发的事务是相互隔离的,即一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。
持久性(Durability):事务的持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。即一旦一个事务提交,它对数据库中数据的改变应该是永久性的,耐得住任何数据库系统故障。持久性通过数据库备份和恢复来保证。
DBI 提供了两种执行事务的方法。一种是 COMMIT العملية 或 إليك مثال على طريقة استدعاء 方法,用于提交或回滚事务。还有一种是 transaction 方法,可用于实现事务。接下来我们来介绍这两种简单的实现事务的方法:
第一种方法使用 DBI 的 COMMIT العملية و إليك مثال على طريقة استدعاء 方法来显式地提交或取消事务:
dbh['AutoCommit'] = false # 设置自动提交为 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'") COMMIT هو عملية تعرف أن قاعدة البيانات قد تم إكمال التغييرات، حيث لا يمكن استعادة جميع التغييرات بعد هذه العملية. rescue puts "transaction failed" dbh.rollback fin dbh.do("UPDATE EMPLOYEE SET AGE = AGE + 1")
第二种方法使用 transaction 方法。这个方法相对简单些,因为它需要一个包含构成事务语句的代码块。transaction 方法执行块,然后根据块是否执行成功,自动调用 COMMIT العملية 或 إليك مثال على طريقة استدعاء:
dbh['AutoCommit'] = false # 设置自动提交为 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'") fin dbh.do("UPDATE EMPLOYEE SET AGE = AGE + 1")
dbh['AutoCommit'] = true
إذا لم تكون راضياً عن بعض أو كل التغييرات، وتود استعادة هذه التغييرات بالكامل، استخدم COMMIT العملية rollback
COMMIT هو عملية تعرف أن قاعدة البيانات قد تم إكمال التغييرات، حيث لا يمكن استعادة جميع التغييرات بعد هذه العملية.
dbh.commit إليك مثال على طريقة استدعاء عملية ROLLBACK
إذا لم تكون راضياً عن بعض أو كل التغييرات، وتود استعادة هذه التغييرات بالكامل، استخدم إليك مثال على طريقة استدعاء rollback
dbh.rollback
إلغاء الاتصال بالقاعدة
لإلغاء اتصال قاعدة البيانات، استخدم واجهة disconnect.
dbh.disconnect
معالجة الأخطاء
هناك العديد من مصادر الأخطاء المختلفة. مثل أخطاء النصوص عند تنفيذ جملة SQL، أو فشل الاتصال، أو استدعاء طريقة fetch على محول جملة تم إلغاءه أو إكماله. DBI::InterfaceError و DBI::DatabaseError.
لديها هذه الفئات من الاستثناءات خطأ،رسالة الخطأ و الحالة ثلاث خصائص، تمثلها الرقم المميز للخطأ، سلسلة وصفية للخطأ، ورمز الخطأ المعياري. وصف الخصائص كما يلي:
خطأ:استرداد تمثيل عددية للخطأ الذي حدث، إذا لم يدعم DBD ذلك، سيتم استرداد nil. على سبيل المثال، يعيد Oracle DBD ORA-XXXX جزء الرقمي من رسالة الخطأ.
رسالة الخطأ:استرداد تمثيل السلسلة للخطأ الذي حدث.
الحالة:استرداد رمز SQLSTATE للخطأ الذي حدث. SQLSTATE هو سلسلة من خمس أحرف. لا يدعم معظم DBD ذلك، لذا سيتم استرداد nil.
في المثال السابق الذي شاهدته بالفعل، تحتوي الكود التالي:
rescue DBI::DatabaseError => e puts "حدث خطأ" puts "كود الخطأ: #{e.err}" puts "رسالة الخطأ: #{e.errstr}" dbh.rollback تأكد # قطع الاتصال بالخادم dbh.disconnect إذا كان dbh fin
للحصول على معلومات التتبع المتعلقة بمحتوى تنفيذ السكربت أثناء التنفيذ، يمكنك تمكين التتبع. لتحقيق ذلك، يجب عليك أولاً تنزيل وحدة dbi/trace، ثم طلب إعداد نمط التتبع ومصدر الوجهة trace 方法:
require "dbi/trace" .............. trace(mode, destination)
mode的值可以是0(off)、1、2或3,destination的值应该是一个IO对象。默认值分别是2和STDERR。
有一些创建句柄的方法。这些方法通过代码块调用。使用带有方法的代码块的优点是,它们为代码块提供了句柄作为参数,当块终止时会自动清除句柄。下面是一些示例,有助于理解这个概念。
DBI.connect :该方法生成一个数据库句柄,建议在块的末尾调用 disconnect 来断开数据库。
dbh.prepare :该方法生成一个语句句柄,建议在块的末尾调用 finish。在块内,您必须调用 execute 方法来执行语句。
dbh.execute :该方法与dbh.prepare类似,但是dbh.execute不需要在块内调用execute方法。语句句柄会自动执行。
DBI.connect 可带有一个代码块,向它传递数据库句柄,且会在块的末尾自动断开句柄。
dbh = DBI.connect("DBI:Mysql:TESTDB:localhost", "testuser", "test123") do |dbh|
dbh.prepare 可带有一个代码块,向它传递语句句柄,且会在块的末尾自动调用finish。
dbh.prepare("SHOW DATABASES") do |sth| sth.execute puts "Databases: " + sth.fetch_all.join(", ") fin
dbh.execute 可带有一个代码块,向它传递语句句柄,且会在块的末尾自动调用finish。
dbh.execute("SHOW DATABASES") do |sth| puts "Databases: " + sth.fetch_all.join(", ") fin
DBI transaction 方法也可带有一个代码块,这在上面的章节中已经讲解过了。
DBI让数据库驱动程序提供了额外的特定数据库的函数,这些函数可通过任何Handle对象的 func 方法进行调用。
使用 []= 或 [] 方法可以设置或获取特定驱动程序的属性。
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 يعود بمعرف السطر الحالي. |
#!/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}" تأكد dbh.disconnect إذا كان dbh fin
سيكون هناك النتيجة التالية:
5.0.45 50045 Localhost عبر وحدة الاتصال UNIX 10 5.0.45 150621 وقت التشغيل: 384981 السلاسل: 1 الاستعلامات: 1101078 الاستعلامات البطيئة: 4 \ فتح: 324 تحديث جداول: 1 فتح جداول: 64 \ عدد الاستعلامات لكل ثانية متوسط: 2.860