2011-03-30 46 views
4

继我之前关于method design的一个问题之后,我建议我将SQL查询作为参数化查询来实现,而不是简单的字符串。简单参数化查询出错-Java/SQL

我从来没有使用参数化查询之前,所以我决定用一些简单的入手,采取以下选择声明:

String select = "SELECT * FROM ? "; 

PreparedStatement ps = connection.prepareStatement(select); 
ps.setString(1, "person"); 

这给了我下面的错误:“[SQLITE_ERROR] SQL错误或缺少数据库(接近“?”:语法错误)“

然后我尝试了一个修改后的版本,它有其他标准;

String select = "SELECT id FROM person WHERE name = ? "; 

PreparedStatement ps = connection.prepareStatement(select); 
ps.setString(1, "Yui"); 

这个版本工作得很好,在我的第一个例子我失去了参数化查询点还是我错误地建设呢?

谢谢!

回答

9

简而言之,SQL绑定无法绑定表,只有where子句的值。这里有一些与“编译”准备好的SQL语句有关的技术上的原因。一般来说,参数化查询的目的是通过防止SQL注入来提高SQL的安全性,并且它具有使查询更“模块化”的优势,但不能动态设置表名称(因为它假定你已经知道表将会是什么)。

+0

因此,如果我想返回一个包含来自表(SELECT * FROM person)的所有结果的ResultSet,那么不能将它作为一个字符串进行隐式输入来完成。 – 2011-03-30 19:24:02

+0

如果你问你是否可以通过参数化查询概括select * from

,答案是否定的。你需要有一个专用的SQL或者构建你自己的select *的通用版本。 – 2011-03-30 19:31:12

+0

是的,这就是我的意思:),这是一个耻辱。我想这样做,所以我可以使用自上次执行命令以来所做的更改来更新我的JTable,您知道刷新表的更好方法吗? – 2011-03-30 19:33:45

1

准备好的语句仍然是SQL,需要使用适当的where子句构造;即其中x = y。他们的优点之一是,它们在第一次被看到时被RDMS解析,而不是每次被发送时都被加以解析,这加快了后续执行具有不同绑定值的相同查询的速度。

2

如果你想从PERSON表中的所有行,这里是你应该做的:

String select = "SELECT * FROM person"; 

PreparedStatement ps = connection.prepareStatement(select); 

变量绑定不能动态绑定表名称为他人如上所述。 如果你有表名即将到您的方法作为变量,您可以构建整个查询如下:

String select = "SELECT * FROM " + varTableName; 
PreparedStatement ps = connection.prepareStatement(select); 

参数化查询是用于查询的字段名称 - 而不是表名!

+0

感谢您的详细示例,让事情变得更清晰:) – 2011-03-30 19:39:43