【问题标题】:Adding value to existing database table in RSQLite为 RSQLite 中的现有数据库表添加值
【发布时间】:2017-09-20 08:27:03
【问题描述】:

我是 RSQLite 的新手。 我有一个文本格式的输入文档,其中的值分别由“|” 我创建了一个包含所需变量的表(虚拟代码如下)

db<-dbconnect(SQLite(),dbname="test.sqlite")

dbSendQuery(conn=db,
"CREATE TABLE TABLE1(
MARKS INTEGER,
ROLLNUM INTEGER
NAME CHAR(25)
DATED DATE)"
)

但是,我对如何将值导入创建的表感到震惊。 我无法使用 INSERT INTO Values 命令,因为原始数据文件中有数千行和 20 多列,并且无法手动输入每个数据点。

有人可以提出另一种有效的方法吗?

【问题讨论】:

标签: r rsqlite


【解决方案1】:

您正在使用脚本语言。这样做实际上是为了避免手动输入每个数据点。对不起。

你有两条路线:

1:您已更正加载数据库连接并在 SQLite 数据库中创建了一个空表。不错!

要将数据加载到表中,请使用例如将文本文件加载到 R 中。 df <- read.table('textfile.txt', sep='|')(修改参数以适合您的文本文件)。

要拥有“动态”INSERT 语句,您可以使用占位符。 RSQLite 允许命名或定位占位符。要插入单行,您可以这样做:

dbSendQuery(db, 'INSERT INTO table1 (MARKS, ROLLNUM, NAME) VALUES (?, ?, ?);', list(1, 16, 'Big fellow'))

你看到了吗?第一个? 得到值1,第二个? 得到值16,最后一个? 得到字符串Big fellow。另请注意,请勿将占位符括在引号中('")!

现在,您有数千行。或者不止一个。无论哪种方式,您都可以发送数据框。 dbSendQuery 有一些要求。 1)每个向量具有相同数量的条目(在提供 data.frame 时不是问题)。并且 2) 您可以提交与占位符相同数量的向量。

我假设您的数据框df 包含列markrollname,对应于这些列。然后你可以运行:

dbSendQuery(db, 'INSERT INTO table1 (MARKS, ROLLNUM, NAME) VALUES (:mark, :roll, :name);', df)

这将为df中的每一行执行一个INSERT语句!

提示!因为对每一行执行 INSERT 语句,插入数千行可能需要很长时间,因为每次插入后,数据都会写入文件并索引已更新。插入,将其包含在事务中:

dbBegin(db)
res <- dbSendQuery(db, 'INSERT ...;', df)
dbClearResult(res)
dbCommit(db)

SQLite 会将数据保存到日志文件中,并且只保存当您执行dbCommit(db) 时的结果。尝试这两种方法并比较速度!


2:啊,是的。第二种方式。这可以完全在 SQLite 中完成。 使用 SQLite 命令实用程序(命令行中的sqlite3,而不是 R),您可以将文本文件附加为表格,然后简单地执行 INSERT INTO ... SELECT ... ; 命令。或者,将sqlite3 中的文本文件读入临时表并运行INSERT INTO ... SELECT ... ;


要记住的有用网站:http://www.sqlite.com/lang.html

【讨论】:

  • 这没有回答问题。
  • 这怎么不能回答问题?
  • Can someone suggest an alternative efficient way to do so? ... 在数据库世界中,生成包含数千条或更多语句的 INSERT 脚本不会被认为是有效的。在任何主要的 RDBMS 上,无论从性能还是从准确性的角度来看,您的答案都不是首选方式。
  • 我的回答是在他所要求的RSQLite 框架内这样做的有效方法。
【解决方案2】:

我认为没有直接从 R 进行大量插入的好方法。SQLite 确实具有批量插入功能,但 RSQLite 包似乎没有公开它。

您可以从命令行尝试以下操作:

.separator |
.import your_file.csv your_table

其中your_file.csv 是包含您的数据的CSV(或管道分隔)文件,your_table 是目标表。

有关详细信息,请参阅 CSV 导入下的 documentation

【讨论】:

  • RSQLite 确实支持通过例如插入(或选择!)数据框或向量,请参阅我的答案。感谢您提供答案,因为这是我的第二种方法,但我懒得写完整了。
  • @MrGumble 不,它似乎不支持批量插入,OP 的问题的重点是避免生成插入语句的混乱和低效的脚本。
  • 什么意思;我的回答的哪一部分表明RSQLite 不支持批量插入?它确实确​​实支持批量插入,请参阅我的回答。 RSQLite 在 INSERT 和 SELECT 语句中支持命名和未命名占位符,允许用户提供值向量以插入占位符。
  • @TimBiegeleisen:检查新的dbBind(),尤其是其中的示例。对于许多应用程序来说应该足够快。
【解决方案3】:

聚会有点晚了,但DBI 提供了dbAppendTable(),它将数据帧的内容写入 SQL 表。数据框中的列名必须与数据库中的字段名匹配。对于您的示例,以下代码会将我的随机数据框的内容插入到您新创建的表中。

library(DBI)

db<-dbConnect(RSQLite::SQLite(),dbname=":memory")

dbExecute(db,
          "CREATE TABLE TABLE1(
             MARKS INTEGER,
             ROLLNUM INTEGER,
             NAME TEXT
           )"
)

df <- data.frame(MARKS = sample(1:100, 10), 
                 ROLLNUM = sample(1:100, 10), 
                 NAME = stringi::stri_rand_strings(10, 10))

dbAppendTable(db, "TABLE1", df)

【讨论】:

  • 问题是关于“文本格式的输入文档”,而不是 data.frame。在 R 中读取这么大的文件效率不高。
  • 我不明白你的评论。 “数千行20多列”没什么大不了的。 dbAppendTable() 将 data.frame 作为输入,因此,OP 可以轻松地将其文本文件读入 data.frame 并使用 dbAppendTable() 在单个事务中插入其行。这比公认答案的方法更有效。
  • R 将其读入内存实际上可能需要一段时间。我没有看到可接受的答案,所以不确定您指的是哪种方法。
  • 相关post对该问题发表评论是最有效的方法
  • 我指的是@MrGrumble 的回答。如果 OP 正在创建新表,则使用 dbWriteTable() 在您提到的帖子中有效,但如果他们将数据附加到现有表中则无效。我对从文件读取和使用dbAppendTable()here 进行了基准测试。 134 us 100k 行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2014-07-09
相关资源
最近更新 更多