Mysql入门系列:Perl DBI基础(1)

ldldabcd

ldldabcd

2016-02-19 15:23

最近很多朋友喜欢上设计,但是大家却不知道如何去做,别担心有图老师给你解答,史上最全最棒的详细解说让你一看就懂。

  本节提供DBI 的背景信息在编写自己的脚本和支持其他人编写的脚本时,需要这些信息。如果已经熟悉DBI,则可以略过这节,直接跳到7 . 3节运行DBI。

  DBI 数据类型

  从某些方面来说,使用Perl DBI API 类似于使用第6章介绍的C 客户机库。在使用C 客户机库时,主要依靠指向结构或数组的指针来调用函数和访问与MySQL相关的数据。在使用DBI API 时,除了函数称为方法,指针称为引用外,也调用函数和使用指向结构的指针。

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)

  指针变量称为句柄,句柄指向的结构称为对象。

  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 如下:

  

  

  要想自己试验这个脚本,可以下载它(请参阅符录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 来访问,则在运行这个脚本时,将获得下面的消息:

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)

  Global symbol "$mv_var" requires explicit package name at line n

  这个消息会使您想,怎么了?$ m v _ v a r?我从未使用过这种名称的变量!,然后,找到脚本中的第n行,看是什么问题,并改正它。如果不用严格模式, Perl 不会给出$ m v _ v a r;将只是简单地按具有un d e f(未定义的)值的该名称创建一个新的变量,并毫无动静地使用它,然后,您会莫名其妙脚本为什么不工作。

  因为我们在严格模式下操作,所以我们将定义脚本使用的变量:

  

  现在我们准备连接数据库:

  

  connect( ) 调用作为DBI-connect( ) 来调用,因为它是DBI 类的方法。不必真正知道它是什么意思;它只是一个使人头痛的面向对象的行话(如果的确想知道,那么它意味着connect( ) 是属于DBI 的一个函数)。connect( ) 有若干参数:

  数据源。(经常调用的数据源名称,或D S N。)数据源格式由要使用的特定DBD 模块需求来确定。对于MySQL驱动程序,允许的格式如下:

  "DBI:mysql:db_name"

  "DBI:mysql:db_name:host_name"

  对于第一种格式,主机名缺省为localhost(实际上有其他允许的数据源格式,我们将在后面7 . 2 . 8节指定连接参数中讨论)。DBI大写没关系,但是 mysql必须小写。

  用户名和口令。

  表示额外连接属性的可选参数。这个参数控制DBI 的错误处理行为,我们指定的看起来有点奇怪的构造启用了RaiseError 属性。这导致DBI 检查与数据库相关的错误,并显示消息,而且只要它检测到错误就退出(这就是为什么在dump_members 脚本中的任何地方都没有看到错误检查代码的原因; DBI 将它全部处理了)。7 . 2 . 3节处理错误包括了对错误响应的可选方法。

  如果connect( ) 调用成功,则它返回数据库句柄,我们分配给$dbh(如果connect( ) 失败,通常返回un d e f。然而,因为我们在脚本中启用了R a i s e E r r o r,所以connect( )不返回;但是,DBI 将显示一条错误消息,并且在出现错误时退出)。

  连接到数据库后, dump_members 发布一条SELECT 语句查询来检索全体成员列表,然后,执行一个循环来处理返回的每一行。这些行构成了结果集。

  为了完成S E L E C T语句,首先需要准备,然后再运行它:

  # issue query

  $sth=$dbh-prepare("SELECT last_name,first_name,suffix,email,"

  "street,city,state,zip,phone FROM member ORDER BY last_name");

  $sth-execute();

  利用数据库句柄调用prepare( );在执行前,它将SQL 语句传递给预处理的驱动程序。实际上,在这里某些驱动程序做了一些有关这条语句的事情。其他驱动程序只是记住它,直到调用execute( ) 使这条语句被执行为止。从prepare( ) 返回的值是一个语句句柄$ s t h,如果出现错误,则为un d e f。在进一步处理与这条语句相关的所有内容时,都使用这个语句句柄。

  请注意,指定的这个查询没有分号结束符。您无疑有这样的(经过长时间使用mysql程序养成的)习惯,用‘ ;’字符终止SQL 语句。然而,在使用DBI时,最好打破这个习惯,因为分号经常导致查询出现语法错误而失败。向查询增加‘ g’也类似,使用DBI 时不要这样。

  在调用一个方法而不用向它传递任何参数时,可以没有这个圆括号。下列两个调用是等价的:

  $sth-execute();

  $sth-execute;

  我宁愿有圆括号,因为它使人感到这个调用看上去不像变量。您的选择就可能不同了。

  调用execute( ) 后,可以处理成员列表的行。在dump_members 脚本中,提取行的循环简单地显示了每行的内容:

  

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

  到目前为止,这是最容易的方法,并且是dump_members 带来的。如果在脚本退出时,想要执行某种类型的清除代码,启用RaiseError 可能是不恰当的,尽管在这种情况下,可以重新定义$SIG{_DIE_} 句柄,可以做想做的事情。

  避免启用RaiseError 属性的另一个原因是DBI 在它的消息中显示技术信息,如下:

  disconnect(DBI::db=HASH(0x197aae4)invalidates 1active statement.Either

  destroy statement handles or call finish on them before disconnecting.

  对于编程者来说,这是好的信息,但对普通用户可能没有什么意义。在此情形,最好自己检查错误,以便可以显示对期望使用这个脚本的人更有意义的消息。或者也可在这里考虑重新定义$SIG{_DIE_} 句柄。这样可能很有用,因为它允许启用RaiseError 来使错误处理简单化,而不是用自己的消息替换DBI 给出的缺省错误消息。为了提供自己的_DIE_ 句柄,可在执行任何DBI 调用以前,进行下面的工作:

  $SIG{_DIE_}=sub{die "Sorry,an error occurred";};

  也可以用普通的风格定义一个子例程,并利用这个子例程的引用来设置这个句柄值:

  

  除了在connect( ) 调用中逐字传递错误处理属性之外,还可以利用散列定义它们,并传递对这个散列的引用。有人发现以这种方式准备属性设置使脚本更容易阅读和编辑,但是在功能上这两种方法是相同的。下面是一个说明如何使用属性散列的样例:

展开更多 50%)
分享

猜你喜欢

Mysql入门系列:Perl DBI基础(1)

编程语言 网络编程
Mysql入门系列:Perl DBI基础(1)

Mysql入门系列:优化MYSQL

编程语言 网络编程
Mysql入门系列:优化MYSQL

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Mysql入门系列:检索MYSQL记录

编程语言 网络编程
Mysql入门系列:检索MYSQL记录

Mysql入门系列:使用MYSQL索引

编程语言 网络编程
Mysql入门系列:使用MYSQL索引

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Mysql入门系列:MySQL查询优化程序

编程语言 网络编程
Mysql入门系列:MySQL查询优化程序

Mysql入门系列:MYSQL用户帐号管理

编程语言 网络编程
Mysql入门系列:MYSQL用户帐号管理

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Visual C#中用WMI获取远程计算机信息

Visual C#中用WMI获取远程计算机信息

范二青年 一直都是半傻半疯 - QQ图案分组

范二青年 一直都是半傻半疯 - QQ图案分组
下拉加载更多内容 ↓