如何为java预处理语句插入使用tablename变量

For*_*DMC 41 java sql variables dynamic prepared-statement

我正在使用java PreparedStatment对象来构造一系列批量INSERT查询.查询语句的格式是......

String strQuery = "INSERT INTO ? (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);";
Run Code Online (Sandbox Code Playgroud)

...所以字段值和表名都是变量(即,我有多个具有相同列格式的表,其中每个插入将指向不同的一个).如果删除"?",我可以让执行工作 tablename变量和硬代码,但每个预处理语句将被插入到不同的表中,因此需要保留一个变量,我在执行批处理查询之前立即填充...

stmt.setString(1, "tableName1");
Run Code Online (Sandbox Code Playgroud)

我怎么能让这个变成动态变量呢?

fmu*_*car 61

你不能.您需要使用字符串连接/占位符和String.format构造sql.prepared语句用于列值而不是表名.

  • 这是否意味着使用动态表名称无法进行SQL注入保护? (21认同)
  • 谢谢大家......似乎我不知道我要插入的表名,直到交换每行的变量,最好是在DB存储过程中构造插入.然后将每行的所有参数传递给存储过程,然后让DB处理tablename操作.不管怎样,谢谢大家的回复.:-) (2认同)
  • 每个人都在谈论 SQL 注入。但我很难想象用户可能会被提示输入表名。如果您对多个表运行相同的查询,则仅在应用程序代码内创建并传递表名称作为参数。 (2认同)
  • 我来到这里就知道答案了。我目前正在寻找可以链接的参考资料,以便 secops 人员可以更轻松地接受这个答案。 (2认同)

tro*_*jan 9

您可以使用占位符代替表名,然后将其替换为您的表名.

String strQuery = "INSERT INTO $tableName (col1, col2, col3, col4, col5)
                   VALUES (?,?,?,?,?,?);";
Run Code Online (Sandbox Code Playgroud)

当你知道tablename时替换

String query =strQuery.replace("$tableName",tableName);
stmt =conn.prepareStatement(query);
Run Code Online (Sandbox Code Playgroud)

  • 易受SQL注入攻击.不要使用这个答案,孩子们! (49认同)
  • @SigmaX那么你的解决方案是什么,不易受SQL注入攻击? (12认同)
  • 只有当$ tablename取自用户输入时,对吧?但是,如果单选按钮选择返回枚举器值,或者将$ tablename的可能值限制为已定义集的任何其他方法,那就没关系了? (9认同)
  • @Mahdi第一个目标应该是避免使用动态SQL查询.但是,如果必须,我将从服务器检索现有表的列表,并将其用作白名单,以检查tableName是否是有效的现有表的名称. (5认同)
  • 它完全取决于myTablename的来源.请参阅Jonathan Warner上面的评论 (3认同)