База данных на лету с языками сценариев - PullRequest
23 голосов
/ 05 апреля 2010

У меня есть набор файлов .csv, которые я хочу обработать. Было бы гораздо проще обрабатывать его с помощью SQL-запросов. Интересно, есть ли какой-нибудь способ загрузить файл .csv и использовать язык SQL, чтобы изучить его с помощью языка сценариев, такого как python или ruby. Загрузка с чем-то похожим на ActiveRecord была бы потрясающей.

Проблема в том, что я не хочу запускать базу данных где-то до запуска моего скрипта. У меня не должно быть дополнительных установок вне языка сценариев и некоторых модулей.

У меня вопрос, какой язык и какие модули использовать для этой задачи. Я огляделся и не смог найти ничего подходящего мне. Это вообще возможно?

Ответы [ 7 ]

63 голосов
/ 05 апреля 2010

Есть 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 является то, что, если вы решите использовать другую, более мощную базу данных в будущем, вы можете сделать это практически без изменения кода.

4 голосов
/ 05 апреля 2010

Посмотрел на 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 в командной строке для получения дополнительной информации.

4 голосов
/ 05 апреля 2010

Использование БД в библиотеке, например SQLite . Существуют версии Python и Ruby .

Загрузите ваш CSV в таблицу, здесь также могут быть модули / библиотеки. Тогда SQL прочь.

3 голосов
/ 05 апреля 2010

Вы можете использовать любой язык сценариев для анализа файла CSV и сохранения данных в SQLite , который просто использует один файл для хранения. Оттуда у вас есть это в базе данных и может выполнять запросы к нему.

Кроме того, в Windows вы можете настроить источник данных ODBC в виде файла CSV. Но это может быть трудно автоматизировать.

3 голосов
/ 05 апреля 2010

CSV-файлы не являются базами данных - у них нет индексов - и любая имитация SQL, которую вы им наложите, будет чуть больше, чем поиск по всему объекту снова и снова.

2 голосов
/ 06 февраля 2012

Я использовал решение nosklo (спасибо!), Но у меня уже был первичный ключ (переданный как pk_col) в строке столбца (первая строка csv). Поэтому я решил поделиться своей модификацией. Я использовал троичный.

table = Table(tablename, metadata,
    *((Column(pk_col, Integer, primary_key=True)) if rowname == pk_col else (Column(rowname, String())) for rowname in row.keys()))
table.create()
1 голос
/ 06 апреля 2010

PHP FlatfileDB доступен здесь - очень хороший вариант, если вы создаете веб-приложение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...