Print sql statement craeted by DBI::dbBind

烂漫一生 提交于 2019-12-20 03:33:11

问题


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:

  1. 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.

  2. 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.

  3. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!