我无法使用R语言DBI :: sqlAppendTable函数来处理除数字之外的任何内容。下面是一些说明问题的代码。我怀疑问题是sqlAppendTable不引用数据。任何修复或解决方法都将非常感激。
num = data.frame(matrix(1:26, ncol=2))
let = data.frame(matrix(letters, ncol=2))
test.sqlAppendTable = function(dfr) {
#dfr: A data frame.
conx <- dbConnect(RSQLite::SQLite(), ":memory:")
on.exit(dbDisconnect(conx))
dbWriteTable(conx, "temp", dfr[1:5, ])
temp = dbReadTable(conx, 'temp')
print(temp)
sat = sqlAppendTable(conx, 'temp', dfr[6:10, ])
print(sat)
rs = dbExecute(conx, sat)
cat('Result set (rs): ')
print(rs)
temp = dbReadTable(conx, 'temp')
print(temp)
}
test.sqlAppendTable(num) #Runs fine.
test.sqlAppendTable(let) #Generates error:
#Error in rsqlite_send_query(conn@ptr, statement) : no such column: j
答案 0 :(得分:1)
我已经多次遇到这个问题,以至于不肯写自己的解决方法。就个人而言,我在Microsoft SQL Server中也遇到了同样的问题,但是我发现同样的解决方案也适用于SQLite。我正在使用:
出于效率考虑,我想避免在行中循环。我发现mapply
和paste0
可以以更面向列的方式组合。
我承认这有点“骇人听闻”,但对我来说一直很好。 使用后果自负;我只是将其用于小型项目,而不是企业解决方案。效率无论如何都不应该是一个大问题,因为无论如何插入的内容都1000 row limit。
db_sql_append_table <- function(p_df, p_tbl) {
# p_df: data.frame that contains the data to append/insert into the table
# the names must be the same as those in the database
# p_tbl: the name of the database table to insert/append into
num_rows <- nrow(p_df)
num_cols <- ncol(p_df)
requires_quotes <- sapply(p_df, class) %in% c("character", "factor")
commas <- rep(", ", num_rows)
quotes <- rep("'", num_rows)
str_columns <- ' ('
column_names <- names(p_df)
for(i in 1:num_cols) {
if(i < num_cols) {
str_columns <- paste0(str_columns, column_names[i], ", ")
} else {
str_columns <- paste0(str_columns, column_names[i], ") ")
}
}
str_query <- paste0("INSERT INTO ", p_tbl, str_columns, "\nVALUES\n")
str_values <- rep("(", num_rows)
for(i in 1:num_cols) {
# not the last column; follow up with a comma
if(i < num_cols) {
if(requires_quotes[i]) {
str_values <- mapply(paste0, str_values, quotes, p_df[[column_names[i]]], quotes, commas)
} else {
str_values <- mapply(paste0, str_values, p_df[[column_names[i]]], commas)
}
# this is the last column; follow up with closing parenthesis
} else {
if(requires_quotes[i]) {
str_values <- mapply(paste0, str_values, quotes, p_df[[column_names[i]]], quotes, ")")
} else {
str_values <- mapply(paste0, str_values, p_df[[column_names[i]]], ")")
}
}
}
# build out the query; collapse values with comma & newline; end with semicolon;
str_values <- paste0(str_values, collapse=",\n")
str_query <- paste0(str_query, str_values)
str_query <- paste0(str_query, ";")
return(str_query)
}
我想让它尽可能类似于原始的sqlAppendTable
函数。此函数仅构造查询。
您仍然必须将此函数包装在对dbExecute()
的调用中才能将行实际插入/追加到数据库中。
dbExecute(conn=conn, statement = db_sql_append_table(my_dataframe, "table_name"))
答案 1 :(得分:0)
这似乎是RSQLite
包中的缺陷;应该引用价值。请注意,引号在以下示例中添加:
DBI::sqlAppendTable(DBI::ANSI(), table = "test", data.frame(a = 1, b = "2"))
#> <SQL> INSERT INTO "test"
#> ("a", "b")
#> VALUES
#> (1, '2')
另请参阅相应的GitHub issue。
答案 2 :(得分:0)
我已经能够拼凑出一个解决方法:
1)将要附加的数据帧作为临时表(temp)写入SQLite数据库文件中。
2)使用SQLite语句将其附加到目标表(目标):
insert into target select * from temp;
3)降温。
运行速度非常快,可能是因为SQLite得到了很好的优化。
附录:
您确实可以使用dbWriteTable将数据框附加到数据库表,并使用append = TRUE选项。我已根据上述解决方法对此进行了测试,令人惊讶的是,解决方法的运行速度比dbWriteTable快了近40%。