我想将mySQL查询存储在一个文件中。我打算用我的程序中的变量来替换它的部分字符串。
我在红宝石中使用'eval'方法,但是它有效,但感觉有点笨拙。
使用irb我做了以下事情。
>> val = 7
=> 7
>> myQuery = "select * from t where t.val = \#{val}" #escaped hash simulates reading it from file
=> "select * from t where t.val = \#{val}"
>> myQuery = eval "\"#{myQuery}\""
=> "select * from t where t.val = 7"
正如你所看到的那样有效!但为了使它工作,我必须将'myQuery'变量包装在转义引号中,整个事情看起来有点混乱。
有更简单的方法吗?
答案 0 :(得分:1)
通常,您不应使用字符串插值来构建SQL查询。这样做会让您受到SQL injection攻击,其中有人提供具有结束引号字符的输入,然后是另一个查询。例如,使用您的示例:
>> val = '7; DROP TABLE users;'
=> "7; DROP TABLE users;"
>> myQuery = "select * from t where t.val = \#{val}"
=> "select * from t where t.val = \#{val}"
>> eval "\"#{myQuery}\""
=> "select * from t where t.val = 7; DROP TABLE users;"
即使没有恶意输入,您也可能只是意外地执行您不想要的代码,例如,如果有人在其输入中包含引号。
除非绝对必要,否则避免使用eval
通常也是个好主意;它使得如果你的程序中有错误,有人可以通过将它传递给eval
来执行任意代码,并且它使代码的可维护性降低,因为你的一些源代码将从你以外的地方加载常规源树。
那么,你怎么做呢?数据库API通常包含prepare
命令,可以准备执行SQL语句。在该语句中,您可以包含?
个字符,这些字符表示可在该语句中替换的参数。然后,您可以在语句上调用execute
,传入这些参数的值,并且它们将被安全地执行,而无法让某人执行任意SQL。
以下是它在您的示例中的工作原理。假设您使用的是this MySQL/Ruby module;如果您使用的是另一个,它可能会有类似的界面,但可能不完全相同。
>> val = 7
>> db = Mysql.new(hostname, username, password, databasename)
>> query = db.prepare("select * from t where t.val = ?")
>> query.execute(val)
答案 1 :(得分:0)
您可以使用ERB模板 - 从文件中读取它们并插入变量(将<%= something%>标记转换为实际值)。
Here's the official doc,它非常完整和直截了当。
答案 2 :(得分:0)
您可以使用类似printf的语法进行字符串替换
"123 %s 456" % 23 # => "123 23 456"
这仅适用于您的程序事先知道要使用哪些变量。
答案 3 :(得分:0)
你能使用参数化查询吗?
我不知道如何在ruby中这样做,但基本上它涉及使用SQL识别的命令标记您的SQL语句,而不是使用除语句之外发送的参数。
此链接可能有所帮助:http://sqlite-ruby.rubyforge.org/sqlite3/faq.html#538670816