【问题标题】:Database on the fly with scripting languages使用脚本语言动态数据库
【发布时间】:2011-02-04 13:09:03
【问题描述】:

我有一组要处理的 .csv 文件。使用 SQL 查询处理它会容易得多。我想知道是否有某种方法可以加载 .csv 文件并使用 SQL 语言使用脚本语言(如 python 或 ruby​​)来查看它。用类似于 ActiveRecord 的东西加载它会很棒。

问题是我不想在运行脚本之前在某个地方运行数据库。除了脚本语言和一些模块之外,我不需要额外的安装。

我的问题是我应该为这项任务使用哪种语言和哪些模块。我环顾四周,找不到任何适合我需要的东西。有可能吗?

【问题讨论】:

  • 要将答案标记为收藏(实际上:作为 the 答案:),您可以单击所选答案的投票数正下方的复选标记 (✓)。例如,目前,nosklo 的回答有 13 票;在“否决”三角形正下方有一个微弱的复选标记。点击那个。

标签: python sql database sqlite sqlalchemy


【解决方案1】:

在像SQLite 这样的库中使用数据库。 有PythonRuby 两个版本。

将您的 CSV 加载到表格中,这里可能也有模块/库可以帮助您。然后 SQL 离开。

【讨论】:

    【解决方案2】:

    CSV 文件不是数据库——它们没有索引——你对它们施加的任何 SQL 模拟都只不过是一遍又一遍地搜索整个内容。

    【讨论】:

      【解决方案3】:

      sqlite3,包含在 python 中。有了它,您可以创建一个数据库(在内存中)并向其中添加行,并执行 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
      

      这将在内存中创建并填充一个包含字段nameagenickname 的表。然后您可以查询该表:

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

      这将自动创建并运行SELECT 查询并返回正确的行。

      使用 sqlalchemy 的另一个优点是,如果您决定在未来使用另一个更强大的数据库,您可以在不更改代码的情况下实用地这样做。

      【讨论】:

        【解决方案4】:

        看过 Perl 和 Text::CSV 和 DBI? CPAN 上有很多模块可以做到这一点。这是一个例子(来自HERE):

        #!/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 即可获得更多信息。

        【讨论】:

          【解决方案5】:

          您可以使用任一脚本语言来解析 CSV 文件并将数据存储到 SQLite,它只使用单个文件进行存储。从那里您可以将其保存在数据库中,并可以对其运行查询。

          或者,在 Windows 上,您可以将 ODBC 数据源设置为 CSV 文件。但这可能很难自动化。

          【讨论】:

            【解决方案6】:

            PHP FlatfileDB 可用 here 如果您正在构建 Web 应用程序,这是一个非常好的选择

            【讨论】:

              【解决方案7】:

              我使用了 nosklo 的解决方案(谢谢!),但我已经在列行(csv 的第一行)中有一个主键(作为 pk_col 传入)。所以我想我会分享我的修改。我用的是三元。

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

              【讨论】:

                猜你喜欢
                • 2012-09-12
                • 1970-01-01
                • 2012-10-19
                • 2018-06-26
                • 2010-11-27
                • 1970-01-01
                • 2010-11-18
                • 2012-08-11
                • 1970-01-01
                相关资源
                最近更新 更多