国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Perl > 正文

Perl--DBI模塊入門(一)

2019-11-06 08:22:15
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

無(wú)論是寫(xiě)腳本還是做CGI,如何使用Perl來(lái)訪問(wèn)數(shù)據(jù)庫(kù)就是很有用的一個(gè)知識(shí)。

各種語(yǔ)言和開(kāi)發(fā)環(huán)境訪問(wèn)數(shù)據(jù)庫(kù)有各種不同的方式,比如可以用C和數(shù)據(jù)庫(kù)提供的API接口來(lái)進(jìn)行訪問(wèn),也可以用JDBC、ODBC、ADO等封裝好的統(tǒng)一接口來(lái)進(jìn)行訪問(wèn)。Perl訪問(wèn)數(shù)據(jù)庫(kù)最常用的包是DBI,可以在www.cpan.org找到。另外還需要安裝對(duì)應(yīng)數(shù)據(jù)庫(kù)的驅(qū)動(dòng)包,例如DBD::MySQL、DBD::Oracle、DBD::Sybase或者DBD::ODBC等。具體的安裝方法請(qǐng)參考上期文章,在此就不贅述了。

下文以常見(jiàn)的MySQL為例,說(shuō)說(shuō)如何實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作。

1 基本流程

習(xí)慣在Windows下開(kāi)發(fā)數(shù)據(jù)庫(kù)、熟悉ADO、ADO.NET的朋友,一定對(duì)ADOConnection/ADODataSet/ADOTable等類耳熟能詳。DBI的接口與之類似,但在操作方法上又有不同,對(duì)ADO熟悉的朋友不妨比較一下異同。一般來(lái)說(shuō),數(shù)據(jù)庫(kù)操作由以下幾個(gè)步驟組成一個(gè)常見(jiàn)的流程:

1. 建立一個(gè)數(shù)據(jù)庫(kù)連接

2. 通過(guò)建立的數(shù)據(jù)庫(kù)連接,執(zhí)行SQL語(yǔ)句

3. 執(zhí)行SQL后獲取返回的數(shù)據(jù)集

4. 在數(shù)據(jù)集中對(duì)記錄進(jìn)行處理,一般是一個(gè)循環(huán)的過(guò)程

5. 處理完畢,關(guān)閉數(shù)據(jù)庫(kù)連接,釋放資源

下面是按照上述的流程,在Perl中訪問(wèn)MySQL的一段代碼,以這段代碼為例,詳細(xì)說(shuō)明DBI的使用方法。

#!/usr/bin/perl -wuse strict;use DBI;my $dbh = DBI->connect("DBI:mysql:test:192.168.1.2", 'root', 'passWord');my $sth = $dbh->PRepare("SELECT * FROM test1");$sth->execute();while ( my @row = $sth->fetchrow_array() ){       print join('/t', @row)."/n";}$sth->finish();$dbh->disconnect();

注意代碼中的灰色部分就是要特別關(guān)注的數(shù)據(jù)庫(kù)訪問(wèn)接口,這里展現(xiàn)的只是一部分,下面將會(huì)依次說(shuō)明每一個(gè)步驟,以及其它的操作在Perl中是如何實(shí)現(xiàn)的。

1.1 連接數(shù)據(jù)庫(kù)

my $dbh = DBI->connect("DBI:mysql:test:192.168.1.2", 'root', 'password');

調(diào)用DBI的方法DBI->connect來(lái)建立一個(gè)數(shù)據(jù)庫(kù)的連接,如果連接成功則返回一個(gè)數(shù)據(jù)庫(kù)連接句柄,之后執(zhí)行SQL等操作都要把這個(gè)連接句柄作為一個(gè)操作參數(shù)。在connect調(diào)用中,首先要提供一個(gè)數(shù)據(jù)庫(kù)連接串。這個(gè)連接串用冒號(hào)分為了幾個(gè)部分,請(qǐng)看下表

小節(jié)說(shuō)明
DBI接口類型
mysql數(shù)據(jù)庫(kù)類型
test數(shù)據(jù)庫(kù)名稱
192.168.1.2數(shù)據(jù)庫(kù)主機(jī)地址

在前面例子中的連接串中,DBI表示這是DBI接口的一個(gè)連接串;mysql表示要連接的數(shù)據(jù)庫(kù)是MySQL數(shù)據(jù)庫(kù)(如果要連接Oracle數(shù)據(jù)庫(kù),這里則是oracle),不同的數(shù)據(jù)庫(kù)有不同的連接串定義,可以參考DBI對(duì)應(yīng)的訪問(wèn)驅(qū)動(dòng)的說(shuō)明;test指明了連接到數(shù)據(jù)庫(kù)主機(jī)上的數(shù)據(jù)庫(kù)名稱;192.168.1.2就是MySQL服務(wù)器的ip地址。這里要注意的是,連接串中的數(shù)據(jù)庫(kù)類型mysql必須小寫(xiě)。如果省略了主機(jī)名,則缺省為localhost。connect方法的后面兩個(gè)參數(shù)是連接數(shù)據(jù)庫(kù)主機(jī)的用戶名和密碼,這個(gè)可是不可缺少的 J

如果在連接過(guò)程中出現(xiàn)任何錯(cuò)誤,則connect的返回值都會(huì)是undef(和C語(yǔ)言中的NULL是一回事)。這里為了簡(jiǎn)化而略去了錯(cuò)誤檢查,實(shí)際做項(xiàng)目的時(shí)候應(yīng)當(dāng)對(duì)這些錯(cuò)誤和返回值的進(jìn)行檢查。

1.2 執(zhí)行SQL語(yǔ)句

my $sth = $dbh->prepare("SELECT * FROM test1");$sth->execute();$dbh->do(“UPDATE test1 SET time=now()”);

連接上了數(shù)據(jù)庫(kù),獲得了數(shù)據(jù)庫(kù)連接句柄,就可以利用這個(gè)句柄來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作了。要執(zhí)行一條SQL語(yǔ)句,為了提高性能,DBI分兩個(gè)步驟來(lái)做。先把SQL語(yǔ)句通過(guò)prepare方法提交到數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)為該語(yǔ)句分配執(zhí)行資源,之后調(diào)用execute方法通知數(shù)據(jù)庫(kù)執(zhí)行該SQL語(yǔ)句。注意prepare方法是通過(guò)數(shù)據(jù)庫(kù)連接句柄調(diào)用的,如果成功則返回一個(gè)該SQL的句柄,之后通過(guò)該SQL語(yǔ)句句柄調(diào)用execute執(zhí)行SQL。 一般來(lái)說(shuō)execute執(zhí)行的都是返回?cái)?shù)據(jù)的語(yǔ)句(例如SELECT語(yǔ)句)。反之如果執(zhí)行INSERT、UPDATE、DELETE、CREATE TABLE等不需要返回?cái)?shù)據(jù)的語(yǔ)句,則有一個(gè)更方便、快速的方法 $dbh->do(SQL語(yǔ)句),可以省去prepare的步驟。do方法返回的是受該SQL影響的記錄數(shù)量。

1.2.1 技巧:對(duì)SQL進(jìn)行排版

常寫(xiě)大段SQL的朋友可能會(huì)對(duì)于SQL中的引號(hào)很頭痛,每每都因?yàn)橐?hào)的問(wèn)題搞的SQL語(yǔ)句亂成一團(tuán)分辨不清。還記得上篇文章講過(guò)的QQ嗎?這里正是它的好用處。由于qq中的字符串同雙引號(hào)” ”內(nèi)的字符串一樣會(huì)對(duì)變量進(jìn)行解釋,同時(shí)qq還可以換行。因此使用它來(lái)對(duì)SQL進(jìn)行排版是非常好的一個(gè)選擇,例如像這樣的一條SQL語(yǔ)句:

my $res_Operator = $dbhandle->prepare( qq{       SELECT o_customerid, COUNT(*) AS totalMsgNum FROM mm4fcdrs       WHERE (m_date>'$begindate') AND (m_date<'enddate')        GROUP BY o_customerid });

根本無(wú)需考慮引號(hào)的問(wèn)題,可以和正常情況一樣的寫(xiě)SQL,是不是方便了很多?

1.2.2 通過(guò)SQL語(yǔ)句中的參數(shù)優(yōu)化查詢執(zhí)行效率

在執(zhí)行大量INSERT之類的語(yǔ)句的時(shí)候,反復(fù)向數(shù)據(jù)庫(kù)服務(wù)器提交同樣結(jié)構(gòu)的一個(gè)SQL語(yǔ)句,在這種情況下可以利用prepare和SQL參數(shù)來(lái)優(yōu)化執(zhí)行效率:

1.先使用prepare提交一個(gè)SQL模板給數(shù)據(jù)庫(kù)服務(wù)器,把其中值的部分用參數(shù)占位符代替。 2.使用prepare讓服務(wù)器為該SQL準(zhǔn)備了執(zhí)行資源后,調(diào)用execute并在該方法中傳入?yún)?shù)實(shí)際的值執(zhí)行SQL。 3.之后可以反復(fù)調(diào)用execute,不需要服務(wù)器重新prepare

假設(shè)要執(zhí)行這樣的一個(gè)系列的SQL

INSERT INTO test1 VALUES (NULL, ‘a(chǎn)’, ‘2005-04-01’)... ...INSERT INTO test1 VALUES (NULL, ‘z’, ‘2005-04-01’)

其中第二個(gè)字段的值是從a到z的字母。那么可以這樣來(lái)優(yōu)化執(zhí)行效率:

my $sth = $dbh->prepare( qq{    INSERT INTO test1 VALUES (NULL, ?, ‘2005-04-01’)} );for my $value('a'..'z')  {    $sth->execute($value);}

其中的問(wèn)號(hào)就是前面說(shuō)的參數(shù)占位符了,它的意思就是告訴在準(zhǔn)備執(zhí)行資源的服務(wù)器:這個(gè)SQL的這個(gè)位置會(huì)有一個(gè)值,但是現(xiàn)在還不知道,等下執(zhí)行的時(shí)候再告訴你。 prepare了之后,用一個(gè)循環(huán)產(chǎn)生a-z的字符給變量$value,然后將$value在execute方法中作為一個(gè)參數(shù)傳入,服務(wù)器那里會(huì)自動(dòng)用傳入的值替換前面的"?"。需要提醒的是,傳入的參數(shù)個(gè)數(shù)一定要和SQL中的占位符的數(shù)量一樣。

1.3 讀取記錄

熟悉ADO的朋友一定知道里面有一個(gè)DataReader對(duì)象,DBI中讀取數(shù)據(jù)的方法和它非常的相似。簡(jiǎn)單來(lái)說(shuō),就是單向、流式的讀取數(shù)據(jù),也就是每次只能向后讀一條數(shù)據(jù)直到?jīng)]有數(shù)據(jù)可以讀取。

文章開(kāi)頭的例子中,用了 $sth->fetchrow_array() 方法來(lái)讀取數(shù)據(jù)。其實(shí)DBI讀取數(shù)據(jù)還有幾種常見(jiàn)的方法,這幾個(gè)方法是類似的,所不同的是返回記錄的形式。

1.3.1 fetchrow_array

返回一個(gè)由字段的值組成的數(shù)組。該數(shù)組的第1個(gè)元素就是當(dāng)前記錄第1個(gè)字段的值。

while ( my @row = $sth->fetchrow_array() )  {    print "$row[0], $row[1], $row[2]/n";}

或者這樣,不過(guò)要注意字段對(duì)應(yīng)的順序

while ( my ($id, $name, $time) = $sth->fetchrow_array() )  {    print "$id, $name, $time/n";}

1.3.2 fetchrow_arrayref

返回由字段的值組成的數(shù)組的引用。同fetchrow_array的區(qū)別很明顯,fetchrow_arrayref返回的數(shù)組的引用。

while ( my $row_ref = $sth->fetchrow_arrayref() ) {    for (my $i = 0; $i < @{$row_ref}; $i++)       {        print "$row_ref->[$i]/t";    }    print "/n";}

這里要注意的是,如果要取字段的個(gè)數(shù),需要把這個(gè)引用轉(zhuǎn)成數(shù)組的形式獲得@{$row_ref} 。獲取數(shù)組元素的值的時(shí)候,因?yàn)?row_ref是引用,因此需要使用->操作符。

1.3.3 fetchrow_hashref

返回一個(gè)由”字段名-字段值”這樣的”鍵-值”對(duì)組成的HASH表。關(guān)鍵的不同就是,只有這個(gè)方法可以通過(guò)一個(gè)字段名獲得它的值,而不必關(guān)心這個(gè)字段是第幾個(gè)字段。而前者只能依靠索引來(lái)訪問(wèn)值。不過(guò)缺點(diǎn)就是,效率要比前面兩個(gè)差一些。

while ( my $record = $sth->fetchrow_hashref() ) {    for my $field( keys %{$record} ) {        print "$field: $record->{$field}/t";    }    print "/n";}

這里需要復(fù)習(xí)一下HASH表的操作方法。keys操作符獲取HASH的鍵(key)的數(shù)組,$record->{$field}獲得HASH表中$field對(duì)應(yīng)的值。注意這里同樣是引用,因此要用->操作符。

使用上面三個(gè)方法可以基本解決問(wèn)題了。此外,還有兩個(gè)方法fetchall_arrayrefselectall_arrayref可以直接通過(guò)SQL一次性獲取整個(gè)數(shù)據(jù)集,不過(guò)使用上稍微復(fù)雜一些,要涉及到 perl的scalar 操作符,這里就不贅述了。有興趣的讀者可以參考DBI的相關(guān)資料。

最后是收尾工作。

1.4 結(jié)束一個(gè)SQL會(huì)話

$sth->finish();

1.5 斷開(kāi)數(shù)據(jù)庫(kù)連接

$dbh->disconnect();

很簡(jiǎn)單明了,就不贅述了。

Perl中利用DBI訪問(wèn)數(shù)據(jù)庫(kù)的接口基本上就是這些了,還有一些高級(jí)的內(nèi)容留給有興趣的讀者自己發(fā)掘研究了。可能有些讀者會(huì)感覺(jué)沒(méi)有ADO、ADO.NET操作起來(lái)方便,但是在腳本的環(huán)境下能夠如此方便的操作數(shù)據(jù)庫(kù),比起用C接口來(lái)說(shuō)已經(jīng)方便很多了。也許在看完這片文章之后的不久,可以在cpan上發(fā)現(xiàn)你的Module和全世界的Perl程序員一起分享呢。

2 參考資源

《Programming the Perl DBI》 O’Reily
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 清流县| 正镶白旗| 南汇区| 台前县| 郓城县| 江山市| 林芝县| 左权县| 洪洞县| 白朗县| 昌邑市| 沁阳市| 嵩明县| 三原县| 西安市| 定西市| 昭苏县| 光泽县| 汉寿县| 阿克| 登封市| 甘德县| 延庆县| 桃源县| 思茅市| 蓬溪县| 苗栗市| 含山县| 昭觉县| 阿图什市| 英山县| 花莲县| 内江市| 伊川县| 镇赉县| 张掖市| 满洲里市| 乃东县| 扎赉特旗| 宜都市| 会泽县|