【问题标题】:Query with a data frame and a database使用数据框和数据库查询
【发布时间】:2013-04-15 12:25:45
【问题描述】:

我想知道是否可以像这样在数据框和数据库之间进行查询:

test <-  sqlQuery(ch,"
                  SELECT *
                  FROM table_from_database as A, dataframe as B
                  WHERE  a.id=b.id ")

【问题讨论】:

  • 也许您想指定您心目中的数据库类型。 SQL? Sqlite?
  • 这是一个带有microsoft sql server的数据库
  • 我要在这里勉强说不。您可以查询数据库,然后使用 R 中的 df 进行连接,或者(如果您有足够的数据库访问权限)您可以将 df 作为表格上传,然后在那里进行连接。
  • sqldf 包应该能够做到这一点,至少对于 SQLite/MySQL/Postgres:透明地将 data.frame 作为临时表发送到数据库,并在数据库中运行查询(使用其他表格)。
  • @joran:哦,你们这些小信仰。这是R;当然可以!

标签: sql r dataframe


【解决方案1】:

使用 RODBC 包连接到 MS SQL Server 数据库。

首先您需要进行一些设置。打开“数据源 (ODBC)”应用程序。 (在 Control Panel\System and Security\Administrative Tools 中,或在“开始”菜单下搜索。)添加用户 DSN(或系统 DSN,如果您有管理员权限并希望所有用户都可以连接)。

第 1 步:将其命名为 MyDataBase,然后选择它所在的服务器。名称不得超过 32 个字符,否则您会收到警告。
第 2 步:连接详细信息与您在 SQL Server 中使用的相同。
第 3 步:将默认数据库更改为您要连接的数据库。
完成并测试您的连接。

现在你可以使用 R 了。它很简单

library(RODBC)
channel <- odbcConnect("MyDataBase") #or whatever name you gave
query <- "SELECT * FROM MyTable WHERE x > 10"
results <- sqlQuery(query, channel)
odbcClose(channel)

如果您喜欢或讨厌向导,您可以通过编写注册表项来设置 ODBC 连接。为大代码块道歉。

#' Reads the Windows registry
#'
#' Wrapper for readRegistry that replace environment variables.
#' @param ... Passed to readRegistry
#' @return A list of registry keys.  See \code{readRegistry}.
#' @examples
#' \dontrun{
#' key <- "Software\\ODBC\\ODBCINST.INI\\SQL Server"
#' hive <- "HLM"
#' read_registry(key, hive)
#' readRegistry(key, hive)
#' }
read_registry <- function(...)
{
  ans <- readRegistry(...)
  lapply(
    ans,
    function(x)
    {
      rx <- "%([[:alnum:]]+)%"
      if(is.character(x) && grepl(rx, x))
      {
        env_var <- stringr::str_match(x, rx)[, 2]
        x <- gsub(rx, Sys.getenv(env_var), x)
      }   
      x
    }
  )
}

#' Add an ODBC data source to the Windows registry.
#' 
#' Adds an ODBC data source to the Windows registry.  
#' 
#' @param data_source_name String specifying the name of the data source to add.
#' @param database The name of the database to use as the default.
#' @param database_server The name of the server holding the database.
#' @param type Type of connection to add.  Either ``sql'' or ``sql_native''.
#' @param permission Whether the connection is for the user or the system.
#' @return Nothing.  Called for the side-effect of registering ODBC data sources.
#' @details A key with the specified data source name is created in 
#' ``Software\\ODBC\\ODBC.INI'', either in ``HKEY_CURRENT_USER'' or 
#' ``HKEY_LOCAL_MACHINE'', depending upon the value of \code{permission}.  
#' Four values are added to this key.  ``Database'' is given the value of the  
#' \code{database} arg.  ``Server'' is given the value of the 
#' \code{database_server} arg. ``Trusted_Connection'' is given the value ``Yes''.
#' ``Driver'' is given the value from the appropriate subkey of 
#' ``HKEY_LOCAL_MACHINE\\SOFTWARE\\ODBC\\ODBCINST.INI'', depending upon the type.
#' Another key with the specified data source name is created in
#' ``Software\\ODBC\\ODBC.INI\\ODBC Data Sources''.
register_odbc_data_source <- function(data_source_name, database, database_server, type = c("sql", "sql_native"), permission = c("user", "system"))
{
  #assert_os_is_windows()

  #data_source_name <- use_first(data_source_name)

  permission <- match.arg(permission)
  type <- match.arg(type)  

  #Does key exist?
  odbc_key <- readRegistry(
    file.path("Software", "ODBC", "ODBC.INI", fsep = "\\"), 
    switch(permission, user = "HCU", system = "HLM")
  )
  if(data_source_name %in% names(odbc_key))
  {
    message("The data source ", sQuote(data_source_name), " already exists.")
    return(invisible())
  }

  hive <- switch(
    permission,
    user   = "HKEY_CURRENT_USER",
    system = "HKEY_LOCAL_MACHINE"
  )
  key <- shQuote(
    file.path(hive, "Software", "ODBC", "ODBC.INI", data_source_name, fsep = "\\")
  )
  odbc_data_sources_key <- shQuote(
    file.path(hive, "Software", "ODBC", "ODBC.INI", "ODBC Data Sources", fsep = "\\")
  )

  type_name <- switch(
    type,
    sql = "SQL Server",
    sql_native = "SQL Server Native Client 11.0"
  )
  driver <- read_registry(
    file.path("SOFTWARE", "ODBC", "ODBCINST.INI", type_name, fsep = "\\"), 
    "HLM"
  )$Driver

  system0(key)
  system0(key, "/v Database /t REG_SZ /d", database)
  system0(key, "/v Driver /t REG_SZ /d", shQuote(driver))
  system0(key, "/v Server /t REG_SZ /d", database_server)
  system0(key, "/v Trusted_Connection /t REG_SZ /d Yes")
  system0(odbc_data_sources_key, "/v", data_source_name, "/t REG_SZ /d", shQuote(type_name))
}

#' Wrapper to system for registry calls
#' 
#' Wraps the \code{system} function that calls the OS shell.
#' @param ... Passed to \code{paste} to create the command.
#' @return The command that was passed to system is invisibly returned.
#' @note Not meant to be called directly.
system0 <- function(...)
{
  cmd <- paste("reg add", ...)
  res <- system(cmd, intern = TRUE)
  if(res != "The operation completed successfully.\r")
  {
    stop(res)
  } else
  {
    message(res)
  }
  invisible(cmd)
}

【讨论】:

  • 感谢您的建议,但我已经知道如何连接和查询数据库。我只是想知道是否可以在 Db 表和 data.frame 之间进行查询。看来我需要下载表格或将 data.frame 上传到 Db 中。
  • 好的,这个问题有点模棱两可。我不知道你为什么要使用 SQL 来混合来自完全不同的地方的数据。按照 Joran 的建议去做。
  • 我想知道 OP 是否找到了解决方案?我遇到了同样的问题 - 我有一个具有读取访问权限的 SQL 数据库,以及一个本地数据文件,我想用它来对患者 ID 上的 SQL 数据库中的数据进行子集化。我无法在 SQL 数据库中创建 #temp 表,因为我没有批量权限。如果我可以直接将 R 数据帧与 SQL DB 合并,我可以做到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 2016-04-07
  • 2019-08-15
  • 2012-11-16
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多