DBI dbWriteTable
Posted
技术标签:
【中文标题】DBI dbWriteTable【英文标题】: 【发布时间】:2017-01-06 19:46:04 【问题描述】:我非常喜欢 DBI 的 dbWriteTable 函数(我通常使用 RSQLite 或 ROracle 作为后端)。
我使用该功能导入大量 Excel 电子表格,问题是如果这些电子表格是长期创建的,则会添加/删除列更改或将名称从一个文档更改为另一个文档。
所以我的问题是,有没有人有一种相对快速的方法可以将数据添加到数据库,而不必完美匹配归档列表?
这是我使用的示例脚本
require(RSQLite)
require(readxl)
# Create database file
conn <- dbConnect(drv=SQLite(),dbname = "path to database")
# Define import function
excel2sqltable <- function(conn, file, table)
source.df <- read_excel(path=file,col_names = TRUE) %>%
cbind("SourceFile" = file, .)
names(source.df) <- source.df %>%
data.frame(check.names = TRUE) %>%
gsub("[.]",x=names(.),replacement="_")
print(paste("Importing ", file))
setOldClass(c("tbl_df", "data.frame"))
dbWriteTable(conn = conn, name = table, value = source.df, append=TRUE)
有了这个功能,我可以做到:
sapply(list.files(),FUN = function(x)excel2sqltable(conn,x,"Imports"))
【问题讨论】:
不清楚您在这里要做什么。您是否要跳过有关命名source.df
列的部分?还是您在谈论脚本的dbWriteTable
部分?
我猜怎么升级这个脚本来动态创建字段,这样dbWriteTable
不会引发错误Columns NewColumn not found
。
在数据库中查询单行,并设置列名来匹配?我必须查看文档以查看是否有 DBI 函数仅用于返回表的列名...
如果您的表已经在数据库中,您可以使用cols <- dbListFields(conn, 'Imports')
获取其列名,然后您实际上可以将这些名称用于导入的数据 (source.df
):source.df <- read_excel(path=file,col_names = cols, skip = 1)
。
对,但是当 source.df 有一个额外的列时,我们将其称为 NewColumn
然后 dbWriteTable
将引发错误 Columns NewColumn not found
。因此,我需要转到数据库,并手动将 ALTER TABLE
包含在 NewColumn
中。我想避免手动执行此操作,我想自动化该部分。
【参考方案1】:
您可以以此为指导:
library(RSQLite)
sqlite_conn <- dbConnect(drv = SQLite(),dbname = 'data_dump.sqlite')
excel2sqltable <- function(conn, file, table)
source.df <- readxl::read_excel(path=file,col_names = TRUE) %>%
cbind("SourceFile" = file, .)
names(source.df) <- source.df %>%
data.frame(check.names = TRUE) %>%
gsub("[.]",x=names(.),replacement="_")
if(!dbExistsTable(conn, table))
dbWriteTable(conn = conn, name = table, value = source.df)
else
# Get both dataframe columns and table columns
df_cols <- colnames(source.df)
tbl_cols <- dbListFields(conn, table)
# Check if there are columns in the dataframe
# that are not in the destination table
# Loop through the missing columns and add
# them to the database table
if (length(setdiff(df_cols, tbl_cols)) > 0)
missing_cols <- setdiff(df_cols, tbl_cols)
for (col_name in missing_cols)
dbSendStatement(conn, sprintf('ALTER TABLE %s ADD %s VARCHAR', table, col_name))
setOldClass(c("tbl_df", "data.frame"))
dbWriteTable(conn = conn, name = table, value = source.df, append=TRUE)
lapply(list.files(), function(x)
excel2sqltable(sqlite_conn, x, "Imports")
)
dbDisconnect(sqlite_conn)
我希望它有一个目的。
【讨论】:
以上是关于DBI dbWriteTable的主要内容,如果未能解决你的问题,请参考以下文章