2014-01-23 3 views
4

Мне интересно, можно ли вызвать функцию SQL в функции R?вызов функции SQL внутри функции R

Скажем, например, что у меня есть это фиктивные данные и SQL функции, написанные в Postgres 9.3

CREATE TABLE tbl (
    id VARCHAR(2) PRIMARY KEY 
    ,name TEXT 
    ,year_born NUMERIC 
    ,nationality TEXT 
); 

INSERT INTO tbl(id, name, year_born, nationality) 
VALUES ('A1','Bill',2001,'American') 
     ,('B1','Anna',1997,'Swedish') 
     ,('A2','Bill',1991,'American') 
     ,('B2','Anna',2004,'Swedish') 
     ,('B3','Anna',1989,'Swedish') 
     ,('A3','Bill',1995,'American'); 


CREATE FUNCTION retrieve_data(TEXT) 
RETURNS TABLE (id VARCHAR(2), name TEXT, year_born NUMERIC, nationality TEXT) AS 
$func$ 
SELECT id, name, year_born, nationality 
FROM tbl 
WHERE name=$1 OR nationality=$1 
GROUP BY 1 
ORDER BY 1 
$func$ LANGUAGE sql 

я могу доступ к этим данным и запустить функцию в пределах R среды через RPostgreSQL и sqldf пакетов, как показано ниже;

require(RPostgreSQL) 
require(sqldf) 

options(sqldf.RPostgreSQL.user = "****", 
     sqldf.RPostgreSQL.password = "****", 
     sqldf.RPostgreSQL.dbname = "test_db", 
     sqldf.RPostgreSQL.host = "localhost", 
     sqldf.RPostgreSQL.port = 5432) 

sqldf("select * from retrieve_data('Bill')") 

Но есть способ вызова выше SQL функции в пределах R функции, например, как;

myfunc <- function(name) { 
sqldf("select * from retrieve_data(name)") 
} 

myfunc('Bill') 

Любые указатели были бы очень благодарны, спасибо!

UPDATE

Используя $fn префикс в sqldf пакете как это было предложено @G. Гротендик

myfunc2 <- function(name){ 
    fn$sqldf("select * from retrieve_data('$name')") 
} 

Или обменять выше options на код ниже, чтобы соответствовать предложенный ответ на @dickoa

require(RPostgreSQL) 
drv <- dbDriver("PostgreSQL") 
con <- dbConnect(drv, 
       user="****", 
       password="****", 
       dbname="test_db", 
       host="localhost", 
       port=5432) 
+1

Попробуйте 'п $ sqldf ("выберите * из retrieve_data ($ название)")' как в примере 5 на sqldf Домашняя страница: https://code.google.com/p/sqldf/#Example_5._Insert_Variables –

ответ

3

Хитрость заключается в том, чтобы использовать shQuote и sprintf но есть умный способ сделать это, я Конечно.

library(sqldf) 
library(RPostgreSQL) 

options(sqldf.RPostgreSQL.user = "****", 
     sqldf.RPostgreSQL.dbname = "****", 
     sqldf.RPostgreSQL.host = "localhost", 
     sqldf.RPostgreSQL.port = 5432) 

myfunc <- function(name) 
    sqldf(sprintf("select * from retrieve_data(%s)", shQuote(name))) 

myfunc('Bill') 
## id name year_born nationality 
## 1 A1 Bill  2001 American 
## 2 A2 Bill  1991 American 
## 3 A3 Bill  1995 American 

Если вы хотите, чтобы избежать процитировать строки, то вы можете использовать

drv <- dbDriver("PostgreSQL") 
con <- dbConnect(drv, dbname = "tempdb") 
myfunc2 <- function(name) 
    dbGetQuery(con, "select * from retrieve_data($1)", name) 

myfunc2("Bill") 
## id name year_born nationality 
## 1 A1 Bill  2001 American 
## 2 A2 Bill  1991 American 
## 3 A3 Bill  1995 American 
+3

Я думаю, вам нужно было бы 'postgresqlEscapeStrings' вместо' shQuote', потому что вам нужно ссылаться на SQL (и postgresql), а не на командной строки оболочки. (Хотя я не уверен, что вы используете для аргумента 'con' в этом случае.) –

+0

@BrianDiggs Это основная проблема, я не знаю, как найти объект типа' con', используя 'sqlf'. Я отредактировал и предложил более чистый подход – dickoa

+0

@ dickoa: Большое спасибо! –