场合
我有一个(Tomcat)Java Web应用程序使用jTDS连接到MSSQL 2008数据库。该Java应用程序使用用户输入执行99%的MSSQL存储过程。
问题
jTDS驱动程序有时会(在应用程序的不同位置)回复错误:
超出最大存储过程,函数,触发器或视图嵌套级别(限制32)。
我们可以通过将prepareSQL=0
添加到jTDS连接字符串来避免这种情况。然后错误随处可见,但是对于prepareSQL
的所有其他值,错误仍然存在。我不知道jTDS添加了多少存储过程嵌套级别,但显然它对我们的应用来说太多了。
问题
只使用存储过程执行,当然在Java代码中使用Prepared Statements,prepareSQL=3
(或prepareSQL=0
)对我们有多大影响?换句话说:在每个网站上我都会发现人们说“绝不在生产环境中使用prepareSQL=0
”,这是否也适用于这种情况?
如果prepareSQL=0
不是推荐的解决方案,安全问题等,我们应该寻找其他驱动程序。 jTDS在过去的两年里没有更新,微软有一个JDBC 4.0的驱动程序。我找不到jTDS和微软的JDBC 4.0驱动程序之间的任何基准或比较。使用Microsoft的2.0和3.0驱动程序,一般意见似乎是jTDS更快,更好,更高效。 JDBC 4.0仍然如此,或者微软是否已经通过了它的竞争对手?
答案 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则不是问题)这不是一个大问题。更改驱动程序无济于事,因为您会遇到同样的问题。