2013-04-23 13 views
9

Ich habe eine Variable in R, die ich an eine Datenbank übergeben möchte. I könnte verwenden paste wie viele vorschlagen beim Lesen von Google-Ergebnissen, aber das ist wegen SQL-Injection-Schwachstellen unsicher. Ich würde eher etwas wie das bevorzugen:Parametrisierte Abfragen mit RODBC

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

Ist es möglich, parametrisierte Abfragen mit RODBC zu verwenden? Wenn nicht, gibt es eine alternative Bibliothek, die sie unterstützt?

Ich benutze SQL Server, RODBC 1.3-6 und R 3.0.0.

+0

Nicht, dass ich wüsste. 'sprintf' ist die einzige andere Option, die ich kenne, aber das macht auch keine Bereinigung. – joran

+0

Es scheint [hier] (http://stackoverflow.com/a/1645086/142019) als "Platzhalter" erwähnt zu werden, aber ich konnte immer noch nicht finden, wie man sie benutzt. –

+1

Würde das Reinigen der Saite vor dem Einfügen nicht dasselbe bewirken? –

Antwort

5

Dies sind die Optionen, die ich von der Verwendung von RODBC kenne. Ich weiß , dass RSQLite native Parameterbindung unterstützt, aber das ist normalerweise keine Option für die meisten Menschen.

# 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) 

beschäftige ich mich mit vielen Konserven Anfragen für meine Arbeit, die verschiedenen Parameter erfordern. Da in meinem Fall habe ich nur SELECT Privilegien, und ich bin die einzige Person, die meinen Code läuft, muss ich nicht wirklich über die Validierung kümmern.

Also ich bin im Grunde die gsub Route gegangen, um in der Lage zu sein, alle meine Abfragen in separaten .SQL-Dateien zu speichern. Das liegt daran, dass die Abfragen oft lang genug sind, um sie in meinen .R-Dateien zu speichern. Indem ich sie getrennt aufbewahre, erleichtert es mir , sie mit Formatierung und Hervorhebung zu bearbeiten und zu pflegen, dass mehr SQL-geeignet ist.

Also habe ich einige kleine Funktionen geschrieben, die eine Abfrage aus einer .SQL-Datei lesen und alle Parameter binden. Ich schreibe die Abfrage mit Parametern, die mit Doppelpunkten bezeichnet sind, , d. H. :param1:, :param2:.

Dann verwende ich diese Funktion, um die SQL-Datei zu lesen:

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) 
    } 
} 

wo gsub_all grundsätzlich für eine nur ein Wrapper für Schleife ist über die Parameter und args ist eine benannte Liste von Parameterwerten.

Das ist die Palette der Möglichkeiten, die mir bekannt sind.

+1

Das Übergeben von Parametern an eine Abfrage ist das genaue Gegenteil des Konstruierens der Zeichenfolge mit String-Manipulation .Es ist gefährlich (erlaubt SQL-Injection-Attacken), zerbrechlich (Unterbrechungen aufgrund von Lokalisierungsproblemen beim Formatieren von Werten in Strings) und langsam –

+0

@PanagiotisKanavos Die am häufigsten verwendete Verwendung von RODBC aus R besteht darin, dass Datenanalysten Daten selbst aus einer Datenbank abrufen. Dies ändert sich etwas mit dem Aufkommen von Dingen wie Shiny, aber die Mehrheit der Benutzer sendet nur Anfragen, die sie geschrieben haben, in kleinen Zahlen. Keines dieser Probleme dürfte für viele RODBC-Nutzer ein Problem darstellen. – joran

+0

Im Gegensatz dazu wirken sie sich auf Personen aus, die versuchen, einen Date-Parameter zu übergeben, oder vergessen, die richtige Syntax zu verwenden, um Unicode vs ANSI-Strings zu übergeben, oder Kollationskonflikte zu begegnen. Datenanalysten machen solche Fehler viel wahrscheinlicher. In jedem Fall hat das OP gefragt, wie man * parametrisierte Abfragen * verwendet und nicht wie man eine SQL-Zeichenfolge erstellt. –

9

Mateusz Zoltak schrieb RODBCext Paket 2014 (basierend auf der Arbeit von Brian Ripley und Michael Lapsley):

conn = odbcConnect('MyDataSource') 

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

Quelle: http://cran.r-project.org/web/packages/RODBCext/vignettes/Parameterized_SQL_queries.html

+1

Ja - das ist eine bessere Lösung. Die richtige Parametrisierung reduziert Sicherheitsprobleme (SQL Injection) und kann die Performance aufgrund zwischengespeicherter Abfragepläne verbessern (nur wichtig, wenn die Abfrage häufig ausgeführt wird). Als eine bessere Software Handwerker Muster - ich empfehle diese Art von Lösung. – ripvlan

Verwandte Themen