Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Can';第二次使用准备好的语句到达临时表_Java_Sql Server_Prepared Statement_Sql Injection - Fatal编程技术网

Java Can';第二次使用准备好的语句到达临时表

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 Server、Java中[这里有一些详细的原因]。我在java中使用Stament对象执行sql查询。然而,最近我决定使用PreparedStatement来避免注入的事情

我的问题是,当使用PreparedStatement创建临时表时,我无法再次使用相同的PreparedStatement访问它。下面是一个简单的例子:

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