如何为java准备的语句插入使用tablename变量

如何为java准备的语句插入使用tablename变量,java,sql,variables,dynamic,prepared-statement,Java,Sql,Variables,Dynamic,Prepared Statement,我正在使用java PreparedStation对象来构造一系列批处理的插入查询。查询语句的格式为 String strQuery = "INSERT INTO ? (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);"; …因此字段值和表名都是变量(即,我有多个具有相同列格式的表,每个插入都将指向不同的表)。如果我删除“?”tablename变量和硬代码,我可以使执行正常工作,但每个准备好的语句都将插入到不同的表中,因此需要保留一个变量,

我正在使用java PreparedStation对象来构造一系列批处理的插入查询。查询语句的格式为

String strQuery = "INSERT INTO ? (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);";
…因此字段值和表名都是变量(即,我有多个具有相同列格式的表,每个插入都将指向不同的表)。如果我删除“?”tablename变量和硬代码,我可以使执行正常工作,但每个准备好的语句都将插入到不同的表中,因此需要保留一个变量,以便在执行批处理查询之前立即使用

stmt.setString(1, "tableName1");

我怎样才能让它成为一个动态变量呢?

如果您的表名仅来自您自己的代码

…您需要将其添加到原始字符串中:

String tableName = "some_table_name";
// some other code
String strQuery = "INSERT INTO " + tableName + " (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);";

如果表名来自任何其他不可靠的源(用户输入,其他代码传入的参数),请不要这样做,然后查看其他答案

表名不能用作参数。它必须是硬编码的。尝试以下方法:

String tableName = "tableName1";
String strQuery = "INSERT INTO " + tableName + " (col1, col2, col3, col4, col5) VALUES (?,?,?,?,?,?);";

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

一种替代方法可以是
String。format

e、 g


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

String strQuery = "INSERT INTO $tableName (col1, col2, col3, col4, col5)
                   VALUES (?,?,?,?,?,?);";
当你知道这个表名时,就把它替换掉

String query =strQuery.replace("$tableName",tableName);
stmt =conn.prepareStatement(query);

谢谢各位…在交换每一行的变量之前,我似乎不知道要插入的表名,最好是在DB存储过程中构造插入。然后将每行的所有参数传递到存储的进程中,然后让DB处理tablename操作。不过还是要感谢各位的回复。:-)这是否意味着使用动态表名不可能进行SQL注入保护?@Richard I得出了同样的结论,这听起来很愚蠢,但至少对照数据库中可用表的列表检查表名相当容易。@RichardTingle不是不可能,只是更难。例如,在MySQL中,您可以将表名括在backticks中,并使用双backticks转义backticks:使用一个以动态tablename为键的hashmap和一个动态sql字符串来第一次准备预处理语句,然后存储它。下次只需根据hashmap中的表名检索准备好的语句。prepared语句的思想是减少每次sql编译,并在运行时绑定数据。易受sql注入的影响。孩子们,不要用这个答案!。。。那要看你的桌子名来自哪里。如果它来自用户或不可靠的客户,那么我同意你的看法。但是,如果它包含在您自己的方法中,那么字符串的不变性意味着它肯定是安全的。技术上是正确的。但一个好的答案仍然需要一个大的免责声明:“作为一项规则,避免使用动态SQL查询,因为这被广泛认为是不安全的做法。如果必须这样做,请确保您确切知道自己在做什么。”易受SQL注入的影响。孩子们,不要用这个答案!只有$tablename是从用户输入中获取的,对吗?但是,如果单选按钮选择返回枚举数值,或者任何其他方法将$tablename的可能值限制在一个定义的集合内,那就没有问题了?@SigmaX那么什么是不易受SQL注入攻击的解决方案?@Mahdi第一个目标应该是避免使用动态SQL查询。但如果必须这样做,我会从服务器检索现有表的列表,并将其用作白名单,以检查tableName是否是有效的现有表的名称。这完全取决于myTablename的来源。见Jonathan Warner在上面的评论这是一种常见的“哦,我知道SQL注入是什么”妄想症——这完全取决于myTablename的来源。同意。但是,和大多数安全问题一样,大部分问答网站的访问者不会理解他们需要关注myTablename的来源。所以答案需要限定。没错,你可以在你的原始评论中提出这一点,而不是大写字母8=}
String query =strQuery.replace("$tableName",tableName);
stmt =conn.prepareStatement(query);