我正在尝试使用类似于此的代码的PreparedStatement:
SELECT * FROM ? WHERE name = ?
显然,当我使用setString()设置表和名称字段时会发生什么:
SELECT * FROM 'my_table' WHERE name = 'whatever'
并且查询不起作用。有没有办法设置没有引号的字符串,所以行看起来像这样:
SELECT * FROM my_table WHERE name = 'whatever'
或者我应该放弃它并使用常规语句(参数来自系统的另一部分,这些都不是由用户输入的)?
答案 0 :(得分:17)
参数不能用于参数化表,也不能参数化任何数据库对象。它们主要用于参数化WHERE / HAVING子句。
要做你想做的事,你需要自己做替换,并根据需要创建一个常规语句。
当您使用预准备语句时,这是数据库在语句上进行前处理的提示 - 例如解析字符串并可能确定执行计划。如果查询中使用的对象可以动态更改,那么数据库就无法做好太多准备工作。
答案 1 :(得分:3)
很遗憾,您无法为预准备语句参数化表名。如果需要,您可以构造一个String并将其作为动态SQL执行。
答案 2 :(得分:3)
我怀疑你的SQL是如此无限灵活。您只有有限数量的表,因此表达所需SQL的静态最终字符串的数量也是有限的。
继续使用PreparedStatement并绑定变量。这完全是值得的,在避免SQL注入问题时尤其有用。
答案 3 :(得分:3)
您所犯的错误是无法将表名作为参数传递。您应该只将值传递给SQL语句。
例: 如果你想要:
Select * from LoggedUsers where username='whatever' and privilege='whatever';
然后你要将PreparedStatement构建为:
Select * from LoggedUsers where username=? and privilege=?
setString(1, usernameObject);
setString(2, privilegeObject);
PreparedStatement的目的是降低数据库连接代码的难度和可读性。当开发人员必须在Statement实例中使用如此多的列值时,很难使用分号,逗号和加号(concat运营商)。
我认为你错误地想要利用它,而不是设计......