无法通过RODBC运行SQL查询

时间:2014-05-15 15:20:37

标签: sql r oracle rodbc

我有一个名为q_cleanup.sql的文件,我通过readLines()读入R。这个文件有很多我们写的小查询来清理一些非常丑陋的数据。一旦我读入R并处理文本,我就会在文件中运行每个查询。

直接通过Oracle的SQL Developer和Tora运行时,所有查询都有效。 通过RODBC运行时,某些查询失败。

例如。该文件包含以下两个查询(剪切并粘贴到文件中)

update T_HH_TMP
set program_type = 'not able to contact'
where
    program_type like '%n0t%'
    or program_type like '%not able to%'
;

update T_HH_TMP
set program_type = 'hh substance use'
where program_type like '%hh substance abuse%'
;

第一个查询运行。第二个查询错误。以下是我的cleanup.R文件中的相关部分。命令odbcStart()是我为简化打开和关闭rodbc连接而构建的函数。这不是问题。

odbcStart()

qry <- readLines("sql/q_cleanup.sql")
qry <- paste(qry[-grep("--", qry)] , collapse=" ")
qry <- unlist(strsplit(qry, ";"))

for(i in seq_along(qry)) {
    print("------------------------------------------------------------")
    print(qry[i])
    print(sqlQuery(con, qry[i]))
}

odbcClose(com)

我正在剥离任何我能想到的可能导致问题的内容,我的字符串用双引号括起来,而我的查询只包含单引号。然而,输出看起来像这样:

[1] "------------------------------------------------------------"
[1] "  update T_HH_TMP set program_type = 'not able to contact' where     program_type like '%n0t%'     or program_type like '%not able to%' "
character(0)
[1] "------------------------------------------------------------"
[1] "  update T_HH_TMP set program_type = 'hh substance use' where program_type like '\\%hh substance abuse\\%' "
[1] "[RODBC] ERROR: Could not SQLExecDirect '  update T_HH_TMP set program_type = 'hh substance use' where program_type like '\\%hh substance abuse\\%' '"

我不认为%是问题,因为第一个查询运行得很好。 有帮助吗?我真的更愿意在R中编写所有这些查询的脚本。

1 个答案:

答案 0 :(得分:0)

我以为我会分享我所知道的。我有一个解决方案,即使我认为它是次优的,因为它不必要地使我的工作流程变得复杂。

我不知道问题是由Oracle服务器,SQL Plus引起的,还是与Windows上的R / Emacs有关。我不是Oracle专家,我工作的办公室将在夏季结束前搬到Vertica,所以我不会投入太多精力来解决这个问题。

我正在使用sqlplus.exe来运行创建视图或存储过程的SQL语法,然后我通过R运行视图/ SP。因此,我必须通过R传递给Oracle的命令是SIMPLE,它可以处理它。

要从R编写sqlplus脚本,我正在使用以下函数,我将来有一天会改进。它没有错误处理,它基本上假设你很好,但它确实有效。

#' queryFile() runs a longish series of queries in a .sql file.
#' It is very important to understand that the path to sqlplus is hardcoded
#' because Windows has a shitty path system. It may not run on another system
#' without being edited.
#'
#' @param file - The relative path to the .sql file.
#' @return output - Vector containing the results from sqlplush
#'
queryFile <- function(file){
    cmd  <- "c:/Oracle/app/product/11.2.0/client_1/sqlplus.exe %user/%password@%db     @%file"
    cmd  <- gsub("%user", getOption("DataMart")$uid, cmd )
    cmd  <- gsub("%password", getOption("DataMart")$pwd, cmd )
    cmd  <- gsub("%db", getOption("DataMart")$db, cmd )
    cmd  <- gsub("%file", file, cmd )
    print(cmd)
    output <- system(cmd, intern=TRUE)
    return(output)
}

显然Markdown不喜欢我的Roxygen风格评论。遗憾。

此功能的关键在于您使用SQL语法将文件传递给它。它使用SQL Plus来运行语法。要存储/访问用户名,密码等,我使用名为〜/ passwords.R的文件。它有一系列的options()命令如下所示:

## Fake example.
options( DataMart = list(
              uid       = "user_name"
             ,pwd       = "user_password"
             ,db        = "TNS Database"
             ,con_type  = "ODBC"
             ,srvr_type = "Oracle"
                    )
        )

最后两个(cont_type和srvr_type)只是我想记录的内容。他们并不是真的需要。我在我的文件中有~10个,我用它来提醒我正在编写哪个数据库服务器。我必须写反对SQL Server,Vertica,MySQL和Oracle(不同的项目/雇主),这对我有帮助。

我提供的函数使用options()来访问必要的信息,然后运行SQLPlus.exe。我可以将SQLPlus添加到我的Window路径中,但我试图让这个函数半独立,看起来我们的IT人员对SQL Plus所处的位置保持一致(当然有不同的版本在运行,但至少我不喜欢不必向那些不是程序员的人解释路径的想法。)