使用DBI的方法:---------------------------------------------------------------------use DBI;---------------------------------------------------------------------注意:特定的DBD 級的模塊不需要包括use 行,因為在與服務(wù)器進(jìn)行連接時, DBI 負(fù)責(zé)激活相應(yīng)的模塊,比如DBD::MySQL。一、一些變量表達(dá)的常用意思$drh表示驅(qū)動程序?qū)ο蟮木浔?dbh表示針對一個數(shù)據(jù)庫對象的句柄$sth表示針對一個語句或者一個查詢對象的句柄$fh表示一個打開文件的句柄$h表示一個通用的句柄,其含意有賴于上下文$rc表示操作代碼返回的布什值(真或假)$rv表示操作代碼返回的整數(shù)值$rows表示操作代碼返回的行數(shù)值$str表示操作代碼返回的字符串@ary表示查詢返回的一行值的數(shù)組(列表)@row_ary表示從查詢中返回的一個行的數(shù)組二、關(guān)于DBI的一些驅(qū)動對象方法:查詢子類函數(shù):DBI->available_drivers比如:---------------------------------------------------------------foreach(DBI->available_drivers){PRint;}---------------------------------------------------------------------結(jié)果:DBI::mysql數(shù)據(jù)源函數(shù):DBI->data_sources比如:---------------------------------------------------------------foreach(DBI->data_sources){print;}---------------------------------------------------------------------結(jié)果:對于大多數(shù)正確的驅(qū)動子類來說,返回值一般為空,對于不能連接、用戶名或密碼為空的驅(qū)動子類,返回值不為空數(shù)據(jù)庫方法調(diào)用:DBI -> install_driver比如:---------------------------------------------------------------------my $drh = DBI -> install_driver("mysql");---------------------------------------------------------------------結(jié)果:提供驅(qū)動子類的句柄,可以使用$drh -> func ("createdb", $db_name, $db_host, $username, $passWord, "admin");來創(chuàng)建數(shù)據(jù)庫數(shù)據(jù)庫連接:DBI -> connect比如:---------------------------------------------------------------my $dsn = "dbi:mysql:database=${db_name};hostname=${db_host};mysql_socket=${db_sock};port=${db_port};mysql_compression=1;mysql_read_default_file=$ENV{HOME}/.my.cnf;mysql_read_default_group=client";my %attr = ( PrintError => 0, RaiseError => 0);my $dbh = DBI -> connect ($dsn, $user_name, $password, [,/%attr]);---------------------------------------------------------------------結(jié)果:返回值是針對一個數(shù)據(jù)庫的句柄,提供數(shù)據(jù)庫連接功能,關(guān)閉連接使用$dbh -> disconnect,其中很多參數(shù)可以省略,包括數(shù)據(jù)庫名稱。三、數(shù)據(jù)庫句柄方法的調(diào)用1,do方法:my $rows = $dbh -> do ($query[, /%attr[, @bind_values]]);語法解釋:準(zhǔn)備并運行$query表示的查詢。返回值為受影響的行數(shù)—如果不知道行數(shù),則返回-1,如果出現(xiàn)錯誤,則返回undef。如果受影響的行數(shù)為0,則返回值為字符串“0E0”,作為數(shù)值它與0等價,但在判斷時它為真。一般用于非SELECT查詢,不檢索行的語句,如DELETE、INSERT、REPLACE或UPDATE,主要使用do()。如果對SELECT語句使用它,則不會獲得返回的語句句柄,也不能提取任何行。當(dāng)語句包括占位符(在此查詢字符串內(nèi)部由‘?’字母表示)時,使用@bind_values。@bind_values為給占位符賦值的值的列表。它必須和占位符有一樣多的值。如果只指定賦值的值,但沒有指定屬性,則將undef作為/%attr參數(shù)的值來傳遞。與prepare和execute結(jié)合使用的功能基本相同。2,ping方法:my $rc = $dbh -> ping ();語法解釋:檢查與服務(wù)器的連接是否仍然有效,并相應(yīng)返回真或假。3,prepare方法:my $sth = $dbh -> prepare ($query[, /%attr]);語法解釋:為以后的執(zhí)行所準(zhǔn)備的由$query表示的查詢,并返回一個語句句柄。返回的句柄可用于execute(),以便執(zhí)行該查詢。4,quote方法:my $str = $dbh -> quote ($value[, $data_type]);語法解釋:處理字符串以實現(xiàn)SQL語句中特定字符的引用和轉(zhuǎn)義,以便在執(zhí)行這條語句時,該字符串不引起語法錯誤。例如,“‘I /’m happy’”(沒有雙引號)返回字符串“I ’m happy”。如果$value為undef,則它返回字符串“NULL”(沒有引號)。一般來說,$data_type參數(shù)不是必需的,因為MySQL將查詢中指定為字符串的值自動地轉(zhuǎn)換為其他類型??梢詫?data_type指定為特殊類型值的提示————例如,DBI::SQL_INTEGER指出$value表示一個整數(shù)。不要使用具有打算利用占位符插入到查詢中的值的quote()。DBI會自動引用這樣的值。5,selectall_arrayref方法my $ary_ref = $dbh -> selectall_arrayref ($query[, /%attr[, @bind_values]]);語法解釋:執(zhí)行由$query指定的查詢,并結(jié)合prepare()、execute()和fetchall_arrayref()返回結(jié)果。如果出現(xiàn)錯誤,則返回undef。如果$query參數(shù)是以前準(zhǔn)備的語句,則省略prepare()步驟。@bind_values參數(shù)和do()方法中的該參數(shù)具有同樣的意義。比如:---------------------------------------------------------------------# fetch all rows into a reference to an array of references my $matrix_ref = $dbh -> selectall_arrayref ($query);# determine dimensions of matrixmy $rows = (!defined ($matrix_ref) ? 0 : scalar (@{$matrix_ref}));my $cols = ($rows == 0 ? 0 : scalar (@{$matrix_ref->[0]}));for (my $i = 0; $i < $rows; $i ++) # print each row{my $delim = "";for (my $j = 0; $j < $cols; $j ++){$matrix_ref -> [$i][$j] = "" if !defined ($matrix_ref -> [$i][$j]); # NULL?print $delim . $matrix_ref -> [$i][$j];$delim = ",";}print "/n";}---------------------------------------------------------------------6,selectcol_arrayref方法my @ary_ref = $dbh -> selectcol_arrayref ($query[, /%attr[, @bind_values]]);語法解釋:執(zhí)行由$query指定的查詢,并通過組合prepare()和execute()返回結(jié)果的第一列。返回結(jié)果作為對含有每行第一列的數(shù)組的引用。如果出現(xiàn)錯誤,則返回undef。如果$query參數(shù)是以前準(zhǔn)備的語句,則省略prepare()步驟。@bind_values參數(shù)和do()方法中的該參數(shù)具有同樣的意義。7,selectrow_array方法my @row_ary = $dbh -> selectrow_array ($query[, /%attr[, @bind_values]]);語法解釋:執(zhí)行由$query指定的查詢,并結(jié)合prepare()、execute()和fetchall_arrayref()返回結(jié)果的第一行。如果參數(shù)$query是以前準(zhǔn)備的語句,則省略prepare()步驟。如果在列表的上下文中調(diào)用時,selectrow_array()返回代表行值的數(shù)組,或者,如果出現(xiàn)錯誤,則返回空數(shù)組。在標(biāo)量的上下文 中,selectrow_array()返回這個數(shù)組的第一個元素的值(行的第一列)。如果出現(xiàn)錯誤,則返回undef。@bind_values參數(shù)和do()方法中的相應(yīng)參數(shù)具有同樣的意義。四、語句句柄方法的調(diào)用1,bind_col方法my $rc = $sth -> bind_col($col_num, /$var_to_bind);將SELECT查詢的給定列與Perl變量相聯(lián)系,將它作為引用傳遞。$col_num的范圍為1到查詢選擇的列數(shù)。每次提取行時,這個變量用列值自動更新。bind_col()應(yīng)該在execute()之前及prepare()之后調(diào)用。如果列號范圍不在1到查詢選擇的列數(shù)之間,則bind_col()返回假。2,bind_columns方法my $rc = $sth -> bind_columns (/$var_to_bind1, /$var_to_bind2, ...);將一系列變量與由準(zhǔn)備好的SELECT 語句返回的列相聯(lián)系,請參閱bind_col()方法的說明。如果引用的數(shù)量與查詢選擇的列數(shù)不匹配,則bind_columns() 返回假。3,bind_param方法my $rv = $sth -> bind_param ($n, $value[, /%attr]);my $rv = $sth -> bind_param ($n, $value[, $bind_type]);在一個語句中,將值與占位符‘?’相聯(lián)系。應(yīng)該在execute()之前及prepare()之后調(diào)用它。$n指定了占位符的數(shù)量,應(yīng)該限定$value值,而且該值范圍應(yīng)該為1到占位符的數(shù)量。為了限定NULL值,可傳遞undef。參數(shù)/%attr或者$bind_type可作為要聯(lián)系的值的類型提示。4,dump_results方法my $rows = $sth -> dump_results ([$maxlen[, $line_sep[, $field_sep[, $fh]]]]);從語句句柄$sth 中提取所有的行,通過調(diào)用實用函數(shù)DBI::neat_list()將他們格式化,并將他們打印到給定的文件句柄中。返回提取的行數(shù)$maxlen、$line_sep、$field_sep和$fh的缺省值分別為35、“/n”、“,”和STDOUT。5,execute方法:my $rows = $sth -> execute ([@bind_values]);執(zhí)行準(zhǔn)備好的語句。如果該語句執(zhí)行成功,則返回真,如果發(fā)生錯誤,則返回undef。參數(shù)@bind_values與do()方法中的有相同的意義。6,fetchall_arrayref方法:my $tbl_ary_ref = $sth -> fetchall_arrayref ([$slice_array_ref]);從語句句柄$sth 中提取所有行,并返回數(shù)組的引用,這個數(shù)組包含提取的每行的一個引用。數(shù)組中每個引用的意義取決于所傳遞的參數(shù)。沒有參數(shù)或者只有數(shù)組部分引用參數(shù), 則$tbl_ary_ref 的每個元素都是包括結(jié)果集的一行值的數(shù)組引用。對于散列部分的引用參數(shù),$tbl_ary_ref 的每個元素就是對包含結(jié)果集的一行值的散列引用。7,fetchrow_array方法:my @ary_ref = $sth -> fetchrow_array ();當(dāng)在一個列表的范圍中調(diào)用時,fetchrow_array()返回包含結(jié)果集下一行列值的數(shù)組,如果不再有行或者發(fā)生錯誤,則 fetchrow_array()返回一個空數(shù)組。在標(biāo)量上下文中,fetchrow_array()返回數(shù)組第一個元素的值(那就是說,行的第一列), 如果不再有行或者發(fā)生錯誤,則fetchrow_array()返回undef。通過檢查$sth->err(),可以將結(jié)果集正常結(jié)束與出現(xiàn)錯誤區(qū)分開來。零值表明已經(jīng)無錯誤地到達(dá)了結(jié)果集的末尾。一般與while使用。比如:---------------------------------------------------------------------while (my @ary = $sth -> fetchrow_array ()) {@ary = map { defined ($_) ? $_ : "NULL" } @ary;print join (",", @ary) . "/n";}---------------------------------------------------------------------8,fetch或fetchrow_arrayref方法my @ary_ref = $sth -> fetchrow_arrayref ();返回一個包括結(jié)果集的下一行列值的數(shù)組引用。如果不再有行或者發(fā)生錯誤,則返回undef。通過檢查$sth->err(),可以將結(jié)果集正常結(jié)束與出現(xiàn)錯誤區(qū)分開來。零值表明已經(jīng)無錯誤地到達(dá)了結(jié)果集的末尾。一般與while使用。比如:-----------------------------------------------------------------------------------my @matrix = (); # array of array references while (my @ary = $sth -> fetchrow_array ()) # fetch each row{push (@matrix, [ @ary ]); # save reference to just-fetched row}# determine dimensions of matrixmy $rows = scalar (@matrix);my $cols = ($rows == 0 ? 0 : scalar (@{$matrix[0]}));for (my $i = 0; $i < $rows; $i++) # print each row{my $delim = "";for (my $j = 0; $j < $cols; $j++){$matrix[$i][$j] = "" if !defined ($matrix[$i][$j]); # NULL value?print $delim . $matrix[$i][$j];$delim = ",";}print "/n";}---------------------------------------------------------------------9,fetchrow_hashref方法my $hash_ref = $sth -> fetchrow_hashref ([$name]);返回包括結(jié)果集的下一行列值的散列引用。如果不再有行或者發(fā)生錯誤,則返回undef。散列是索引值是列名稱,散列的元素是列值。對于散列的關(guān)鍵值,指定變量$name說明使用的語句句柄屬性。缺省值為“NAME”。這可能導(dǎo)致查詢中的列名稱不區(qū)分大小寫的問題,但是散列鍵是區(qū)分大 小寫的。要強迫散列鍵為大寫字母或者小寫字母,可以指定“NAME_lc”或“NAME_uc”的$name值。通過檢查$sth->err(),可以將結(jié)果集正常結(jié)束與出現(xiàn)錯誤區(qū)分開來。零值表明已經(jīng)無錯誤地到達(dá)了結(jié)果集的末尾。一般與while使用。比如:---------------------------------------------------------------------while (my $hash_ref = $sth -> fetchrow_hashref ()) {my $delim = "";foreach my $key (keys (%{$hash_ref})){$hash_ref -> {$key} = "" if !defined ($hash_ref->{$key}); # NULL value?print $delim . $hash_ref -> {$key};$delim = ",";}print "/n";}---------------------------------------------------------------------10,finish方法my $rc = $sth -> finish();釋放有關(guān)語句句柄的任何資源。通常不必顯式地調(diào)用這個方法,但是如果只提取部分結(jié)果集,則調(diào)用finish()使DBI了解已經(jīng)提取了數(shù)據(jù)。調(diào)用 finish()可能使語句屬性無效,最好在調(diào)用execute()之后立即訪問它們。11,rows方法my $rv = $sth -> rows();返回與$sth相關(guān)的語句所作用的行數(shù),如果發(fā)生錯誤,則返回-1。使用這個方法主要用于不返回行的語句。對于SELECT語句,不能依賴rows()方法在提取行時統(tǒng)計行數(shù)。五、通用句柄方法下面的方法不是專用于特定類型的句柄的。可用驅(qū)動程序、數(shù)據(jù)庫或語句句柄來調(diào)用它們。1,$h -> err()返回最近調(diào)用的驅(qū)動程序操作的數(shù)字錯誤代碼。0表示沒有錯誤。2,$h -> errstr()返回最近調(diào)用的驅(qū)動程序操作的字符串錯誤消息??兆址硎緵]有錯誤。3,DBI -> trace($trace_level[, $trace_filename]);$h -> trace($trace_level[, $trace_filename]);設(shè)置跟蹤級別。跟蹤提供有關(guān)DBI操作的信息。跟蹤級別的范圍從0(關(guān)閉)到9(最多信息)。通過作為DBI類方法或獨立的句柄調(diào)用跟蹤,跟蹤可以啟用腳本內(nèi)部的所有DBI操作:DBI->trace(2);打開腳本跟蹤$sth->trace(2);打開句柄跟蹤通過設(shè)置DBI_TRACE環(huán)境變量,也可以對運行的所有DBI腳本在全局級別啟用跟蹤。缺省時,跟蹤輸出到STDERR.。提供的$filename參 數(shù)可以直接將結(jié)果輸出到不同的文件。將輸出添加到這個文件的任何已有內(nèi)容后面。每個跟蹤調(diào)用導(dǎo)致來自所有跟蹤的句柄中的輸出進(jìn)入相同的文件。如果文件已命名,則所有跟蹤就輸出到那個文件。如果沒有命名的文件,則所有跟蹤輸出到STDERR。4,DBI -> trace_msg($str[, $min_level])$h -> trace_msg($str[, $min_level])如果跟蹤這個句柄或如果在DBI級啟用跟蹤,則編寫這個跟蹤輸出的消息。如果啟用DBI級的跟蹤,則trace_msg()可以作為 DBI->trace_msg()來調(diào)用,編寫消息。只有在跟蹤級別至少為這個級別時,才可以提供$min_level 參數(shù)來指定應(yīng)該編寫的消息。六、MySQL 的特定管理方法DBI 作為直接訪問驅(qū)動程序的手段所供的func() 函數(shù)方法---------------------------------------------------------------------$rc = $drh -> func("createdb", $dbname, [host, user, password,], 'admin');$rc = $drh -> func("dropdb", $dbname, [host, user, password,], 'admin');$rc = $drh -> func("shutdown", [host, user, password,], 'admin');$rc = $drh -> func("reload", [host, user, password,], 'admin');---------------------------------------------------------------------or---------------------------------------------------------------------$rc = $dbh -> func("createdb", $dbname, 'admin');$rc = $dbh -> func("dropdb", $dbname, 'admin');$rc = $dbh -> func("shutdown", 'admin');$rc = $dbh -> func("reload", 'admin');---------------------------------------------------------------------通過驅(qū) 動程序句柄或通過數(shù)據(jù)庫句柄訪問func()方法。驅(qū)動程序句柄與打開的連接無關(guān),所以,如果以這種方式訪問func(),則必須提供允許這個方法創(chuàng)建連 接的主機名稱、用戶名稱和口令的參數(shù)。如果用數(shù)據(jù)庫句柄訪問func(),則不需要那些參數(shù)。如果需要,可以像下面這樣獲得驅(qū)動程序句柄:my $drh = DBI -> install_driver(“mysql”);#(“mysql”mustbelowercase)createdb創(chuàng)建由$db_name指定的數(shù)據(jù)庫。要這樣做,必須對該數(shù)據(jù)庫擁有CREAT權(quán)限。dropdb刪除由$db_name指定的數(shù)據(jù)庫。要這樣做,必須對該數(shù)據(jù)庫擁有DROP權(quán)限。當(dāng)心,如果刪除了一個數(shù)據(jù)庫,則它將會消失,且再也不能恢復(fù)。shutdown關(guān)閉服務(wù)器。必須具有SHUTDOWN權(quán)限。reload告訴服務(wù)器重新加載授權(quán)表。如果直接使用DELETE、INSERT或UPDATE而不是使用GRANT或REVOKE來修改這個授權(quán)表的內(nèi)容,則這是必需的。要使用reload,必須具有RELOAD權(quán)限。七、DBI 環(huán)境變量DBI考慮了幾個環(huán)境變量,如表G-3所示。除了DBI_TRACE之外,所有變量都由connect()方法使用。DBI_TRACE由trace()方法使用。DBI_DRIVER:DBI級的驅(qū)動程序名(MySQL的“mysql”)DBI_DSN:數(shù)據(jù)源名DBI_PASS:口令DBI_TRACE:跟蹤級別和/或跟蹤輸出文件DBI_USER:用戶名稱---------------------------------------------------------------------$errno = $dbh->{'mysql_errno'};$error = $dbh->{'mysql_error};$info = $dbh->{'mysql_hostinfo'};$info = $dbh->{'mysql_info'};$insertid = $dbh->{'mysql_insertid'};$info = $dbh->{'mysql_protoinfo'};$info = $dbh->{'mysql_serverinfo'};$info = $dbh->{'mysql_stat'};$threadId = $dbh->{'mysql_thread_id'};---------------------------------------------------------------------八、一個例子---------------------------------------------------------------------#!/usr/bin/perl -w use CGI::Carp "fatalsToBrowser"; use strict; use warnings; use DBI; use CGI qw (:standard escapeHTML escape); my ($driver_name, $db_name, $db_host, $db_sock, $db_port, $db_user, $db_pswd, $dsn); $driver_name = 'mysql'; $db_name = 'mydata'; $db_host = 'localhost'; $db_sock = '/tmp/mysql.sock'; $db_port = '3306'; $db_user = 'cnangel'; $db_pswd = 'cnangel'; $dsn = "dbi:mysql:database=${db_name};hostname=${db_host};mysql_socket=${db_sock};port=${db_port}"; # ... set up connection to database (not shown) ... my $dbh = DBI -> connect ($dsn, $db_user, $db_pswd, { RaiseError => 1, PrintError => 0 }); # put out initial part of page my $title = "$db_name Database Browser"; print header (); print start_html (-title => $title, -bgcolor => "white"); print h1 ($title); # parameters to look for in URL my $tbl_name = param ("tbl_name"); my $sort_col = param ("sort_col"); # If $tbl_name has no value, display a clickable list of tables. # Otherwise, display contents of the given table. $sort_col, if # set, indicates which column to sort by. !defined ($tbl_name) ? display_table_names ($dbh, $db_name) : display_table_contents ($dbh, $tbl_name, $sort_col); print end_html (); sub display_table_names { my ($dbh, $db_name) = @_; print p ("Select a table by clicking on its name:"); # retrieve reference to single-column array of table names my $ary_ref = $dbh -> selectcol_arrayref (QQ{ SHOW TABLES FROM $db_name }); # Construct a bullet list using the ul() (unordered list) and # li() (list item) functions. Each item is a hyperlink that # re-invokes the script to display a particular table. my @item; foreach my $tbl_name (@{$ary_ref}) { my $url = sprintf ("%s?tbl_name=%s", url (), escape ($tbl_name)); my $link = a ({-href => $url}, escapeHTML ($tbl_name)); push (@item, li ($link)); } print ul (@item); } sub display_table_contents { my ($dbh, $tbl_name, $sort_col) = @_; my @rows; my @cells; # if sort column not specified, use first column $sort_col = "1" if !defined ($sort_col); # present a link that returns user to table list page print p (a ({-href => url ()}, "Show Table List")); print p (strong ("Contents of $tbl_name table:")); my $sth = $dbh -> prepare (qq{ SELECT * FROM $tbl_name ORDER BY $sort_col LIMIT 200 }); $sth -> execute (); # Use the names of the columns in the database table as the # headings in an HTML table. Make each name a hyperlink that # causes the script to be reinvoked to redisplay the table, # sorted by the named column. foreach my $col_name (@{$sth -> {NAME}}) { my $url = sprintf ("%s?tbl_name=%s;sort_col=%s", url (), escape ($tbl_name), escape ($col_name)); my $link = a ({-href => $url}, escapeHTML ($col_name)); push (@cells, th ($link)); } push (@rows, Tr (@cells)); # display table rows while (my @ary = $sth -> fetchrow_array ()) { @cells = (); foreach my $val (@ary) { # display value if non-empty, else display non-breaking space if (defined ($val) && $val ne "") { $val = escapeHTML ($val); } else { $val = " "; } push (@cells, td ($val)); } push (@rows, Tr (@cells)); } # display table with a border print table ({-border => "1"}, @rows); } 1, AutoCommit — 是否自動提交一般來說自動提交不利于應(yīng)用程序的性能.$dbh->{AutoCommit} = 1;print “AutoCommit: $dbh->{AutoCommit}/n”;2, ChopBlanks — 取舍CHAR類型后面的空格當(dāng)你從數(shù)據(jù)庫中取CHAR類型的值時, 你可以指定要不要帶后面的空格, 在數(shù)據(jù)庫中CHAR是定長的, 長足不足時, 后面以空格補充, 但你在寫應(yīng)用程序時, 可能并不想要后面的空格, 這時你可以將這個選項設(shè)為1.$dbh->{ChopBlanks} = 1;print “ChopBlanks: $dbh->{ChopBlanks}/n”;3, LongTruncOK — 是否允許載斷返回值如果返回值(如Long或LOB類型)的值大于緩沖區(qū)的長度, 有兩個選項, 一種是報錯, 另一種是只取緩沖區(qū)的長度的值, 丟棄后面的值. 設(shè)為True, 則不報錯而只取一部份值, 設(shè)為False則報錯.$dbh->{LongTruncOk} = 1;print “LongTruncOk: $dbh->{LongTruncOk}/n”;4, LongReadLen — 指定Long或LOB緩沖的最長大度在數(shù)據(jù)庫中, Long或LOB類型可以存放2GB或更多的值, 在Perl應(yīng)用程序去取這些值時, 必須要指定一個最大的緩沖區(qū)大小, 和LongTruncOk配合, 可以取出一定長度的值.$dbh->{LongReadLen} = 1048576;print “LongReadLen: $dbh->{LongReadLen}/n”;