繁体   English   中英

T-SQL 长动态查询被中断

[英]T-SQL long dynamic query gets cut off

我正在处理将生成 html 页面的查询。 一开始,该页面只是一个带有标签的简单 HTML 表格。 标签稍后将被处理并替换为子查询(主要是标量函数)。 这种方式将 HTML 与替换标签组合在一起,将使用 sp_executesql 执行以生成最终的 html。

该 HTML 的摘录:

...Arial, Helvetica, Verdana, sans-serif; font-weight: bold;">Firma:</td><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif;">'+(select cast(coalesce(Companyname,'') as nvarchar(max)) as result from Customer WHERE CustomerID=988082)+'</td></tr><tr><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif; font-weight: bold;">Anrede:</td><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif;">'+(select cast(coalesce(Anrede,'') as nvarchar(max)) as result from Customer WHERE CustomerID=988082)+'</td></tr><tr><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif; font-weight: bold;">Vorname:</td><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif;">'+(select cast(coalesce(Firstname,'') as nvarchar(max)) as result from Customer WHERE CustomerID=988082)+'</td></tr><tr><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif; font-weight: bold;">Nachname:</td><td style="font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif;">'+(select cast(coalesce(Lastname,'') as nvarchar(max)) as result from Customer WHERE CustomerID=988082)+'</td></tr><tr><td style="font-size: 1...

现在,我知道如果我使用 nvarchar(max) 以外的任何东西,我的结果将被截断为 4000,所以我将所有函数结果转换为 nvarchar(max),我的结果不止于此,但仍然奇怪地从内部截断。

因此,当我运行一个示例脚本时,我得到了9043个字符作为结果(使用 len 函数),结果被截断(注意:从内部,接近尾声但不是尾声)。 现在我追加一个字母,结果是9044 但如果我在最终结果前 100 个字符添加那个字母,结果仍然是9043 ??

这有什么问题? 为什么我不能构建一个长的 T-SQL 查询来执行预期的结果?

谢谢

更新 1

因为原始解决方案太长,无法在此处显示,所以我将尝试显示较小的版本,只是为了让您了解我是如何做到的以及我最终用它做了什么:

declare @BodyTXT nvarchar(max)
set @BodyTXT =  N'select ''some string' + (select cast('result of some function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) +
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another AAA string' + (select cast('result of antoher function' as nvarchar(max))) + N''''

execute sp_executesql @BodyTXT

假设这是 LEN = 9043 个字符,现在,请注意 AAA 如果我在那里添加字符,最终结果将保持为 LEN = 9043,但如果我在最开始添加一些字符串,字符串大小将改变并增加我在那里添加的字符串。

结果将以这种方式被切断:

some stringresult of some function another stringresult of antoher function
 another stringresult of antoher function another stringresult of antoher 
function another stringresult of antoher function another stringresult of antoher
 function another stringresult of antoher function another ...ult of antoher function

你能看到那些......几乎在结果末尾的点它在那里我缺少应该在输出中的其余字符串(大约 12000,我有 9043)

更新 2

因为这一切都是自动电子邮件系统的一部分,而且它是实时运行的,所以我必须找到解决方案,而我所做的就是从结果表中删除一些样式信息。 因此,在削减 1/3 的 html 之后,我终于得到了预期的结果,但是因为最终字符串的大小取决于客户购买的产品数量,因为这个问题肯定会再次出现。 而且我还想知道这种行为的原因是什么以及如何克服它。

我曾经遇到过使用 += 运算符连接长字符串的问题,它会减少字符。

所以改为使用@SQL = @SQL + N'a really long text'; 已经解决了。

我知道这是一篇旧文章,但仍然是当前主题。 这只是一个仅供参考,以帮助任何在这个问题上需要帮助的人。

我刚刚遇到一个问题,我的@SqlStr(设置为 NVARCHAR(MAX))在 SP_ExecuteSQL 调用期间不断切断导致错误。

对这个长脚本所做的唯一串联是设置为 NVARCHAR(100) 的 @TableName。

经过几个小时的调试,问题是由@tablename引起的

似乎当使用 nvarchar(###) 而不是 NVarchar(max) 时,SQL 将其视为略有不同的数据类型,并将长字符串剪切为 4000 个字符。

要解决此问题,我必须更改 @Tablename 以匹配 nvarchar(max) 数据类型。

我在生成大型 html 输出作为字符串时回想起类似的事情。 不记得到底是什么问题,可能是管理工作室的一些限制。 解决方法是将表生成为 xml。 以下是您可以试验的示例。 首先生成 sql 表,然后用您的表替换“select * from (values..)”。

declare
 @baseTable xml = (select * from ( Values
   (123, 'Firma:', 'Google'),
   (123, 'Anrede:', 'NYC'),
   (123, 'Vorname:', 'John'),
   (123, 'Nachname:', 'Doe')
  ) T(CustID, property, Val)
 for XML PATH('row'), ELEMENTS XSINIL)

,@tblClass VARCHAR(100)
,@thClass VARCHAR(100) 
,@TRstyle VARCHAR(100) = 'font-size: 14px'
,@TDstyle VARCHAR(100) = 'font-size: 14px; font-family: Arial, Helvetica, Verdana, sans-serif; font-weight: bold'

 SELECT @tblClass AS [@class]  
    ,@thClass AS [thead/@class]
    ,@baseTable.query(
              N'let $first:=/row[1]
                return 
                <tr> 
                {
                for $th in $first/*
                return <th>{local-name($th)}</th>
                }
                </tr>') AS thead
            ,@baseTable.query(                 
               N'for $tr in /row
                 return 
                 <tr style="{sql:variable("@TRstyle")}">
                  {
                   for $td in $tr/*
                     return <td style="{sql:variable("@TDstyle")}">{string($td)}</td>
                  }
                 </tr>') AS tbody
    FOR XML PATH('table'),TYPE

问题几乎可以肯定是你的@BodyTXT 可能是 nvarchar(max),但你放入其中的东西不是。 通过执行 set @BodyTxt = a + b + c + d +..... ,所有的串联都首先完成,然后立即插入您的变量中。 这很好,直到某处 SQL 由于类型强制(或其他原因)决定最新位的结果是 nvarchar(默认长度 4000),而不是 nvarchar(max),并截断其中的一些。

您可以检查整个查询,检查所有内容并查找问题,但将串联分解为足够小的位可能会更简单,就像这样。

declare @BodyTXT nvarchar(max)

set @BodyTXT =  N'select ''some string' + (select cast('result of some function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max)))

set @BodyTXT = @BodyTXT +
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) +

set @BodyTXT = @BodyTXT +
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another string' + (select cast('result of antoher function' as nvarchar(max))) + 
N' another AAA string' + (select cast('result of antoher function' as nvarchar(max))) + N''''

LEN将修剪尾随空格, DATALENGTH不会。 select len('a '), datalength('a ') 因此,如果您将该字母插入 100 个字符,那么最后一个字符就是一个空格。 只需使用DATALENGTH ,您应该会得到预期的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM