将 MySQL 转储导入 R(不需要 MySQL 服务器)

问题描述 投票:0回答:3

RMySQL
sqldf
这样的包允许与本地或远程数据库服务器交互。我正在创建一个便携式项目,其中涉及在不总是有权访问正在运行的服务器的情况下(或在设备上)导入 sql 数据,但 do 始终可以访问数据库的最新 .sql 转储。

目标似乎很简单:将.sql转储导入到R中,而不需要MySQL服务器的参与。更具体地说,我想创建一个列表列表,其中的元素对应于.sql中定义的任何数据库dump(可能有多个),这些元素又由这些数据库中的表组成。

为了使其可重现,让我们获取示例 sportsdb SQL 文件此处 — 如果解压它,它的名称为 sportsdb_sample_mysql_20080303.sql。

有人会认为

sqldf
也许能够做到:

read.csv.sql('sportsdb_sample_mysql_20080303.sql', sql="SELECT * FROM addresses")
Error in sqliteSendQuery(con, statement, bind.data) : 
  error in statement: no such table: addresses

即使转储中有一个表地址,也是如此。 sqldf 列表上的这篇文章提到了相同的错误,但没有解决方案。

然后

sql.reader
包中有一个
ProjectTemplate
函数,看起来很有前途。四处寻找,可以在here找到该函数的源代码,它假设有一个正在运行的数据库服务器并依赖于
RMySQL
——不是我需要的。

所以...我们似乎已经没有选择了。感谢来自 hivemind 的任何帮助!

(重申一下,我不是在寻找依赖于访问 SQL 服务器的解决方案;使用

dbReadTable
包中的
RMySQL
很容易实现。我非常想绕过服务器并直接获取数据来自 .sql 转储文件。)

sql r database mysql
3个回答
2
投票

根据您想要从表中提取的内容,以下是您可以如何处理数据

numLines <- R.utils::countLines("sportsdb_sample_mysql_20080303.sql")
# [1] 81266

linesInDB <- readLines("sportsdb_sample_mysql_20080303.sql",n=60)

然后您可以执行一些正则表达式来获取表名称(在 CREATE TABLE 之后)、列名称(在第一个括号之间)和值(在 CREATE TABLE 之后和第二个括号之间的行)

参考: 使用 MySQL Workbench 对 mysqldump 输出进行逆向工程,给出“从指向的行开始的语句包含非 UTF8 字符”错误


编辑:响应OP的回答,如果我正确解释python脚本,它也会逐行读取它,过滤INSERT INTO行,解析为csv,然后写入文件。这与我最初的建议非常相似。我的 R 版本如下。如果文件太大,最好使用其他 R 包分块读取文件

options(stringsAsFactors=F)
library(utils)
library(stringi)
library(plyr)

mysqldumpfile <- "sportsdb_sample_mysql_20080303.sql"

allLines <- readLines(mysqldumpfile)
insertLines <- allLines[which(stri_detect_fixed(allLines, "INSERT INTO"))]
allwords <- data.frame(stri_extract_all_words(insertLines, " "))
d_ply(allwords, .(X3), function(x) {
    #x <- split(allwords, allwords$X3)[["baseball_offensive_stats"]]
    print(x[1,3])

    #find where the header/data columns start and end
    valuesCol <- which(x[1,]=="VALUES")
    lastCols <- which(apply(x, 2, function(y) all(is.na(y))))
    datLastCol <- head(c(lastCols, ncol(x)+1), 1) - 1

    #format and prepare for write to file
    df <- data.frame(x[,(valuesCol+1):datLastCol])
    df <- setNames(df, x[1,4:(valuesCol-1)])
    #type convert before writing to file otherwise its all strings
    df[] <- apply(df, 2, type.convert)
    #write to file
    write.csv(df, paste0(x[1,3],".csv"), row.names=F)
})

1
投票

我认为您不会找到一种方法来导入 sql 转储(其中包含多个带引用的表),然后在 R 中对它们执行任意 sql 查询。这基本上需要 R 包运行完整的数据库服务器(兼容与创建转储的人一起)在 R 中。

我建议从数据库中将您需要的表/选择语句导出为 CSV (请参阅此处)。如果您只能从转储中工作,并且不想设置服务器进行转换,您可以使用一些简单的正则表达式,使用以下工具将转储中的

insert
语句转换为表格的一堆 CSV 文件:您选择像
sed
awk
(甚至是其他答案建议的 R,但对于这个文件大小来说可能会相当慢)。


1
投票

我将不情愿地使用 +bnord 和 +chinsoon12(他们都贡献了拼图的一部分)的输入来回答我自己的问题。

简短的回答:没有开箱即用的解决方案。 正如 +bnord 所说,最好在服务器端修复它(例如,通过使用 mysqldump 导出为 CSV 格式)。然而,正如我的问题所表明的,我正在寻找一种解决方案,允许我绕过服务器来使用 sql 转储。

那么如果我们必须处理转储,该怎么办?最核心的手动方法是使用正则表达式将

INSERT
语句转换为 CSV,(1) 在 R 外部使用 .sql 文本文件 (+bnord) 上的
sed
awk
,或 (2) 在 R 内部带有
grep
gsub
的字符串加载有
readLines
(+chinsoon12)。

一些好人写了一个可以将 sql 转储转换为 CSV 的 python 脚本。这需要另一块(安装/维护可能并不简单)软件,所以这不是我所希望的答案,但它看起来确实是一个很好的模型,以防有人想在 R 中重新发明轮子。

现在,我将坚持我的操作方式(在 Windows 上)运行 MySQL Community Server 并使用 WorkBench 导入转储,然后从 R 与本地服务器对话。这是一种非常间接的方法,非常麻烦,因为MySQL 难以理解的访问权限系统(特别烦人,因为它都只存在于 ASCII 文本文件中),但似乎是目前唯一的方法。感谢大家的意见!

(如果有更好、更完整的答案出现,我会很乐意接受,如果可能的话,将其变成评论。)

© www.soinside.com 2019 - 2024. All rights reserved.