“String data,right truncation”via ODBC but not via SQL Server Manager with the same query

我有一个服务器上的LAPP堆栈和另一个上运行的MSSQL。 前者通过微软的Linux驱动程序1.0 for Linux连接到后者,一般效果不错。

如果查询string太长,我们的一个search页面会失败,并显示以下错误:

Couldn't execute statement: [unixODBC][Microsoft][SQL Server Native Client 11.0]String data, right truncation (SQL-22001) 

但是,如果我复制查询,将其粘贴到连接到同一数据库的MS SQL Serverpipe理器查询窗口中,全部replace? 占位符正是我的脚本传递给$sth->execute() ,并运行它,它不会产生错误。

为什么是这样? (这是否表示ODBC驱动程序或SSM中的错误,或只是两者之间的差异?)

更好的是,或者我想我的最终目标是:我怎样才能让我的脚本像SSM一样行事呢? 目前我能看到的唯一的解决方法是遍历每一列(并且有很多,这是跨5个查询的联合,每个查询都有许多表连接),并找出每个varchar列的长度是什么,查询string可能每一个都太长了,然后用长度来区分所有的占位符。 即我必须做我自己的截断,并有另一个代码依赖 – 例如,当我们的数据库供应商决定加长列时,那么我必须去减less列出现在任何脚本中的截断。不能ODBC驱动程序“正常工作”SSM一样,没有抱怨?

如果我启用跟踪,我得到这些占位符之一:

 -dbd_bind_ph=rebind_param +rebind_param 7 '%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%' (size svCUR=43/SvLEN=48/max=0) svtype:8, value type:1, sql type:0 +get_param_type(7f22ca950e88,7) bind 7 '%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...' value_len=43 maxlen=47 null=0) bind 7 value_type:1 VARCHAR cs=20 dd=0 bl=43 -rebind_param +dbd_bind_ph(7f22ca950e88, name=8, value='%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%', attribs=, sql_type=0(unknown), is_inout=0, maxlen=0 First bind of this placeholder 

这似乎是cs=...是什么变化,似乎对应的最大占位符的大小,我可以摆脱在这种情况下。 有没有办法访问该值,所以我可以限制的价值之前,我绑定它,但dynamic,以便我没有这些额外的代码依赖? 也许这就是SSM自动完成的?

更新:我发现DBD :: ODBC :: FAQ下“为什么我得到绑定参数的错误? 在“数据截断错误”下面或多或less的描述了这个问题。 是真的,我必须遍历每个参数来修复它返回的SQLDescribeParam的长度(减2,所以我可以在开始和结束时添加search'%'标志)…但那不是甚至保证工作,如果我使用任何forms的联接,因为它可能会得到长度错误? 这张照片有什么问题?

UPDATE2:我刚刚在这里发现,“如果您正在使用Microsoft SQL Server ODBC驱动程序1.0的Linux,您应该升级到SQL Server的Microsoft ODBC驱动程序11”。 关于尝试一下…关于最新的libmsodbcsql-11.0.so.2270.0驱动libmsodbcsql-11.0.so.2270.0 ,它也performance出这种行为。

感谢bohica,DBD :: ODBC现在导出了一个函数odbc_describe_param ,公开了uber-text-search情况的解决方法的必要信息:

 # $sth is an already-prepared statement for (1..(scalar keys %{$sth->{ParamTypes}})) { my @help = $sth->odbc_describe_param($_); if ($help[1]) { # like SQLDescribeParam API - ie, type, size, decimal digital and nullable $sth->bind_param($_, '%' . substr($s, 0, $help[1] - 2) . '%'); } else { # 0 = false = unlimited length allowed $sth->bind_param($_, '%' . $s . '%'); } } $sth->execute(); ...