代码之家  ›  专栏  ›  技术社区  ›  hoju

如何生成各种数据库转储

  •  2
  • hoju  · 技术社区  · 15 年前

    我有一个csv文件,想为sqlite、mysql、postgres、oracle和mssql生成数据转储。

    是否有一个通用的API(理想情况下是基于Python)来执行此操作?

    我可以使用ORM将数据插入每个数据库,然后导出转储,但是这需要安装每个数据库。这似乎也是浪费资源-这些csv文件 大的 .

    由于每个数据库的不同,我对自己构建SQL持谨慎态度。理想情况下,有人已经完成了这项艰巨的工作,但我还没有找到。

    3 回复  |  直到 15 年前
        1
  •  5
  •   David Fraser piouson    15 年前

    SQLAlchemy 是一个数据库库, ORM functionality 支持 SQL generation dialects 在您提到的所有不同的数据库中(等等)。

    在正常使用中,可以创建SQL表达式/指令(使用 schema.Table object 创建一个 database engine ,然后将指令绑定到引擎,以生成SQL。

    然而,引擎并不是绝对必要的;每个方言都有一个 compiler 它可以在没有连接的情况下生成SQL;唯一需要注意的是,您需要阻止它生成绑定参数,就像默认情况下那样:

    from sqlalchemy.sql import expression, compiler
    from sqlalchemy import schema, types
    import csv
    
    # example for mssql
    from sqlalchemy.dialects.mssql import base
    dialect = base.dialect()
    compiler_cls = dialect.statement_compiler
    class NonBindingSQLCompiler(compiler_cls):
        def _create_crud_bind_param(self, col, value, required=False):
            # Don't do what we're called; return a literal value rather than binding
            return self.render_literal_value(value, col.type)
    
    recipe_table = schema.Table("recipe", schema.MetaData(), schema.Column("name", types.String(50), primary_key=True), schema.Column("culture", types.String(50)))
    
    for row in [{"name": "fudge", "culture": "america"}]: # csv.DictReader(open("x.csv", "r")):
        insert = expression.insert(recipe_table, row, inline=True)
        c = NonBindingSQLCompiler(dialect, insert)
        c.compile()
        sql = str(c)
        print sql
    

    上面的示例实际上是有效的;它假定您知道目标数据库表模式;它应该很容易适应从csv导入并为多个目标数据库方言生成。

        2
  •  1
  •   mac    15 年前

    我不是数据库向导,但是在Python中,没有一个通用的API可以满足您的需求。有 PEP 249 它定义了访问数据库的模块应该使用的API,以及至少由mysql和postgre python模块使用的afaik。( here here )这可能是一个起点。

    然而,我试图追随自己的道路将是另一条:

    1. 将cvs导入mysql (例如,这仅仅是因为MySQL是我最熟悉的,而且网上有大量的资料 this very easy recipe ,但可以从另一个数据库开始执行相同的过程)。
    2. 生成mysql dump .
    3. 处理mysql转储文件 为了修改它以满足sqlite(和其他)语法。

    用于处理转储文件的脚本可能非常紧凑,但如果使用regex解析行,这些脚本可能会有些棘手。这是一个示例脚本mysql sqlite,我只是从中粘贴的 this page :

    #!/bin/sh 
    mysqldump --compact --compatible=ansi --default-character-set=binary mydbname | 
    grep -v ' KEY "' | 
    grep -v ' UNIQUE KEY "' | 
    perl -e 'local $/;$_=<>;s/,\n\)/\n\)/gs;print "begin;\n";print;print "commit;\n"' | 
    perl -pe ' 
    if (/^(INSERT.+?)\(/) { 
    $a=$1; 
    s/\\'\''/'\'\''/g; 
    s/\\n/\n/g; 
    s/\),\(/\);\n$a\(/g; 
    } 
    ' | 
    sqlite3 output.db
    

    您可以用python编写脚本(在这种情况下,您应该查看 re.compile 为了表现)。

    我选择的理由是:

    1. 我得到了沉重的负担[导入,因此数据一致性检查+生成开始的SQL文件] MySQL
    2. 我只需要安装一个数据库。
    3. 我对正在发生的事情有完全的控制权,并且有可能对这个过程进行微调。
    4. 我可以以这样一种方式构造我的脚本,以便很容易地将它扩展到其他数据库(基本上,我会像一个解析器那样构造它,识别单个字段+一组语法(每个数据库一个语法),我可以通过命令行选项进行选择)
    5. 与单数据库导入/导出库相比,有更多关于SQL风格差异的文档。

    编辑:基于模板的方法

    如果出于任何原因,您没有足够的信心自己编写SQL,那么可以使用一种基于模板的脚本。我可以这样做:

    1. 在计划使用的所有4个数据库中导入并生成表的转储。
    2. 对于每个数据库,保存转储的初始部分(包括模式声明和所有其余部分)和一条插入指令。
    3. 编写一个python脚本,对于每个db export,该脚本将输出转储的“header”加上相同的“saved line”,您将在其中以编程方式替换cvs文件中每行的值。

    这种方法的明显缺点是您的“模板”只能用于一个表。最重要的一点是,写这样的脚本将非常容易和快速。

    至少有一点!

        3
  •  0
  •   Community Mohan Dere    9 年前

    你可以这样做- Create SQL tables from CSV files

    Generate Insert Statements from CSV file

    或者试试这个 Generate .sql from .csv python

    当然,您可能需要调整上面提到的脚本来满足您的需求。