如何在dplyr中创建left_join(...,copy = TRUE)而不授予INSERT权限

时间:2015-05-27 17:50:30

标签: mysql r dplyr

我们需要使用excel文件的内容加入数据库表。使用dplyr left_join这很简单,但要求在联接中设置copy=TRUE,因为数据不是来自同一来源。这反过来意味着代码只会在数据库用户具有INSERT权限时运行,以便left_join可以在/ tmp文件夹中创建临时表。

有没有办法在没有授予INSERT权限的情况下执行此操作copy=TRUE left_join?访问数据进行分析的数据库用户确实应该只是一个读者。

如果未授予插入权限,则会出现如下错误:

Error in .local(conn, statement, ...) : 
  could not run statement: INSERT command denied to user 
  'reader'@'192.168.135.1' for table 'utiexriryc'
将出现

(每个连接上使用不同的随机表名称)。

一个简短的可重现示例很难,因为它需要数据库连接(在本例中为src_mysql()的mysql)和excel文件(在本例中为readxl读取)。联接看起来像:

df.biozones <- db.sites %>% 
  left_join(ef.join_site_ids, by=c("site_id"="id"), copy=TRUE) %>% 
  collect()

其中db.sites是一个mysql数据库表,ef.join_site_ids是一个excel电子表格中的data.frame,用readxl读取。

有没有办法在dplyr中执行上述操作并避免为读取数据的用户授予INSERT权限?

1 个答案:

答案 0 :(得分:2)

虽然没有办法直接按照我的要求行事,正如@hadley所说,有一种不同的方式来看待这个问题。我花了一些时间来理解的是,dplyr将每个连接视为差异源(或简称为src)。在src上始终存在着内存中对象的集合。

所以在我的问题中,我实际上是在处理三个来源:

  1. 内存中的对象
  2. Database_1
  3. 了Database_2
  4. 这三者之间的任何连接都需要dplyr的权限才能生成临时表并插入它们。任何这三个中的任何一个加入都不是问题。因此,当您无法获得数据库的其他权限时,至少有三种可能的方法来解决这个问题。

    <强> 1。将所有内容加载到内存中

    如果您将所需的所有对象从两个数据库中获取到内存中,那么您将把它们带入共享的src并能够对它们进行任何连接。 Dplyr提供了collect()功能:

    db_table_of_interest <- tbl(Database_1, "table_of_interest")
    df_table_of_interest <- collect(db_table_of_interest).
    

    实际上,您将表格转换为本地数据帧。您需要在所有感兴趣的数据库中为所有感兴趣的表执行此操作。只要你有足够的RAM来存放你正在阅读的所有数据,它就能正常工作。

    <强> 2。复制数据库之间的标识符

    如果(就我们的情况而言)您需要在两个在不同ID下拥有相同网站的数据库之间加入记录标识符(例如网站或样本ID),那么最简单的方法是将两个数据库中的表中的ID加倍。因此,不是使用外部工作表来列出每个数据库中每个站点的所有ID,并设置匹配项,而是在每个数据库的site_table中添加一列,并引用另一个。

    只要您不需要使用实际数据设置连接表,那么您就可以了。例如,如果您需要在逐个物种和逐个环境的表中读取物种和环境数据存储在单独的数据库中,并且每个站点具有不同的ID。

    如果你确实需要连接表,那么至少你可以在执行collect()之前在两个数据库中预先选择并读取内存中的所有内容。当有大量数据需要读取时,这将节省内存需求。

    第3。将所有内容复制到一个分析数据库

    如果由于某种原因无法获得更多内存,那么理论上您可以先将所有数据复制到一个数据库中。我无法想象在任何情况下这是一个可行的选择,除了只有几个感兴趣的表,因此将它们合并到一个新的联合数据库是可行的。也许在数据集非常大且不会改变的情况下。

    如果我在此列表中遗漏了一个选项,我很乐意知道您可能找到的其他解决方案。