第二次使用预准备语句无法访问临时表



我在代码中使用临时表是为了在SQL Server、Java中[这里有一些长期的原因]。我使用java中的Stament对象执行sql查询。然而,最近我决定使用PreparedStatement来避免注入的事情。

我的问题是,当使用PreparedStatement创建临时表时,我无法再次使用相同的prepared语句访问它。这里有一个简单的例子:

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();

在这里之前,还可以。在获得ResultSet并对其进行处理之后,或者不获得仅用于preparedStatement.execute()的ResultSet都没有区别,我就无法再次访问#someTable对象。

sql = "select count(*) from #someTable"
preparedStatement = conn.prepareStatement(sql);
this.rs = preparedStatement.executeQuery();

这里CCD_ 2部分给出了CCD_。我只使用一个Connection对象,不关闭或重新打开它,就完成了上面的所有操作。我需要再次使用那个临时表。有没有什么方法可以用java中的PreparedStatement对象创建临时表,并一次又一次地重用这个临时表?问候,

派对来晚了,但面临同样的问题,发现上面的答案是错误的:

阅读这篇关于这个问题的文章:https://learn.microsoft.com/en-us/sql/connect/jdbc/using-usefmtonly?view=sql-服务器-2017

我发现使用PreparedStatement创建临时表是行不通的,但如果我改为使用Statement创建临时表格,它也会起作用(即使没有useFmtOnly(。因此,从这个(来自MS文章(开始,并在此基础上进行构建:

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'
}
}

在第一条语句中创建的临时表在该请求的scope\lifetime中存在。一旦您调用另一个查询,您就处于不同的作用域中,因此它不再存在,因为它本来会被清除。

解决方案是在同一个调用中发出两个请求(不太好(,或者创建一个可以由第二个查询访问的全局临时表(仍然不太好。(。

更好的解决方案是创建一个可以完成所需一切的存储过程,临时表的创建、查询和整理都封装在该过程中。

PS我看不到任何周围的代码,但在这样的代码中构建查询时要注意SQL注入。

相关信息:SQL Server 中临时表的范围

最新更新