2011年6月1日星期三

如何用 Perl 来展示数据库的表结构

如何用 Perl 来展示数据库的表结构

有两个小工具是必不可少的,第一个就是导出数据用的脚本,这里命名为 emp。它能在本地主机上的 employees 数据库上执行任何的 SQL,并且把输出导出成为 tab 分隔的纯文本。

$ cat bin/emp
#!/bin/sh
perl -le 'use DBI; ($s=($d=DBI->connect(q(dbi:mysql:database=employees),q(emp),q()))->prepare_cached(join qq(),<STDIN>))->execute(@ARGV); $,=qq(\t); print STDERR @{$s->{NAME}}; print @r while @r=$s->fetchrow_array; $d->disconnect' $*

测试一下这个小工具:

$ echo 'select user()' | emp
user()
emp@localhost

注意,输出虽然有两行,但是第一行是标准出错(STDERR),是用来显示字段名的。真正的数据只有一行。

所以,可以这样来导出表结构:

$ echo 'desc employees' | emp > employees.desc
Field   Type    Null    Key     Default Extra

因为转向的只是标准输出,所以这里的字段名没有被转向到 employees.desc 文件中,而是直接显示在屏幕上了。

另外一个小工具是用来进行行转列的,这里把它先实现为一个 bash 函数。

$ row2col() { perl -MList::MoreUtils=each_arrayref -F\\t -lane 'END{ $ea=each_arrayref(@lines); print join qq(\t), @x while @x=$ea->()} push @lines, [@F]'; }

测试一下:

jjiang@flatpan:~$ echo -e '1\t2' | row2col
1
2

它工作了!

现在导出一行样本数据:

$ echo 'select * from employees limit 1' | emp | row2col
emp_no  birth_date      first_name      last_name       gender  hire_date
10001
1953-09-02
Geogri
Facello
M
1986-06-26

而且这一列数据,恰好能够和刚才的表结构合并!所以,我们先把它存入文件 employees.data。

$ echo 'select * from employees limit 1' | emp | row2col > employees.data
emp_no  birth_date      first_name      last_name       gender  hire_date

然后就是最后一个出场的小工具 merge-tab 了:

$ cat bin/merge-tab
#!/usr/bin/perl
use IO::File;
@f= map { IO::File->new($_) } @ARGV;
print $q,qq(\n) until ($q=join (qq(\t), map { m{(.*)} && $1 } map { $_->getline } @f))=~m{^\t+$}

这样,我们就可以做到需要的效果了:

$ merge-tab employees.desc employees.data
emp_no  int(11) NO      PRI                     10001
birth_date      date    NO                              1953-09-02
first_name      varchar(14)     YES                             Geogri
last_name       varchar(16)     YES                             Facello
gender  enum('M','F')   NO                              M
hire_date       date    NO                              1986-06-26

Posted via email from purl's posterous

没有评论: