动态脚本语言下的数据库
我有一堆 .csv 文件想要处理。用 SQL 查询来处理这些文件会简单很多。我在想有没有办法用像 Python 或 Ruby 这样的脚本语言来加载 .csv 文件,然后用 SQL 语言来查询它。如果能像使用 ActiveRecord 那样加载就太好了。
问题是,我不想在运行我的脚本之前还要在某个地方运行一个数据库。我希望只需要在脚本语言和一些模块之外,不需要额外的安装。
我想知道应该用什么语言和模块来完成这个任务。我查了一圈,没找到合适的东西。这样做真的可能吗?
8 个回答
4
你有没有看过Perl语言,还有Text::CSV和DBI这两个模块?在CPAN上有很多模块可以专门用来处理这些事情。这里有一个例子(来自这里):
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
# Connect to the database, (the directory containing our csv file(s))
my $dbh = DBI->connect("DBI:CSV:f_dir=.;csv_eol=\n;");
# Associate our csv file with the table name 'prospects'
$dbh->{'csv_tables'}->{'prospects'} = { 'file' => 'prospects.csv'};
# Output the name and contact field from each row
my $sth = $dbh->prepare("SELECT * FROM prospects WHERE name LIKE 'G%'");
$sth->execute();
while (my $row = $sth->fetchrow_hashref) {
print("name = ", $row->{'Name'}, " contact = ", $row->{'Contact'}. "\n");
}
$sth->finish();
name = Glenhuntly Pharmacy contact = Paul
name = Gilmour's Shoes contact = Ringo
如果想了解更多,可以在命令行输入 perldoc DBI 和 perldoc Text::CSV。
67
Python里面有一个叫做 sqlite3
的库。用这个库,你可以创建一个数据库(在内存中),然后往里面添加数据行,还可以执行一些SQL查询。
如果你想要更好用的功能,像ActiveRecord那样的,你可以添加一个外部的ORM(对象关系映射),比如 sqlalchemy。不过这个需要单独下载。
这里有一个使用sqlalchemy的简单例子:
from sqlalchemy import create_engine, Column, String, Integer, MetaData, Table
from sqlalchemy.orm import mapper, create_session
import csv
CSV_FILE = 'foo.csv'
engine = create_engine('sqlite://') # memory-only database
table = None
metadata = MetaData(bind=engine)
with open(CSV_FILE) as f:
# assume first line is header
cf = csv.DictReader(f, delimiter=',')
for row in cf:
if table is None:
# create the table
table = Table('foo', metadata,
Column('id', Integer, primary_key=True),
*(Column(rowname, String()) for rowname in row.keys()))
table.create()
# insert data into the table
table.insert().values(**row).execute()
class CsvTable(object): pass
mapper(CsvTable, table)
session = create_session(bind=engine, autocommit=False, autoflush=True)
现在你可以查询这个数据库,按照任何字段进行筛选等等。
假设你在这个csv文件上运行上面的代码:
name,age,nickname
nosklo,32,nosklo
Afila Tun,32,afilatun
Foo Bar,33,baz
这会在内存中创建一个表,并填充字段 name
、age
、nickname
。然后你可以查询这个表:
for r in session.query(CsvTable).filter(CsvTable.age == '32'):
print r.name, r.age, r.nickname
这会自动创建并执行一个 SELECT
查询,并返回正确的数据行。
使用sqlalchemy的另一个好处是,如果你将来决定使用一个更强大的数据库,你几乎不需要改动代码就可以做到。