Base de datos sobre la marcha con lenguajes de scripting

Tengo un conjunto de archivos .csv que quiero procesar. Sería mucho más fácil procesarlo con consultas SQL. Me pregunto si hay alguna forma de cargar un archivo .csv y usar el lenguaje SQL para examinarlo con un lenguaje de scripting como python o ruby. Cargarlo con algo similar a ActiveRecord sería increíble.

El problema es que no quiero tener que ejecutar una base de datos en algún lugar antes de ejecutar mi script. No debería tener instalaciones adicionales necesarias fuera del lenguaje de scripting y algunos módulos.

Mi pregunta es qué idioma y qué módulos debo usar para esta tarea. Miré a mi alrededor y no puedo encontrar nada que se adapte a mi necesidad. ¿Es incluso posible?

Hay sqlite3 , incluido en python. Con él puede crear una base de datos ( en la memoria ) y agregarle filas y realizar consultas SQL.

Si desea una funcionalidad nítida de ActiveRecord, debe agregar un ORM externo, como sqlalchemy . Eso es una descarga separada aunque

Ejemplo rápido usando 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) 

Ahora puedes consultar la base de datos, filtrando por cualquier campo, etc.

Supongamos que ejecuta el código anterior en este csv:

 name,age,nickname nosklo,32,nosklo Afila Tun,32,afilatun Foo Bar,33,baz 

Eso creará y llenará una tabla en la memoria con los campos name , age , nickname . A continuación, puede consultar la tabla:

 for r in session.query(CsvTable).filter(CsvTable.age == '32'): print r.name, r.age, r.nickname 

Eso creará y ejecutará automáticamente una consulta SELECT y devolverá las filas correctas.

Otra ventaja de usar sqlalchemy es que, si decide usar otra base de datos más poderosa en el futuro, puede hacerlo de manera práctica sin cambiar el código.

Utilice una base de datos en una biblioteca como SQLite . Hay versiones en Python y Ruby .

Cargue su CSV en la tabla, puede que haya módulos / bibliotecas que lo ayuden aquí también. Entonces SQL desaparece.

Mirado a Perl y Text :: CSV y DBI? Hay muchos módulos en CPAN para hacer exactamente esto. Aquí hay un ejemplo (de AQUÍ ):

 #!/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 

Simplemente escriba perldoc DBI y perldoc Text :: CSV en el símbolo del sistema para obtener más información.

Los archivos CSV no son bases de datos, no tienen índices, y cualquier simulación de SQL que les imponga equivaldría a poco más que buscar todo el contenido una y otra vez.

Puede usar cualquiera de los dos lenguajes de script para analizar el archivo CSV y almacenar los datos en SQLite , que solo usa un único archivo para el almacenamiento. A partir de ahí lo tiene en una base de datos y puede ejecutar consultas en su contra.

Alternativamente, en Windows puede configurar una fuente de datos ODBC como un archivo CSV. Pero puede ser difícil automatizar esto.

Usé la solución de nosklo (¡gracias!) Pero ya tenía una clave principal (que se pasa como pk_col) dentro de la línea de la columna (primera línea de csv). Así que pensé en compartir mi modificación. Utilicé un ternario.

 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() 

PHP FlatfileDB disponible aquí es una muy buena opción si está creando una aplicación web