[LinuxFocus-icon]
<--  | Home  | Map  | Index  | Search

News | Archives | Links | About LF
This document is available in: English  Castellano  ChineseGB  Deutsch  Francais  Nederlands  Russian  Turkce  

[Photo of the Author]
by Diego Alberto Arias Prad
<dariapra(at)yahoo.es>

About the author:

我是西班牙Lugo电信工程师。我不记得我开始使用Linux的准确时间,大概是1995或1996年吧。之前我是Microsoft Windows用户,我甚至不知道Linux的存在。当我第一次在大学里看到运行Linux的计算机时就被吸引了。我立即在家中的计算机中安装了它,我记得我的第一个Linux发行版是Slackware。

在这些年里,多种Linux发行版与BSD变体都带给我很多的快乐,我使用象是Java或者Tcl这类编程语言,操作数据库,web与应用服务器...对我来说Linux不只是娱乐,我在 Telefónica I+D的工作中也同样有机会使用Linux。


Content:

 

TclMySQL入门

MySQLTcl

Abstract:

在文章中你将学习如何安装与使用MySQLTcl,它是一个可以利用Tcl脚本对MySQL数据库服务器进行SQL查询(select,insert,deltet...等操作)的Tcl库。文章中Tcl、MySQL服务器与MySQLTcl库的版本分别为 8.4.2, 4.0.15 和 2.40.

Tcl 是“ Tool Command Language”的缩写,它是 John Ousterhout [1]的作品。 Tcl实际上由两部分组成,一个脚本语言和一个翻译器。Tcl是结构化编程语言,使用三种基本数据结构:字符串(strings),链( lists) 和数组(arrays)。Tcl的特性包括正则表达式,第三方Tcl扩展库,和Tk(Tcl中用来写图形界面程序的工具包)。

MySQL 是开源社区中非常流行的数据库服务器,我认为不需要再对它进行更多的解释了。

MySQLTcl 是一个允许使用Tcl脚本对MySQL数据库进行查询的Tcl库。当前这个库的作者与维护者是:Paolo Brutti (Paolo.Bruti at tlsoft.it), Tobias Ritzau (tobri at ida.liu.se) 与 Artur Trzewick (mail at xdobry.de).

_________________ _________________ _________________

 

安装MySQLTcl

如果你的Linux发行版或*BSD系统支持包(如RPM或DEB)或ports(比如Crux LinuxFreeBSD,)安装方式,你可以使用包或ports系统来安装 MySQLTcl 并跳过这一节的内容。

如果你不能使用上述方式或者你更喜欢手工安装,我将在下面给出我的安装步骤。不过这只是基本指导方针而不是手把手的安装手册。在Mandrake发行版中(9.2版),使用如下bash命令:
$ ./configure --with-mysql-lib=/usr/lib
$ make
$ make install
如果在执行 "configure"时出现一些错误,错误信息会给出一个解决问题的建议。 问题通常是由于configure脚本无法找到某些目录或文件而引起的。对于这种情况,你可以在执行时将所缺文件或目录的位置通过参数告诉脚本。让我们来看看另一个例子。在使用FreeBSD5.0时,我使用这些选项来安装MySQLTcl: 
$ export CPP=/usr/bin/cpp
$ ./configure --with-tcl=/usr/lib/local/tcl8.3
 --with-tclinclude=/usr/local/include/tcl8.3
 --with-mysql-include=/usr/local/include/mysql
 --with-mysql-lib=/usr/local/lib/mysql
$ make
$ make install
你一定要注意,在第二个例子中Tcl的版本是8.3,而MySQLTcl与MySQL的版本分别是2.15与3.23.54。

 

Tcl 基础

这一节中我会向对本文有兴趣但并不了解Tcl的读者简要的介绍一些Tcl的基础知识。如果你已经是一名Tcl程序员,你可以跳过此节。

你可以复用这小节(以及其后的)中展示的Tcl shell(tclsh)例子。

 

变量,命令与变量置换。

Tcl 使用命令set来建立变量。请看下面的例子:
% set address {Edison Avenue, 83}
Edison Avenue, 83
% set zip_code 48631
48631
这两个例子中,我们定义了两个名字为address与zip_code的变量,分别包含两个字符串值 Edison Avenue, 83 与 48361。注意在定义address变量时使用了括号,这是因为它包含的字符串中有空格。使用命令set也同样可以得到变量的值,如下:

% set address
Edison Avenue, 83
% set zip_code
48631
假设我们想将变量address的值打印到屏幕上,可以使用puts命令:
% puts stdout [set address]
Edison Avenue, 83
我们向命令puts传递了参数 stdout。 这个参数告诉puts在标准输入上打印,在这里指的是屏幕。传递给puts的第二个参数是  [set address]。方括号告诉Tcl解释器,括号内是另一条Tcl命令,它必须在puts命令之前被Tcl解释器执行 ,这叫做命令置换。还可以用另一种方法来完成相同的工作:
% puts stdout $address
Edison Avenue, 83
这个例子里我们所做的叫做变量置换:变量名前的字符 $ 表示要进行变量置换。

在早先的例子中,我们知道可以使用圆括号将多个被空格隔开的单词组合成一个字符串,其实还有另一种方式来组合它们,就是使用双引号(“)。不过这两种组合方式的含义并不完全相同,让我们看一个例子:
% puts stdout "the zip code is [set address]"
the zip code is 48631
% puts stdout "the zip code is $address"
the zip code is 48631
% puts stdout {the zip code is [set address]}
the zip code is [set address]
% puts stdout {the zip code is $address}
the zip code is $address
通过例子我们可以看到,使用圆括号进行组合,不会发生命令与变量置换,但使用双引号时它们将会产生作用。
使用unset命令来删除变量:
% unset address
% set address
can't read "address": no such variable
% unset zip_code
% set zip_code
can't read "zip_code": no such variable

 

Tcl 字符串

字符串是Tcl三种基本数据结构之一。一个字符串是一些字符的集合。使用set命令能够建立字符串。

% set surname Westmoreland
Westmoreland
% set number 46.625
46.625
变量 surnamenumber都是字符串。 字符串可以使用 string 命令来操作。  string 命令的一般语法为:string 操作 字符串值 其它参数。 让我们通过几个例子来了解这个命令是如何使用的:
% string length $surname
12
% set surname [string range $surname 0 3]
West
% puts stdout $surname
West
% string tolower $surname
west
与 Java 或 Pascal不同, Tcl 不是一个强类型编程语言,这一点从下面的例子可以看出来:
% set number [expr $number + 24.5]
70.125
% string range $number 2 5
.125
通过命令 expr,变量number 的值增加了 24.5。之后使用string命令将变量number当作字符串进行处理,以显示它最后的四个字符。

还有比上述例子中所展示的更多的字符串操作。

 

Tcl 链

Tcl 链是一种将元素通过空格分开并有特别的解释特殊字符串(string)。

% set friends_list {Fany John Lisa Jack Michael}
Fany John Lisa Jack Michael
% set friends_list [string tolower $friends_list]
fany john lisa jack michael
% set friends_list
fany john lisa jack michael
有几个Tcl命令用于链的操作。下面是几个例子:
% lindex 2 $friends_list
lisa
% lrange $friends_list 2 4
lisa jack michael
% set friends_list [lsort -ascii $friends_list]
fany jack john lisa michael
% set friends_list
fany jack john lisa michael
% set friends_list [linsert $friends_list 2 Peter]
fany jack Peter john lisa michael
% string toupper $friends_list
FANY JACK PETER JOHN LISA MICHAEL
从最后一个例子可以看出链与字符串实际上是相同的数据结构。

 

Tcl 数组

数组可以看作一个用字符串值作索引的链。数组可象下面的例子那样被创建:

% set phone_numbers(fany) 629
629
% set phone_numbers(michael) 513
513
% set phone_numbers(john) 286
286
数组的值可以使用set命令与变量置换来得到。同上面的例子一样,字符串索引是用括号标识的:
% set $phone_numers(michael)
513
命令 array 返回数组变量的相关信息。让我们通过一些例子来看看这个命令能作些什么:
% array size phone_numbers
3
% array names phone_numbers
fany john michael

 

联接数据库

在使用Tcl脚本对数据库进行任何查询之前,必须与数据库服务器建立联接。这一小节中我们将学习如何联接以及如何处理在尝试联接数据库服务器时出现的错误。

 

建立数组库联接 

看看下面这个用于联接MySQL数据库的Tcl脚本:

0:  #!/usr/bin/tclsh8.4
1:
2:  package require mysqltcl
3:  global mysqlstatus
4:
5:  set port {3306}
6:  set host {127.0.0.1}
7:  set user {john_smith}
8:  set password {jsmith_password}
9:
10: set mysql_handler [mysqlconnect -host $host
    -port $port -user $user -password $password]
11:
12: mysqlclose $mysql_handler
请注意,左边那一排数字与冒号并不是Tcl脚本的内容,只是为了方便解释所标识的行号。同样要注意,根据你所使用的Linux版本,你可能要将第0行更改为正确的Tcl shell路径。

第0行告诉shell这个文件是一个Tcl脚本以及在哪可以找到Tcl解释器。
 第2行告诉Tcl解释器在执行脚本命令时去MySQLTcl库中进行查找。例如在第10行中我们看到命令 mysqlconnect, 如果脚本中没有包含第2行,在解释器执行mysqlconnect 时会抱怨不能找到命令。 .

第5与第6行中的port 和 host 是Tcl脚本准备联接的端口与主机。在脚本中端口号(port)是3306 (这是MySQL服务器侦听的默认端口),主机(host)与执行Tcl脚本的是同一部机器。

第7与第8行设置的是数据库用户与密码。
在第10行开始真正建立起与数据库的联接。  mysqlconnect 命令的输出保存在变量 mysql_handler中。这个变量将是数据库联接的句柄。这个句柄用于数据库查询,当然关闭数据库联接时也使用它,这就是第12行所作的。 

 

错误处理

在上一节中脚本的第3行还没有解释。这是我们现在要作的。

MySQLTcl 库中的命令可能会产生错误。如果一个错误没有被捕获,脚本将中断,这个结果可能会引起我们的注意也可能不会。让我们用下面的方法来更改原先的脚本:

10: if [catch {mysqlconnect -host $host -port $port
    -user $user -password $password} mysql_handler] {
11:     puts stderr {error, the database connection could not be established}
12:     exit
13: } else {
14:     mysqlclose mysql_handler
15: }
如果命令 set mysql_handler [mysqlconnect -host $host... 产生一个错误,错误将被命令catch捕获。如果在执行花括号内的命令时出现错误catch将返回1,反之则返回0。变量 mysql_handler 用来保存花括号内命令执行的结果。
如果出现了错误,将会在标准错误输出(stderr)上打印信息,在这里指的是屏幕。在与数据库建立联接时有多种情况会引发错误:错误的密码,不正确的主机或端口号等等,因此,在这里给出更详细的信息要比“那是一个错误”这类的简单信息更好。

在第3行, 变量 mysqlstatus 声明为全局变量。全局变量可以在Tcl脚本的任何位置使用。这涉及到Tcl的变量作用域,这已经超出了本文的介绍范围。库MySQLTcl创建与维护一个名为mysqlstatus的全局数组。这个数组包含下列元素:
element meaning
code 如果没有错误发生 mysqlstatus(code) 等于0;否则设置为MySQL错误代码。如果错误不是由MySQL服务器引起的,   mysqlstatus(code)设置为 -1。

 任何MySQLTcl库中的命令执行后 mysqlstatus(code) 的值都会更新。
command 最后执行的MySQLTcl 库命令引发的错误保存在  mysqlstatus(command)中

  mysqlstatus(command) 是在MySQLTcl库命令执行失败时才更新,因此如果 MySQLTcl命令都成功执行它将不会更新。
message  mysqltcl(message) 的值在任何MySQLTcl命令执行失败后被更新为包含错误信息的字符串。与mysqlstatus(command)一样如果 MySQLTcl命令都成功执行它将不会更新

全局数组mysqlstatus 中还有一个与错误处理无关的元素。 :

element meaning
nullvalue 用于表示一个SQL查询结果为空的情况。 musqlstatus(nullvalue) 可以被设置为任何字符串,默认为一空字符串。

因此利用全局数组 mysqlstatus  ,可以重写早先的代码,使它在建立与数据库的联接时一旦发生错误能给出更详细信息。
10: catch {mysqlconnect -host $host -port $port
    -user $user -password $password} mysql_handler
11: if {$mysqltatus(code) != 0} {
12:     puts stderr $mysqlstatus(message)
13: } else {
14:     mysqlclose mysql_handler
15: }
很明显全局数组能够处理除了在建立数据库联接时引发的错误之外更多的错误。

 

基本的 MySQLTcl 库命令

这一节中将介绍大多数MySQLTcl中的基本命令,我还将通过一些例子来展示如何使用它们。更完整的内容,请参考MySQLTcl库man页。
下面的表中列出了这一节中要介绍的命令。参数用下划线标出。如果参数在两个?号之间,表示它是可选的,字符|表示“或”。

command short description
mysqlconnect ?option value ...? 联接到一个数据库;将返回一个其它mysqltcl命令必须使用的联接句柄。
mysqluse handle dbname 将一个MySQL句柄与指定的数据库相关联。
mysqsel handle sql_statement ?-list | -flatlist? 发送SQL select语句到数据库。
mysqlexec handle sql_statement 发送除了select 之外的SQL语句到数据库。
mysqlclose handle 关闭一个数据库联接。

 

mysqlconnect

这个命令已经在 "建立数据库联接"一节中讨论过了。不过有一个额外的参数在前面没有说到:-db。使用参数 -db,可以直接指定随后的SQL语句所使用的数据库。看下面的例子:

% set mysql_handler [mysqlconnect -h 127.0.0.1 -p 3306 \\
  -user john_smith -password jsmith_password -db jsmith_database]
数据库句柄  mysql_handler 将名为jsmith_database的数据库指定为MySQLTcl命令的目标数据库。

(请注意字符 \\不是命令的一部分,它表示命令在一下行继续)

 

mysqluse

这个命令将改变由第一个参数给出的MySQL句柄所关联的数据库。

 

mysqlsel

这个命令发送 SQL select语句到由MySQL句柄所关联的数据库。如果参数  sql_statement 不是一个SQL 选择语句将会引发错误。
第三个参数可以是  list 或 flat_list。让我们通过一个例子来看看这个参数对命令的输出会产生什么样的影响。假设MySQL句柄所关联的数据库中有一个名为people的表,内容如下:

id first_name last_ name phone
26 Karl Bauer 8245
47 James Brooks 1093
61 Roberto Castro Portela 6507

我们使用 mysqlsel 发送SQL选择语句到数据库:

% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc} -list
{Karl Bauer} {James Brooks} {Roberto {Castro Portela}}
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc} -flatlist
Karl Bauer James Brooks Roberto {Castro Portela}
在第一句中 (使用参数-list), 命令返回的链中全部元素也都是独立的链。而第二句 (使用参数-flatlist),命令返回一个单一的链全部元素都是互相联接的。
如果mysqlsel 不使用第三个参数会发生什么呢?这种情况中,命令的输出是通过查询返回的行数:
% mysqlsel $mysql_handler {select first_name, last_name from people order by id asc}
3
 

mysqlexec

 mysqlexec 命令发送非选择 SQL语句到由MySQL名柄所关联的数据库。如果参数  sql_statement 是一个选择语句,并不会产生一个错误,但它不作任何事。

看我们看看上一段中显示的例子:

% mysqlexec $mysql_handler {delete from people where id=26}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 1093} {Roberto {Castro Portela} 6507}
% mysqlexec $mysql_handler \\
  {insert into people (id, first_name, last_name, phone) values (58, "Carla", "di Bella", 8925)}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 1093} {Carla {di Bella} 8925} {Roberto {Castro Portela} 6507}
当然,除了delete与insert之外的SQL命令也可以使用这个命令发送到数据库。比如,更新(update):
% mysqlexec $mysql_handler {update people set phone=3749 where first_name="James"}
1
% mysqlsel $mysql_handler {select first_name, last_name, phone from people order by id asc} -list
{James Brooks 3749} {Carla {di Bella} 8925} {Roberto {Castro Portela} 6507}
 mysqlexec 如果执行成功则返回被发送到数据库的非选择SQL语句所影响的行数。

 

mysqlclose

就象之前看到的,命令 mysqlclose 用来关闭与数据库的联接。这个命令的参数是一个MySQL句柄,它指向与我们想关闭的数据库。

 

其它 MySQLTcl 库命令

 MySQLTcl 库 除了这一节所展示的五个命令之外还有更多的命令。使用它们可以检索数据库的相关信息,转义字符串以适应它们的查询,进行嵌套查询等等。 MySQLTcl的man页是一个很好的参考,它是MySQLTcl库安装的一部分。

 

参考

[1] a slightly skeptical view on John K. Ousterhout and Tcl:
http://www.softpanorama.org/People/Ousterhout/index.shtml

[2] Tcl 正则表达式教程
http://www.mapfree.com/sbf/tcl/book/select/Html/7.html

TclTutor是一个自由的可交互式学习Tcl的程序:
http://www.msen.com/~clif/TclTutor.html

MySQL 文档,有多种格式 (HTML, PDF...):
http://www.mysql.com/documentation/index.html

 

Talkback form for this article

Every article has its own talkback page. On this page you can submit a comment or look at comments from other readers:
 talkback page 

<--, back to the index of this issue

Webpages maintained by the LinuxFocus Editor team
© Diego Alberto Arias Prad, FDL
LinuxFocus.org
Translation information:
en --> -- : Diego Alberto Arias Prad <dariapra(at)yahoo.es>
en --> zh: 郭晓龙 <gxl117(at)yahoo.com.cn>

2004-03-08, generated by lfparser version 2.46