DBI 數據類型
從某些方面來說,使用Perl DBI API 類似於使用第6章介紹的C 客戶機庫。在使用C 客戶機庫時,主要依靠指向結構或數組的指針來調用函數和訪問與MySQL相關的數據。在使用DBI API 時,除了函數稱為方法,指針稱為引用外,也調用函數和使用指向結構的指針。
指針變量稱為句柄,句柄指向的峁鉤莆韻蟆?br> DBI 使用若干種句柄。它們往往通過表7-1所示的慣用名稱在DBI 文件中引用。而慣用的非句柄變量的名稱如表7 - 2所示。實際上,在本章中,我們並不使用每個變量名,但是,在閱讀其他人編寫的DBI 腳本時,了解它們是有用的。
表7-1慣用的Perl DBI 句柄變量名
名稱說明 $dbh 數據庫對象的句柄 $sth 語句(查詢)對象的句柄 $fh 打開文件的句柄 $h “通用”句柄;其意義取決於上下文表7-2 慣用的Perl DBI 非句柄變量的名稱
名稱說明 $rc 從返回真或假的操作中返回的代碼 $rv 從返回整數的操作中返回的值 $rows 從返回行數的操作中返回的值 @ary 查詢返回的表示一行值的數組(列表)
一個簡單的DBI 腳本
讓我們從一個簡單腳本d um p _ member s開始,它舉例說明了DBI 程序設計中若干標准概念,如與MySQL服務器的連接和斷開、檢索數據等。此腳本產生的結果為以制表符分隔形式列出的歷史同盟成員。這個格式本身並不讓人感興趣:在這裡,了解如何使用DBI 比產生漂亮的輸出更為重要。
dump_members 如下:
(study.iader.com)
要想自己試驗這個腳本,可以下載它(請參閱符錄A),或使用文本編輯器創建它,然後使之可執行,以便能運行。當然,可能至少需要更改一些連接參數(主機名、數據庫名、用戶名和口令)。本章中的其他DBI 腳本也是這樣。在參數缺省時,本章下載腳本的權限設置為只允許讀。如果您將自己的MySQL用戶名和口令放在它們之中,我建議將它們保留為這種方式,以便其他人不能讀取這些值。以後,在7 . 2 . 8節“指定連接參數”中,我們將看到如何從選項文件中獲得這些參數,而不是將它們直接放在腳本中。
現在,讓我們逐行看完這個腳本。第一行是標准行,指出哪裡可以找到Perl 的指示器:
#! /usr/bin/perl
在本章將要討論的腳本中,每個腳本都包含這行;以後不再說明。此腳本中至少應該含有一個簡短的目的說明,這是一個好主意,所以下一行是一個注釋,給閱讀此腳本的人提供一個關於它做什麼的線索:
# dump_members.dump Historical League's membership list
從‘#’字符到行尾部的文本為注釋。有必要做一些練習,就是在整個腳本中編寫一些注釋來解釋它們如何工作。
接下來是兩個use 行:
use DBI;
use strict;
use DBI 告知Perl 解釋程序它需要引入DBI 模塊。如果沒有這一行,試圖在腳本中做與DBI 相關的任何事,都將出現錯誤。不需要指出想要哪個DBD 級別的模塊。在連接數據庫時,DBI 會激活相應的模塊。
use strict 告知Perl,在使用它們之前需要聲明變量。如果沒有use strict 行,也可以編寫腳本,但是,它有助於發現錯誤,所以建議始終要包括這行。例如,置為嚴格模式時,如果聲明變量$ my _ v a r,但是之後錯誤地用$mv_var 來訪問,則在運行這個腳本時,將獲得下面的消息:
如果connect( ) 調用成功,則它返回數據庫句柄,我們分配給$dbh(如果connect( ) 失敗,通常返回un d e f。然而,因為我們在腳本中啟用了R a i s e E r r o r,所以connect( )不返回;但是,DBI 將顯示一條錯誤消息,並且在出現錯誤時退出)。
fetchrow_array( ) 返回含有當前行的列值的數組,在沒有剩余的行時,返回一個空數組。這樣,此循環提取了由SELECT 語句返回的連續行,並顯示列值之間用制表符分隔的每一行。在數據庫中NULL 作為undef 值返回到Perl 腳本,但是將它們顯示為空字符串,而不是單詞“NULL”。
請注意,制表符和換行符(表示為‘ \ t’和‘\ n’)括在雙引號中。在Perl 中,只解釋出現在雙引號內的轉義符序列,不解釋出現在單引號內的轉義符序列。如果使用單引號,則輸出將為字符串“\ t”和“\ n”。
提取行的循環終止以後,調用finish( ) 告知DBI 不再需要語句句柄,並且釋放分配給它的所有臨時資源。實際上,除非只提取結果集的一部分(無論是設計的原因,還是因為出現一些問題),否則不需要調用finish( )。然而,在提取循環之後, finish( ) 始終是很保險的,我認為調用並執行finish( ),比區分何時需要,何時不需要更容易一些。
我們已經顯示完了全部成員列表,所以我們可以從服務器上斷開連接,並且退出:
$dbh->disconnect();
exit(0);
dump_members 示出了許多DBI 程序的大多數通用概念,而且不必了解更多的知識,就可以著手編寫自己的DBI 程序。例如,要想寫出一些其他表的內容,所需要做的只是更改傳遞給prepare( ) 方法的SELECT 語句的文本。而且實際上,如果想了解這種技術的某些應用,可略過這部分,直接跳到7 . 3節“運行DBI”中討論如何生成歷史同盟一年一度的宴會成員列表程序和League 打印目錄的部分。然而,DBI 提供許多其他有用的功能。下一節介紹了一些,以便能夠在Perl 腳本中看看如何完成比運行一條簡單的SELECT 語句更多的事情。
處理錯誤
在dump_members 調用connect( )方法時,應該啟用RaiseError 錯誤處理屬性,以便這些錯誤用一條錯誤消息就能自動地終止相應的腳本。也可以用其他方式處理這些錯誤。例如,可以自己檢查錯誤而不必使用DBI。
為了查看如何控制DBI 的錯誤處理行為,我們來仔細查看一下connect( ) 調用的最終參數。下面兩個相關的屬性是RaiseError 和P r i n t E r r o r:
如果啟用R a i s e E r r o r(設為非零值),如果在DBI 方法中出現錯誤,則DBI 調用dIE( ) 來顯示一條消息並且退出。
如果啟用P r i n t E r r o r,在出現DBI錯誤時,DBI 會調用warn( ) 來顯示一條消息,但是相應腳本會繼續執行。
缺省時, RaiseError 是禁用的,而PrintError 啟用。在此情況下,如果connect( )調用失敗,則DBI 顯示一條消息,而且繼續執行。這樣,如果省略connect( ) 的四個參數,則得到缺省的錯誤處理行為,可以如下檢查錯誤:
$dbh=DBI->connect($dsn,$user_name,$passWord) or exit (1);
如果出現錯誤,則connect( ) 返回undef 表示失敗,並且觸發對exit( ) 的調用。因為DBI 已經顯示了錯誤消息,所以您就不一定要顯示它了。
如果明確給出該錯誤檢查屬性的缺省值,可如下調用connect( )。
$dbh=DBI->connect($dsn,$user_name,$passWord,{RaiseError=>0,PrintError=>1})
or exit (1);
這就需要更多的編寫工作,但是即使對不經意的讀者,處理錯誤行為也會更為明顯。
如果想自己檢查錯誤,並顯示自己的消息,應該禁用RaiseError 和P r i n t E r r o r:
變量$DBI::err 和$ DBI : :er r s t r,只用於所顯示的dIE( ) 調用中,有助於構造錯誤消息。它們含有MySQL錯誤代碼和錯誤字符串,非常像C API 函數中的mysql_errno( ) 和MySQL_error( )。
如果僅僅要DBI 處理錯誤,以便不必自己檢查它們,則啟用R a i s e E r r o r:
$dbh=DBI->connect ($dsn,$user_name,$passWord,{RaiseError=>1});
避免啟用RaiseError 屬性的另一個原因是DBI 在它的消息中顯示技術信息,如下:
if (!$rows) {#error}
可如下使用fetchrow_array( ):
如果希望將一行值傳遞給某個函數而又不需要這個函數知道SELECT 語句中指定列的次序時,fetchrow_hashref( ) 是非常有用的。既然如此,可以調用fetchrow_hashref( ) 來檢索行,並且編寫一個使用列名訪問來自行散列值的函數。
如果使用fetchrow_hashref( ),請記住下列警告:
如果性能很重要,則fetchrow_hashref( ) 並不是最好的選擇,因為它沒有fetchrow_array( ) 或fetchrow_arrayref( ) 的效率高。
作為散列鍵值使用的列名具有與SELECT 語句中寫出時相同的字符。在MySQL中,列名不區分大小寫,所以此查詢也是這樣,不管以大寫字母還是小寫字母給出列名,查詢結果都是一樣的。但是Perl 散列索引名是區分大小寫的,這可能會帶來一些問題。為了避免潛在的大小寫不匹配問題,可通過傳遞NAME_lc 或NAME_uc 屬性,告知fetchrow_hashref( ) 強迫列名為大寫或小寫:
散列對每個唯一的列名含有一個元素。如果正在執行從多個具有重疊名稱的表中返回列的連接,則不能訪問所有的列值。例如,如果發布下面的查詢, fetchrow_hashref( )將返回只有一個元素的散列:
SELECT a.name FROM a,b WHERE a.name=b.name
2. 確定查詢返回的行數
如何知道SELECT 或類似於SELECT 的查詢返回的行數?一種方法是,當提取它們時,計算這些行的數量。實際上,這是知道SELECT 查詢返回多少行的唯一方便的方法。使用MySQL驅動程序,可以在調用execute( ) 後利用語句句柄調用rows( ) 方法,但是這對其他數據庫引擎並不方便。而且即使就MySQL來說,如果已經設置了MySQL_use_result 屬性,rows( ) 也不能返回正確的結果,直到提取了所有行(有關的詳細信息,請參閱附錄G)。所以只能如提取行一樣對它們進行計數。
3. 提取單行的結果
如果結果集只含單個行,則不需要運行循環來獲得結果。假設要編寫得出歷史同盟成員當前數量的腳本count _ member s。完成查詢的代碼如下所示:
SELECT 語句只返回一行,所以不需要循環;我們只調用fetchrow_array( ) 一次。另外,因為我們只選擇一列,所以甚至不需要將返回值分配給數組。當在標量環境中(單個值而不是所期望的一列)調用fetchrow_array( ) 時,它返回這個行的第一列,如果沒有更多的有效行,則返回un d e f。
另一種期望最多有一個記錄的查詢是一個含有LIMIT 1來約束返回的行數的查詢。其一般的用法是返回特定列含有最大或最小值的行。例如,下面的查詢給出最近出生的總統姓名和出生日期:
必須無提取循環的其他類型的查詢利用MAX( ) 或MIN( ) 來選擇單個值。但是在所有這些情況下,獲得單個行結果的一種更容易的方法就是使用數據庫句柄方法selectrow_array( ),它結合了prepare( )、execute( ) 並在單個調用中提取行。它返回一個數組(而不是一個引用),如果出現錯誤,則返回一個空數組。前一例子可利用selectrow_array( ) 編寫如下:
4. 處理完整的結果集
在使用提取循環時, DBI 不提供在結果集中隨意查找的方法,或以任何次序而不是以循環返回的次序來處理行。同樣,提取行以後,如果沒有保存,前一行會丟失。這種做法並不一定合適以下情況:
以非連續的次序處理行。考慮一種情況,想以歷史同盟的president 表中列出的美國總統為主體,進行一些測驗。如果希望每次測驗時都以不同的次序提出問題,則可以從president 表中選擇所有行。然後,可能以任意的次序提取行來改變與所問問題有關的總統的次序。要想任意地提取一行,就必須同時訪問所有的行。
元素。下面的討論說明這兩種方法。
使用提取循環來捕獲結果集的一種方法是使用fetchrow_array( ) 並保存對這些行引用的數組。除了保存所有的行,然後顯示矩陣舉例說明了如何確定矩陣中的行數和列數,及如何訪問矩陣的個別成員以外,下面的代碼和dump_members 中提取和顯示的循環作用是一樣的。
在確定矩陣的維數時,必須首先確定行數,因為無論這個矩陣是否為空,都可能計算列數。如果$rows 為0,則這個矩陣為空,並且$cols 也為0。否則,列數可能作為行數組中的元素數量來計算,用語法@{$matrix[$i]} 來整體訪問行$ i。
在前述的樣例中, 我們提取每一行, 然後保存對它的引用。可以設想調用fetchrow_arrayref( ) 而不是直接地檢索行引用可能更有效率:
它不能正常工作,因為fetchrow_arrayref( ) 重新使用了引用指向的數組。結果矩陣是一個引用的數組,數組中的每個元素都指向相同行—最後檢索的行。因此,如果想一次提取一行,則要使用fetchrow_array( ) 而不是fetchrow_arrayref( )。
另一個選擇是使用提取循環,可以使用返回整個結果集的DBI 方法中的一個。例如,fetchall_arrayref( ) 返回對引用數組的引用,數組的每個元素都指向結果集中某行。這非常簡單,但很有效,這個返回值是對矩陣的引用。要想使用fetchall_arrayref( ),則調用prepare( )和execute( ),然後如下檢索結果:
如果結果集為空,則fetchall_arrayref( ) 返回一個對空數組的引用。如果出現錯誤,則結果為un d e f,所以如果沒有啟用R a i s e E r r o r,則在開始使用它以前,要確保檢查返回值。
行數和列數由矩陣是否為空來確定。如果想作為一個數組訪問這個矩陣的整個行$ i,應該使用語法@ { $ m a t r i x _ r e f - > [ $ i ] }。
Perl 和MySQL都允許用單引號或雙引號引用字符串,所以混合使用引用字符有時可以避免這種無法引用引用字符自身的情況:
然而,在Perl 中,這兩種類型的引號並不等價。只有在雙引號內部才解釋為變量引用。因此,當想通過在查詢字符串中嵌入變量引用來構造查詢時,單引號並不是非常有用的。例如,如果$var 的值為14,則下面的兩個字符串並不等價:
兩個字符串的解釋如下所示;顯然,第一個字符串與希望傳遞給MySQL服務器的內容更為相像:
用雙引號來引用字符串的另一個選擇是使用QQ{} 結構,它告訴Perl 在‘q q {’和‘}’之間的每個字符都要看作為雙引號括起的字符串(兩個q 表示“雙引號”)。例如,下列兩行是等價的:
使用qq{} 時,構造查詢不用過多考慮引號的問題,因為可以在這個查詢字符串內自由地使用引號(單引號或雙引號),而不用避開它們。此外,還解釋了變量引用。QQ{} 的這兩種特性可用下面的INSERT 語句來說明:
不一定使用‘ {’和‘ }’作為qq 的分隔符。其他格式,如qq( ) 和q q / /,也可以使用,只要封閉的分隔符不出現在字符串內即可。我喜歡用q q { },因為‘ {’不像‘)’或‘/’會出現在查詢的文本內,並且在查詢字符串的結尾也可能有問題。例如,‘)’出現在所顯示的INSERT 語句的內部,所以QQ( ) 對於引用查詢字符串來說不是一個有用的結構。
請注意,在查詢字符串中引用$last 和$first 時,不要增加括起來的引號; quote( ) 方法支持它們。如果增加了引號,則查詢將出現過多的引號,如下面的例子所示:
這些語句產生下面的輸出:
占位符和參數約束
在前面各節中,我們通過把要插入或選擇的值作為選擇標准,直接放在查詢字符串中構造了查詢。不一定非要這樣做。DBI允許在查詢字符串內部放置一些稱為占位符的特殊標記符,然後,在執行該查詢時,將這些值代替那些標識符來使用。這樣做的主要原因是提高性能,特別是在循環中反復執行某個查詢的時候。
為了說明占位符如何工作,舉例說明。假設學校新學期剛開始,打算清理學分薄的student 表,然後利用包含在文件中的一列學生姓名將其初始化,使其包含新學生。不用占位符,可以如下這樣刪除現有表的內容,並裝入新的姓名:
這樣做效率很低,因為INSERT 查詢的基本格式每次都是相同的,並且在整個循環中,do( ) 每次都調用prepare( ) 和execute( )。在進入這個循環以前,只調用一次prepare( ) 來設置INSERT 語句,並且在這個循環內部只調用execute( ),這樣做效率更高一些。只調用一次prepare( ),可避免其他多次調用。DBI 允許我們這樣做:
請注意這個INSERT 查詢中的‘ ?’就是一個占位符。調用execute( ) 時,將查詢發送給服務器,傳遞這個值來代替占位符。一般來說,如果發現在循環內部調用了do( ),應該在循環前調用prepare( ),並在這個循環內部調用execute( ) 更好一些。
有關占位符的一些注意事項:
bind_col( ) 的每個調用都應該指定一個列號和一個希望與該列相聯的變量的引用。列號從1開始。bind_col( ) 應該在execute( ) 之後調用。
$ENV{HOME} 含有用戶運行這個腳本的主目錄的路徑名,所以這個腳本使用的主機名、用戶名和口令將會從每個用戶自己的選項文件中抽取出來。以這種方式編寫腳本,不必在這個腳本中逐字地嵌入連接參數。
還可以使用MySQL_read_default_group 選項,來指定一個選項文件組。這自動地導致讀取用戶的.my.cnf 文件,並且除了[clIEnt] 組以外,還允許讀取一個指定的選項組。例如,如果在DBI 腳本中具有指定的選項,則可以將它們列在[dbi] 組中,然後以如下方式使用數據源值:
mysql_read_default_file 和mysql_read_default_group 需要MySQL3.22.10 或更新的版本,以及DBD::mysql1.21.06 或更新的版本。有關指定的數據源字符串的選項的詳細信息,請參閱附錄G。有關MySQL選項文件格式的詳細信息,請參閱附錄E。
使用選項文件並不防礙在connect( ) 調用中指定連接參數(例如,如果想這個腳本作為特殊的用戶來連接)。在connect( ) 調用中指定的任何明確的主機名、用戶名和口令值都將覆蓋在選項文件中找到的連接參數。例如,想要腳本從命令行中分析- - host、--user 和--passWord 選項,並使用那些值,如果給定,則優先於在選項文件中發現的任何內容。這是有用的,因為它是標准的MySQL客戶機操作的方式。DBI 腳本將因此符合它的行為。
對於在本章中我們開發的保留在命令行中的腳本,我將使用一些標准的連接設置代碼及卸載代碼。我只在這裡說明它一次,以便我們可以將精力集中在每個腳本的主體上,我們編寫如下代碼:
我們腳本的最後部分也類似於從腳本到腳本;它簡單地終止這個連接並退出:
不幸的是,當做這些的時候,使用顯示語句不能看到完整查詢的樣子,因為直到調用d o ( )才能估計占位符的值。當使用占位符時,跟蹤可能對調試方法更有幫助。
2. 使用跟蹤調試
當試圖查出腳本不能正確工作的原因時,可以告知DBI 來生成跟蹤(調試)信息。跟蹤級別范圍從0(關閉)到9(最多信息)。一般來說,跟蹤級別1和2 是最有用的。級別2 跟蹤說明正在執行的查詢文本(包括占位符替換的結果)、調用quote( ) 的結果等等。這可能對捕獲問題有極大的幫助。
使用trace( ) 方法,可以從獨立的腳本內部控制跟蹤,或者可以設置DBI_TRACE 環境變量來影響所運行的所有DBI 腳本的跟蹤。
要想使用trace( ) 調用,則傳遞一個跟蹤級別參數,並可以有選擇地再傳遞一個文件名。如果沒有指定文件名,則所有的跟蹤輸出到STDERR 中;否則,它就轉到這個命名的文件中。一些樣例如下:
當調用DBI->trace( ) 時,跟蹤所有的DBI 操作。一個更精細的方法是,可以用獨立的處理級別啟用跟蹤。當沒想好腳本中問題的位置,並對在那點出現的每件事的跟蹤輸出不想插手時,這是有幫助的。例如,如果特定的SELECT 查詢有問題,則可以跟蹤與這個查詢相關的語句句柄:
如果對任何trace( ) 調用指定一個文件名參數,則無論對DBI 作為整體還是單獨的句柄,所有的跟蹤輸出都要到那個文件中。
要想對運行的所有DBI 腳本全部都打開跟蹤,則從命令解釋程序中設置DBI_TRACE 環境變量。它的語法取決於使用的命令解釋程序:
value 的模式和所有命令解釋程序的模式一樣:數字n表示在級別n打開跟蹤到S T D E R R中;文件名打開級別2 跟蹤到這個命名的文件,或n=file_name 打開級別n跟蹤到這個命名的文件中。下面的樣例使用了csh 語法:
如果打開跟蹤到命令解釋程序中的文件,則確保一旦解決了這個問題,就將它關閉。將調試輸出增加到這個跟蹤文件中,而不用重寫它,所以如果不小心,則這個文件可能變得非常大。極其不好的想法是在命令解釋程序的啟動文件(如.cshrc、.lonin 或. p r o f i l e)中定義DBI _ T R A C E!在UNIX 下,可以使用下面兩個命令( csh 語法)之一關閉跟蹤:
% setenv DBI_TRACE 0
% unsetenv DBI_TRACE
對於s h、ksh 或b a s h,這樣做:
$ DBI_TRACE=0
$export DBI_TRACE
在Windows 操作系統中,可以使用下面兩個命令之一關閉跟蹤:
c:\>unset DBI_TRACE
c:\>set DBI_TRACE=0
使用結果集元數據
可以使用DBI 來獲得訪問結果集元數據——也就是有關由查詢選擇行的描述信息。訪問與結果集生成的查詢所相關的語句句柄的屬性來獲得這個信息。提供這些屬性中有一些是作為可用於橫跨所有數據庫驅動程序的標准DBI 屬性(如N U M _ O F _ F I E L D S,結果集中列的數量)。另外一些是MySQL特定的,由DBD::mysql所提供的DBI 的MySQL驅動程序。這些屬性,如mysql_max_length 告知了每列值的最大寬度,不能用於其他數據庫引擎。要想使用任何MySQL特定的屬性,都必須冒著使腳本不可移植到其他數據庫的危險。另一方面,它們可以使它更容易地獲得想要的信息。
必須在適當時候請求元數據。一般來說,直到調用prepare( ) 和execute( ) 之後,結果集屬性才能用於SELECT 語句。除此之外,在調用finish( ) 之後,屬性可能變為無效。
文5.com (andyyoo) [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24]
讓我們來看看如何使用MySQL的一個元數據屬性mysql_ m a x _ l e n g t h,與保留查詢列名的DBI 級別的NAME 屬性一起使用。我們可以將這些屬性提供的信息合並起來,編寫一個腳本b o x _ o ut,它以交互模式運行MySQL客戶機程序時獲得的相同邊框風格,從SELECT 查詢產生輸出。box_out 的主體如下(可以用任何其他的語句替換SELECT 語句;編寫輸出的例程獨立於特定的查詢):
用execute( ) 將這個查詢初始化之後,我們獲得了所需的元數據。$sth->{NAME} 和$ s t h ->{MySQL_max_length} 給出了列名和每列值的最大寬度。為了在這個查詢中為列命名,每個屬性值都引用了一個數組,這個數組含有結果集每列中的一個值。
剩余的計算非常類似於在第6章中開發的客戶機程序5中所使用的那些內容。例如,為避免偏離輸出,如果列的名比該列中任何數據值都寬,則我們要向上調整列的寬度值。
輸出函數print_dashes( ) 和print_row( ) 代碼編寫如下,它們也類似於客戶機程序5中相應的代碼:
box_out 的輸出如下:
我們的下一個腳本使用了列元數據來產生不同格式的輸出。這個腳本s h o w _ member,允許快速浏覽歷史同盟成員項目,而不用輸入任何查詢。給出成員的姓,它就這樣顯示所選擇的項目:
使用成員資格號碼,或者使用與若干姓相匹配的模式也可以調用s h o w _ member s。下面的命令說明成員號碼為2 3的項目,和以字母“C”開始的姓的成員項:
show_member 腳本的主體如下所示。它使用了NAME 屬性來確定輸出的每行所使用的標號和NUM_OF_FIELDS 屬性,找出這個結果集含有的列數:
無論區域是什麼, show_member 的目的都是說明一個項目的全部內容。通過使用SELECT * 來檢索所有的列和NAME 屬性來看看它們是什麼,即使從member 表中增加或刪除列,這個腳本也會工作而不用做修改。
如果不檢索任何行就想知道一個表含有哪些列,則可以發布下面這條查詢:
SELECT * FROM tbl_name WHERE 1=0
以正常方式調用prepare( ) 和execute( ) 之後,可以從@{$sth->{NAME}} 中得到列名。然而,請注意,盡管使用“空”查詢的這個小竅門可以在MySQL下運行,但是它不可移植,而且並不是對所有的數據庫引擎都可以工作的。
有關DBI 和DBD::mysql所提供屬性的詳細信息,請參見附錄G。它完全可以使您確定是想通過避免MySQL特定的屬性而為可移植性花費努力,還是在可移植性的開銷方面利用它們。