【问题标题】:PreparedStatement is executed on prepareStatement on SQL ServerPreparedStatement 在 SQL Server 上的 prepareStatement 上执行
【发布时间】:2009-08-16 14:02:00
【问题描述】:

我们有一个类似于下面的 Java 代码:

PreparedStatement stmt = connection.prepareStatement("drop login tmp");
int result = stmt.executeUpdate();

通过调试器运行时,似乎我们的SQL语句是在第一行执行之后执行的,甚至在第二行执行之前执行。执行第二行时,再次执行 drop SQL,并导致错误,因为用户名 tmp 不再存在。

这只会发生在 SQL Server 上,但不会发生在具有类似 drop SQL 查询的 Oracle 和 Postgres 上。

这是一个已知问题吗?除了转移到 Statement 而不是 PreparedStatement 之外,还有其他常见的解决方法吗?

【问题讨论】:

  • 嗯,你的陈述不包含任何变量,所以真的没有什么要“准备”的。您是否尝试过仅使用语句?
  • 我同意 drop 不是准备好的语句的好候选者,事实上,我们切换到语句并且问题解决了。但是,这是一个库代码,我们可能需要将它用于不同的查询,所以我想找到问题的根源。

标签: java sql-server jdbc


【解决方案1】:

我认为最好的办法是针对测试数据库运行 SQL Server Profiler,然后查看运行此代码时服务器的实际情况。使用 C# 准备好的语句,您会看到类似

的内容
declare @p1 int
set @p1=-1
exec sp_prepexec @p1 output, N'@param, varchar(100)', ...
select @p1

Java 或您的 SQL 客户端库可能使用不同的技术。

话虽如此,准备好的语句仅用于缓存和参数化重复的、可参数化的类似语句。这个想法是为了节省重新编译 SQL 语句。如果您没有发出许多重复的、类似的语句,那么准备好的语句就不会对您有利,并且缓存 SQL 也没有用。就我个人而言,我无法想象使用“drop login”这么多缓存会有所帮助。

除此之外,我认为 DROP LOGIN 语句不能在 T-SQL 中接受参数。

【讨论】:

  • 我同意 drop 不是准备好的语句的好候选者,事实上,我们切换到语句并且问题解决了。但是,这是一个库代码,我们可能需要将它用于不同的查询,所以我想找到问题的根源。
【解决方案2】:

当您创建PreparedStatement 时,查询将发送到服务器以对其进行预编译 (Source)。

据推测,SQLServer 发现没有占位符,而是直接执行查询。

从 cmets 来看,您已经知道解决方法是创建一个 Statement。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多