简体   繁体   English

T-SQL 长动态查询被中断

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

I am working with a query that will produce a html page.我正在处理将生成 html 页面的查询。 In the beginning that page is just a simple HTML table with tags.一开始,该页面只是一个带有标签的简单 HTML 表格。 The tags will later be processed and replaced with subqueries (mostly scalar functions).标签稍后将被处理并替换为子查询(主要是标量函数)。 This way combined HTML with replaced tags will be executed with sp_executesql to produce final html.这种方式将 HTML 与替换标签组合在一起,将使用 sp_executesql 执行以生成最终的 html。

Excerpt of that 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...

Now, I know that if I use anything but nvarchar(max) my result will be truncated to 4000, so I do casting of all function results to nvarchar(max) and my results is more than that but still strangely cut of from inside.现在,我知道如果我使用 nvarchar(max) 以外的任何东西,我的结果将被截断为 4000,所以我将所有函数结果转换为 nvarchar(max),我的结果不止于此,但仍然奇怪地从内部截断。

So when I run an example script I get 9043 characters as the result (with len function), and the result is cut off (note: from inside, near the end but not at the end).因此,当我运行一个示例脚本时,我得到了9043个字符作为结果(使用 len 函数),结果被截断(注意:从内部,接近尾声但不是尾声)。 Now I append one letter and result is 9044 .现在我追加一个字母,结果是9044 But if I add that letter 100 characters before the end result is still 9043 ??但如果我在最终结果前 100 个字符添加那个字母,结果仍然是9043 ??

What is wrong with this?这有什么问题? Why I can;t build a long T-SQL query to be executed with the expected results?为什么我不能构建一个长的 T-SQL 查询来执行预期的结果?

Thanks谢谢

UPDATE 1更新 1

Because the original solution is too long to display it here I will try to display smaller version just for you to see how I did it and what is my final doing with it:因为原始解决方案太长,无法在此处显示,所以我将尝试显示较小的版本,只是为了让您了解我是如何做到的以及我最终用它做了什么:

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

Let's say that this is LEN = 9043 characters long and now, notice AAA if I add characters there the final results stays to be LEN = 9043, but if I add some strings at the very beginning string size will change and increase for the number of strings I add there.假设这是 LEN = 9043 个字符,现在,请注意 AAA 如果我在那里添加字符,最终结果将保持为 LEN = 9043,但如果我在最开始添加一些字符串,字符串大小将改变并增加我在那里添加的字符串。

Result will be cut off this way:结果将以这种方式被切断:

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

Can you see those... dots almost at the end of the result it is there where I am missing rest of string that should be in the output (approx 12000, and I am having 9043)你能看到那些......几乎在结果末尾的点它在那里我缺少应该在输出中的其余字符串(大约 12000,我有 9043)

UPDATE 2更新 2

Because this all is part of automated emailing system and it was running live I had to find solution and what I have done is removing some style information from the result table.因为这一切都是自动电子邮件系统的一部分,而且它是实时运行的,所以我必须找到解决方案,而我所做的就是从结果表中删除一些样式信息。 So after cutting 1/3 of html I finally got result as expected BUT because size of the final string depends on how many products customer purchases for certainly this issue will come again.因此,在削减 1/3 的 html 之后,我终于得到了预期的结果,但是因为最终字符串的大小取决于客户购买的产品数量,因为这个问题肯定会再次出现。 And also I want to know what is the reason for this behavior and how to overcome it.而且我还想知道这种行为的原因是什么以及如何克服它。

I once have encountered an issue using += operator to concatenate long strings, it was cutting characters down.我曾经遇到过使用 += 运算符连接长字符串的问题,它会减少字符。

So instead using @SQL = @SQL + N'a really long text';所以改为使用@SQL = @SQL + N'a really long text'; has solved it.已经解决了。

I know this is an old Post but still a current subject.我知道这是一篇旧文章,但仍然是当前主题。 This is just as an FYI, to help anyone that would need help on this subject.这只是一个仅供参考,以帮助任何在这个问题上需要帮助的人。

I just ran into a problem where my @SqlStr (that is set to NVARCHAR(MAX)) kept on cutting off causing errors during the SP_ExecuteSQL call.我刚刚遇到一个问题,我的@SqlStr(设置为 NVARCHAR(MAX))在 SP_ExecuteSQL 调用期间不断切断导致错误。

The only concatenation that is done to this long script was @TableName which was set to NVARCHAR(100).对这个长脚本所做的唯一串联是设置为 NVARCHAR(100) 的 @TableName。

After several hours of debugging, the issue was caused by the @tablename经过几个小时的调试,问题是由@tablename引起的

it seems like when nvarchar(###) is used instead of NVarchar(max), SQL sees it as a slightly different datatype and cuts the long string to 4000 characters.似乎当使用 nvarchar(###) 而不是 NVarchar(max) 时,SQL 将其视为略有不同的数据类型,并将长字符串剪切为 4000 个字符。

To fix the issue I had to change the @Tablename to match the nvarchar(max) data type.要解决此问题,我必须更改 @Tablename 以匹配 nvarchar(max) 数据类型。

I recall something similar while generating large html output as a string.我在生成大型 html 输出作为字符串时回想起类似的事情。 Can't recall what exactly was the issue, probably some limitation of management studio.不记得到底是什么问题,可能是管理工作室的一些限制。 The workaround was to generate table as xml.解决方法是将表生成为 xml。 Below is a sample you can experiment with.以下是您可以试验的示例。 Generate sql table first and then replace "select * from (values..)" with your table.首先生成 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

The problem is almost certainly that your @BodyTXT may be nvarchar(max), but something you are putting into it is not.问题几乎可以肯定是你的@BodyTXT 可能是 nvarchar(max),但你放入其中的东西不是。 By doing set @BodyTxt = a + b + c + d +..... , all of the concatenation is being done first, and then stuck into your variable at once.通过执行 set @BodyTxt = a + b + c + d +..... ,所有的串联都首先完成,然后立即插入您的变量中。 Which is great, until somewhere SQL decides because of type coercion (or something) that the results of the latest bit are nvarchar (default length 4000), not nvarchar(max), and truncates some of it.这很好,直到某处 SQL 由于类型强制(或其他原因)决定最新位的结果是 nvarchar(默认长度 4000),而不是 nvarchar(max),并截断其中的一些。

You can go through your whole query, checking everything and looking for the problem, but it would probably be simpler to break the concatenation up into bits that will all be small enough, something like this.您可以检查整个查询,检查所有内容并查找问题,但将串联分解为足够小的位可能会更简单,就像这样。

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 will trim trailing spaces, DATALENGTH will not. LEN将修剪尾随空格, DATALENGTH不会。 select len('a '), datalength('a ') . select len('a '), datalength('a ') So if you insert that letter 100 characters back then the last character is a space.因此,如果您将该字母插入 100 个字符,那么最后一个字符就是一个空格。 Just use DATALENGTH instead and you should get your expected results.只需使用DATALENGTH ,您应该会得到预期的结果。

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

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