问题
I want to print the sql syntax created with DBI::dbBind while creating safe parametrized query:
conn <- #create connection
stmt <- "select * from dbo.mytable where mycolumn = ?"
params = list("myvalue")
query <- DBI::dbSendQuery(conn, stmt)
DBI::dbBind(query, params) # how print created sql syntax?
in the last line the sql syntax is created. How to view it?
回答1:
I'll formalize my comment into an answer.
"Binding" does not change the query, it merely "augments" a query with objects that are treated solely as data, vice intermingled with code.
The latter intermingling can be problematic for a few reasons:
Malevolent code deploying "SQL Injection" (https://xkcd.com/327/, and a wiki explanation). In short, it takes advantage of closing out a quoted string or literal and executing SQL code directly, perhaps to delete or modify data, perhaps to extract data.
Innocently enough, if the "data" you add to the query contains quotes that are not escaped properly, you could inadvertently perform your own SQL injection, though perhaps less likely to do as "Bad Things" as #1 would do.
Optimization of SQL code. Most DBMSes will analyze and optimize a SQL query so that it performs better, takes advantage of keys, etc. They often remember queries, so that a repeated query does not need to be re-analyzed, saving time. If you intermingle data/parameters in with the raw SQL query text, then when you change one thing about it (even just one digit in a parameter), the DBMS will likely need to re-analyze the query. Inefficient.
There are functions that facilitate escaping or quoting literals and strings, and if you feel you must put literals in your SQL query, then I urge you to use them. These include (but are not limited to) DBI::dbQuoteString
, DBI::dbQuoteLiteral
, and DBI::dbQuoteIdentifier
.
Another such function is glue::glue_sql
, which handles correct quoting/escaping of literals and identifiers, to "make[s] constructing SQL statements safe and easy" (quoted from the github repo). This is "just" string interpolation, so while it should protect you just fine against #1 and #2 above, it does not necessarily permit/encourage #3.
(It only takes one mis-quoting to remind you which is used where for your particular DBMS.)
For the record, binding is rather simple, as provided in its documentation:
iris_result <- dbSendQuery(con, "SELECT * FROM iris WHERE [Petal.Width] > ?")
dbBind(iris_result, list(2.3))
results <- dbFetch(iris_result)
If you want, you can re-use the same res
(at least in some DBMSes, not tested on all), as in
# same iris_result as above
dbBind(iris_result, list(2.5))
dbFetch(iris_result)
dbBind(iris_result, list(3))
dbFetch(iris_result)
dbBind(iris_result, list(3.2))
dbFetch(iris_result)
As many times as you need, ultimately finishing with
DBI::dbClearResult(iris_result)
来源:https://stackoverflow.com/questions/54235874/print-sql-statement-craeted-by-dbidbbind