如何生成各种数据库转储

Posted

技术标签:

【中文标题】如何生成各种数据库转储【英文标题】:how to generate various database dumps 【发布时间】:2011-05-06 12:27:44 【问题描述】:

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

是否有通用的 API(最好是基于 Python)来执行此操作?

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

由于每个数据库的差异,我对尝试自己编写 SQL 持谨慎态度。理想情况下,有人已经完成了这项艰苦的工作,但我还没有找到。

【问题讨论】:

【参考方案1】:

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

Generate Insert Statements from CSV file

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

当然,您可能需要调整上述脚本以满足您的需求。

【讨论】:

但每种数据库格式之间存在细微差别 那么我想您需要分别处理每个脚本,但这些脚本应该可以帮助您入门 我不是投反对票的人,但我的猜测是,无论是谁做的,都是因为你的答案只不过是谷歌点击 [合法答案,因此如果你问我不值得投反对票,但是有点马虎] ;)【参考方案2】:

我不是数据库向导,但是 Python 中的 AFAIK 没有一个通用的 API 可以开箱即用地满足您的要求。 PEP 249 定义了一个 API,该 API 应该由访问 DB 的模块使用,并且 AFAIK 至少被 MySQL 和 Postgre python 模块(here 和 here)使用,这可能是一个起点。

我会尝试自己走的路——然而——将是另一条路:

    将 CVS 导入 MySQL(这只是因为 MySQL 是我最了解的,并且网上有大量资料,例如 this very easy recipe,但您可以从另一个数据库)。 生成 MySQL 转储处理 MySQL 转储文件以对其进行修改以满足 SQLite(和其他)语法。

处理转储文件的脚本可能非常紧凑,但如果您使用正则表达式解析行,它们可能会有些棘手。这是一个示例脚本 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 以了解性能)。

我选择的理由是:

    mysql 为我完成了繁重的 [导入和数据一致性检查 + 生成起始 SQL 文件] 我只需要安装一个数据库。 我可以完全控制正在发生的事情以及微调过程的可能性。 我可以以这样一种方式构建我的脚本,以便将它扩展到其他数据库非常容易(基本上我会像一个解析器那样构建它,它可以识别单个字段 + 一组语法 - 每个数据库一个语法 - 我可以通过命令行选项选择) 与单一数据库导入/导出库相比,关于 SQL 风格之间差异的文档要多得多。

编辑:基于模板的方法

如果出于某种原因您对自己编写 SQL 没有足够的信心,您可以使用一种基于模板的脚本。以下是我的做法:

    在您计划使用的所有 4 个 DB 中导入并生成表的转储。 为每个 DB 保存转储的初始部分(包括架构声明和所有其余部分)和单个插入指令。 编写一个 python 脚本 - 对于每个 DB 导出 - 将输出转储的“标题”以及您将以编程方式替换 CVS 文件中每一行的值的相同“保存行”。

这种方法的明显缺点是您的“模板”仅适用于一个表。最大的优点是编写这样的脚本会非常简单快捷。

至少有点!

【讨论】:

第 3 步是我所关心的。如果有任何东西可以为每个数据库创建插入语句? 有很多商业实用程序可以在一些最常见的数据库之间进行自动转换(它们的价格在 40 到 900 美元之间)。然而,这些实用程序通常处理所有 DB 位和螺栓(索引、外键等)。另外,我不确定这些实用程序是否可以编写脚本,或者它们是否只能通过 GUI 工作。 抱歉,打扰了!我不知道上述实用程序的 FLOSS 替代品(例如:tinyurl.com/2wyszoq)。老实说,要导入一个表,我宁愿自己研究各种 SQL 方言之间的差异:在定义模式和编写插入语句时,它们通常非常简单。如有疑问,您可以为您计划使用的每个数据库创建一个初始导入和转储,并确保您的“转换代码”将生成一个与目标数据库本身生成的文件相同的文件。 @Plumo - 另见我在原始答案底部的编辑。 这将需要安装每个数据库,这是我试图避免的。我同意 SQL 方言并不复杂,但它需要测试(=时间)才能正确。我很惊讶还没有人做过这项工作。【参考方案3】:

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

在正常使用中,可以创建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 导入并为多种目标数据库方言生成。

【讨论】:

很好的解决方案设计 (+1) 尽管看起来处理 BIG(使用 OP 词)cvs 表需要很长时间...跨度> 对实际数据库运行 sqlalchemy 会更快;但他想要 SQL。不过,我实际上并不认为它会慢得离谱。显然,如果您知道数据类型等,您可以创建一个更快的配方,但这具有使用现有库的优势 见***.com/a/36141722/120398 - 显然你可以通过说q.statement.compile(compile_kwargs="literal_binds": True)来更简单地做到这一点

以上是关于如何生成各种数据库转储的主要内容,如果未能解决你的问题,请参考以下文章

当我们将 Telerik 网格与 LinqDataSource 一起使用时,如何在页面的各种按钮单击事件上重新生成网格数据

如何生成各种mif文件,绝对经典!!!

漂亮地将 JSON 转储到文本

如何生成阳性预测值 (PPV) 与分类的各种截止点的图?

python使用fpdf生成各种样式pdf表格数据

各种数据结构在线生成的网址