Java Can';第二次使用准备好的语句到达临时表
我在代码中使用临时表是为了在SQL Server、Java中[这里有一些详细的原因]。我在java中使用Stament对象执行sql查询。然而,最近我决定使用PreparedStatement来避免注入的事情 我的问题是,当使用PreparedStatement创建临时表时,我无法再次使用相同的PreparedStatement访问它。下面是一个简单的例子:Java Can';第二次使用准备好的语句到达临时表,java,sql-server,prepared-statement,sql-injection,Java,Sql Server,Prepared Statement,Sql Injection,我在代码中使用临时表是为了在SQL Server、Java中[这里有一些详细的原因]。我在java中使用Stament对象执行sql查询。然而,最近我决定使用PreparedStatement来避免注入的事情 我的问题是,当使用PreparedStatement创建临时表时,我无法再次使用相同的PreparedStatement访问它。下面是一个简单的例子: sql = "select * into #someTable from (select someColumns from someOth
sql = "select * into #someTable from (select someColumns from someOtherTable where smth = ? and smth2 = ?)"
PreparedStatement preparedStatement = conn.prepareStatement(sql);
for(int i=0; i<parameters.size(); i++){
preparedStatement.setString(i+1, parameters.get(i).toString());
}
this.rs = preparedStatement.executeQuery();
此处
this.rs=preparedStatement.executeQuery()代码>部分给出了无效的对象名#someTable'
。我只使用一个连接对象,而不关闭或重新打开它,就可以完成上述所有工作。我需要再次使用临时表。有没有办法用java中的PreparedStatement对象创建临时表,并一次又一次地重用这个临时表?关于,您在第一条语句中创建的临时表在该请求的作用域\生存期内存在。一旦调用另一个查询,您就处于不同的作用域中,因此它不再存在,因为它将被清理
解决方案是在同一个调用中发出2个请求(不太好),或者创建一个可由第二个查询访问的全局临时表(仍然不太好)
更好的解决方案是创建一个存储过程,该过程完成所有需要的操作,临时表的创建、查询和整理封装在该过程中
PS我看不到任何周围的代码,但是在这样的代码中构建查询时要小心SQL注入
相关信息:
参加派对已经很晚了,但面临着同样的问题,并且发现上面的答案是错误的:
阅读这篇关于这个问题的文章:
我发现使用PreparedStatement来创建临时表是行不通的,但是如果我改为使用语句来创建临时表,它就会起作用(即使没有useFmtOnly)。
因此,请从这篇文章开始并在此基础上继续:
final String sql = "INSERT INTO #Bar VALUES (?)";
try (Connection c = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
try (Statement s = c.createStatement()) {
s.execute("CREATE TABLE #Bar(c1 int)");
}
try (PreparedStatement p1 = c.prepareStatement(sql); PreparedStatement p2 = c.prepareStatement(sql)) {
((SQLServerPreparedStatement) p1).setUseFmtOnly(true);
ParameterMetaData pmd1 = p1.getParameterMetaData();
System.out.println(pmd1.getParameterTypeName(1)); // prints int
ParameterMetaData pmd2 = p2.getParameterMetaData(); // throws exception, Invalid object name '#Bar'
}
}
谢谢你的回答。我只使用1个连接,而不关闭和重新打开它来完成所有这些工作。@JollyRoger但你打了不止一个电话?首先创建表,然后返回一些数据,因此它们有不同的作用域。您能解释一下调用的含义吗。这两部分代码实际上在一个方法中结合在一起。您调用SQL Server在一行代码上构建临时表,然后尝试在另一行代码上查询该临时表。因此,代码可以采用相同的方法,但是您与SQL Server进行了两次单独的对话,并且第二次对话中不存在临时表。是的,这是正确的,但例如,如果我使用语句而不是PreparedStatement,我可以多次访问#Dentiable。语句对象是否不创建另一个调用?我需要从#tentable和#tentable的计数中选取一些列。有没有办法在不创造“诱惑”两次的情况下一起实现这些目标?
final String sql = "INSERT INTO #Bar VALUES (?)";
try (Connection c = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
try (Statement s = c.createStatement()) {
s.execute("CREATE TABLE #Bar(c1 int)");
}
try (PreparedStatement p1 = c.prepareStatement(sql); PreparedStatement p2 = c.prepareStatement(sql)) {
((SQLServerPreparedStatement) p1).setUseFmtOnly(true);
ParameterMetaData pmd1 = p1.getParameterMetaData();
System.out.println(pmd1.getParameterTypeName(1)); // prints int
ParameterMetaData pmd2 = p2.getParameterMetaData(); // throws exception, Invalid object name '#Bar'
}
}