jTDS +存储过程+ prepareSQL =嵌套级错误?

时间:2012-05-03 07:01:46

标签: java sql-server sql-server-2008 stored-procedures jtds

场合
我有一个(Tomcat)Java Web应用程序使用jTDS连接到MSSQL 2008数据库。该Java应用程序使用用户输入执行99%的MSSQL存储过程。

问题
jTDS驱动程序有时会(在应用程序的不同位置)回复错误:

  

超出最大存储过程,函数,触发器或视图嵌套级别(限制32)。

我们可以通过将prepareSQL=0添加到jTDS连接字符串来避免这种情况。然后错误随处可见,但是对于prepareSQL的所有其他值,错误仍然存​​在。我不知道jTDS添加了多少存储过程嵌套级别,但显然它对我们的应用来说太多了。

问题

  1. 只使用存储过程执行,当然在Java代码中使用Prepared Statements,prepareSQL=3(或prepareSQL=0)对我们有多大影响?换句话说:在每个网站上我都会发现人们说“绝不在生产环境中使用prepareSQL=0”,这是否也适用于这种情况?

  2. 如果prepareSQL=0不是推荐的解决方案,安全问题等,我们应该寻找其他驱动程序。 jTDS在过去的两年里没有更新,微软有一个JDBC 4.0的驱动程序。我找不到jTDS和微软的JDBC 4.0驱动程序之间的任何基准或比较。使用Microsoft的2.0和3.0驱动程序,一般意见似乎是jTDS更快,更好,更高效。 JDBC 4.0仍然如此,或者微软是否已经通过了它的竞争对手?

1 个答案:

答案 0 :(得分:2)

当prepareSQL不等于0时,jTDS在嵌套时添加一个级别。请考虑以下程序:

CREATE PROCEDURE F @v int
AS
BEGIN
    select @v = @v - 1
    IF @v = 0 SELECT @v
    ELSE EXEC F @v
END

使用它的java代码:

 Connection connection = DriverManager.getConnection("jdbc:jtds:sqlserver://xxx.xxx.xxx.xxx:1433/xxx;prepareSQL=0");
 PreparedStatement statement = connection.prepareStatement("EXEC F ?");
 statement.setInt(1, 32);
 statement.execute();

如果将prepareSQL设置为0以外的值,则会因“超出最大存储过程,函数,触发器或视图嵌套级别(限制32)”而失败。您需要找到为什么您的代码使用如此多的嵌套?通过prepareSQL = 0,你阻止mssql使用stamements和那些强制在每次执行时解析SQL。如果语句执行时间远远超过语句编译时间(E.G.如果存储过程执行10秒,那么如果编译花费10ms则不是问题)这不是一个大问题。更改驱动程序无济于事,因为您会遇到同样的问题。