我想知道是否还有使用预准备语句指定返回的列名。
我正在使用MySQL和Java。
当我尝试时:
String columnNames="d,e,f"; //Actually from the user...
String name = "some_table"; //From user...
String query = "SELECT a,b,c,? FROM " + name + " WHERE d=?";//...
stmt = conn.prepareStatement(query);
stmt.setString(1, columnNames);
stmt.setString(2, "x");
我得到这种类型的陈述(在执行前打印)。
SELECT a,b,c,'d,e,f' FROM some_table WHERE d='x'
但我希望看到:
SELECT a,b,c,d,e,f FROM some_table WHERE d='x'
据我所知,我知道我不能为表名执行此操作 here,但是想知道是否有某种方法可以为列名称执行此操作。
如果没有,那么我只需要尝试确保我清理输入,这样就不会导致SQL注入漏洞。
答案 0 :(得分:32)
这表明数据库设计错误。用户不需要知道列名称。创建一个真正的数据库列,其中包含这些“列名称”并将数据存储在其中。
无论如何,不,您不能将列名设置为PreparedStatement
值。您只能将值列设置为PreparedStatement
值
如果您想继续这个方向,则需要清理列名并自行连接/构建SQL字符串。引用单独的列名称并使用String#replace()
来转义列名称中的相同引号。
答案 1 :(得分:15)
准备允许列名称的白名单。使用“查询”查找白名单以查看列名是否存在。如果没有,请拒绝查询。
答案 2 :(得分:2)
我认为这种情况不起作用,因为准备好的声明的重点是阻止用户输入未转义的查询位 - 所以你总是要引用或转义文本。
如果要安全地影响查询结构,则需要使用Java清理此输入。
答案 3 :(得分:0)
使用SQL接口不利于Statement Interface作为优势。 例如:
st=conn.createStatement();
String columnName="name";
rs=st.executeQuery("select "+ columnName+" from ad_org ");
答案 4 :(得分:0)
public void MethodName(String strFieldName1, String strFieldName2, String strTableName)
{
//Code to connect with database
String strSQLQuery=String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName);
st=conn.createStatement();
rs=st.executeQuery(strSQLQuery);
//rest code
}
答案 5 :(得分:0)
接受的答案实际上是不正确的。尽管OP方法表明数据库设计不正确,但业务逻辑(例如MySQL IDE)可能会要求它
无论如何,对于MySQL准备好的语句,您需要知道?
是用于值的,但是如果您需要转义列名,表名等,请使用??
。
类似的事情会起作用:
SELECT ??, ??, ?? FROM ?? WHERE ?? < ?
将值设置为['id', 'name', 'address', 'user', 'id', 100]
答案 6 :(得分:-3)
以下是java中的解决方案。
String strSelectString = String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName);