2013-04-23 2 views
9

데이터베이스에 전달하려는 변수가 R입니다. I paste은 Google 검색 결과를 읽을 때 많은 추천을 받았지만 SQL 주입 취약점으로 인해 안전하지 않습니다. 나는 다음과 같은 것을 선호합니다 :RODBC로 매개 변수화 된 쿼리

x <- 42 
sqlQuery(db, 'SELECT Id, Name FROM People WHERE Age > ?;', bind=c(x)) 

RODBC에서 매개 변수화 된 쿼리를 사용할 수 있습니까? 그렇지 않은 경우이를 지원하는 대체 라이브러리가 있습니까?

SQL Server RODBC 1.3-6 및 R 3.0.0을 사용하고 있습니다.

+0

. 'sprintf'는 제가 아는'붙여 넣기'옵션뿐입니다.하지만 위생 화도하지 않습니다. – joran

+0

"placeholder"로 [here] (http://stackoverflow.com/a/1645086/142019) 언급 된 것 같지만 여전히 그들을 사용하는 방법을 찾을 수 없습니다. –

+1

붙여 넣기 전에 문자열을 청소해도 똑같은 일을하지 못합니까? –

답변

5

다음은 RODBC를 사용하여 알고있는 옵션입니다. 나는 이 기본적으로 RSQLite가 매개 변수 바인딩을 기본적으로 지원한다는 것을 알고 있지만 대부분은 대부분 옵션이 아닙니다.

# Note that sprintf doesn't quote character values. The quotes need 
# to be already in the sql, or you have to add them yourself to the 
# parameter using paste(). 
q <- "select * from table where val1 = '%s' and val2 < %d and val3 >= %f" 
sprintf(q,"Hey!",10,3.141) 

# The gsub route means you can't easily use a single placeholder 
# value. 
q <- "select * from table where val1 = '?' and val2 < ? and val3 >= ?" 
gsub("?","Value!",q,fixed = TRUE) 

나는 다양한 매개 변수를 필요로 내 작품에 대한 통조림 쿼리를 많이 다룬다. 필자의 경우에는 SELECT 권한 만 있고, 나는 사람 만이 내 코드를 실행하므로 검증에 대해 걱정할 필요가 없다.

모든 내 쿼리를 별도의 .sql 파일로 저장할 수 있도록 기본적으로 gsub 경로가 있습니다. 이것은 쿼리가 종종 내 .R 파일에 보관하는 것이 다루기 힘들 정도로 길어질 때까지 만큼 길기 때문입니다. 이들을 별도로 유지하면 이 더 적절한 SQL이되도록 서식을 지정하고 유지 관리하는 것이 더 쉬워집니다.

그래서 저는 .sql 파일 에서 쿼리를 읽고 모든 매개 변수를 바인딩하는 몇 가지 작은 함수를 작성했습니다. 콜론으로 표시된 매개 변수가 인 쿼리를 작성합니다 (예 : :param1:, :param2:). gsub_all은 기본적으로 매개 변수를 통해 루프 args위한 단지 래퍼입니다

function (path, args = NULL) 
{ 
    stopifnot(file.exists(path)) 
    if (length(args) > 0) { 
     stopifnot(all(names(args) != "")) 
     sql <- readChar(path, nchar = file.info(path)$size) 
     p <- paste0(":", names(args), ":") 
     sql <- gsub_all(pattern = p, replacement = args, x = sql) 
     return(sql) 
    } else { 
     sql <- readChar(path, nchar = file.info(path)$size) 
     return(sql) 
    } 
} 

매개 변수 값의 명명 된 목록입니다

는 다음 나는 .SQL 파일을 읽기 위해이 기능을 사용합니다.

내가 알고있는 옵션 범위입니다.

+1

쿼리에 매개 변수를 전달하는 것은 문자열 조작으로 문자열을 생성하는 것과 정반대입니다 .느린 (SQL 인젝션 공격을 허용), 깨지기 쉬운 (값을 문자열로 서식을 지정할 때 지역화 문제로 인한) 느림 –

+0

@PanagiotisKanavos R에서 RODBC를 가장 많이 사용하는 방법은 데이터 분석가가 db에서 데이터를 검색하는 것입니다. 이것은 Shiny와 같은 것들의 출현으로 다소 변화하지만, 대다수의 사용자는 적은 수로 작성한 쿼리 만 제출합니다. 따라서 많은 RODBC 사용자가 이러한 문제를 염려하지 않을 것입니다. – joran

+0

반대로 date 매개 변수를 전달하려고하거나 유니 코드 대 ANSI 문자열을 전달하는 올바른 구문을 사용하지 않거나 데이터 정렬 충돌이있는 사용자에게는 영향을줍니다. 데이터 분석가들은 그러한 실수를 저지르기 쉽습니다. 어쨌든, OP는 SQL 문자열을 만드는 방법이 아닌 * 매개 변수화 된 쿼리 *를 사용하는 방법을 질문했습니다. –

9

마테우스 Zoltak은 (브라이언 리플리와 마이클 랩 슬리의 작업을 기반으로) 2014 년 RODBCext 패키지를 썼다 :

conn = odbcConnect('MyDataSource') 

sqlPrepare(conn, "SELECT * FROM myTable WHERE column = ?") 
sqlExecute(conn, 'myValue') 
sqlFetchMore(conn) 

출처 : 제가 알고하지 않는 것이 http://cran.r-project.org/web/packages/RODBCext/vignettes/Parameterized_SQL_queries.html

+1

예 - 이것이 더 나은 해결책입니다. 적절한 매개 변수화는 보안 문제 (SQL 주입)를 줄이고 캐시 된 쿼리 계획으로 인해 성능을 향상시킬 수 있습니다 (쿼리가 많이 실행되는 경우에만 중요). 더 나은 소프트웨어 장인 패턴 - 나는 이런 종류의 솔루션을 권장합니다. – ripvlan

관련 문제