你能帮我理解这个奇怪的NVARCHAR
变量行为吗?
我正在构建一个dSQL查询,其范围为LEN()
,大约为6,700到6,900个字符,并将其存储在变量中:
DECLARE
@SQL NVARCHAR(MAX),
@WhereClause NVARCHAR(MAX) = 'WHERE 1 = 1
',
@OrderByClaose NVARCHAR(MAX)
SET @SQL =
'SELECT
<column list>
FROM
<very complicated FROM clause>
'
不幸的是,我不允许发布实际代码。
最初,dSQL是一个长常量SELECT
和FROM
字符串,大约有6,600个字符。确定了可变长度dSQL WHERE
和ORDER BY
子句
IF <condition p>
SET @WhereClause = @WhereClause + 'AND <condition p clause>
'
IF <condition q>
SET @WhereClause = @WhereClause + 'AND <condition q clause>
'
etc.
然后添加到@SQL的末尾。
整个@SQL
会PRINT
很好地执行,然后sp_executesql
顺便执行。
因此,客户自然需要进行一些更改,从而将好的常量字符串分成几部分。这需要将动态列部分添加到SELECT列列表中间的IF语句。
SET @SQL = '
SELECT <code through first few columns>
...
'
IF <condition>
SET @SQL = @SQL +
' <new dynamic column spec stuff A>
'
ELSE
SET @SQL = @SQL +
' <new dynamic column spec stuff B>
'
SET @SQL = @SQL + ' <next block of constant chars>'
...
当我添加新的IF/ELSE
块时,由于某种原因@SQL
停止接受前4,000个字符后的数据,大约是FROM
子句的一半。
删除IF/ELSE
块并将SELECT
和FROM
返回到常量字符串(只是为测试添加一个新的需求案例),然后再次愉快@SQL
接受了所有6,700个左右的字符。
作为解决方法,我将@SQL
的声明更改为VARCHAR(MAX)
DECLARE @SQL varchar(max)
SET @SQL = <The built-up query string with the new IF/ELSE blocks>
DECLARE @NSQL nvarchar(max) = cast(@SQL as nvarchar(max))
exec sp_executesql @NSQL
一切都很好。
虽然我还没有测试过,但我想知道这个解决方法是否适用于这个特定任务的唯一原因是因为我最大的dSQL语句中的字符数小于8,000个字符。
我看过几篇文章,包括
但我发现的任何东西似乎都没有解释我在这个特殊的dSQL构造中观察到的行为。
知道这里有什么用吗?
答案 0 :(得分:2)
首先,由于您有NVARCHAR
数据类型,因此应始终使用N'...'
格式(带有前导N
前缀)来清楚地表示Unicode字符串文字。
DECLARE @WhereClause NVARCHAR(MAX) = N'WHERE 1 = 1'
其次,如果仅此一点没有帮助,请尝试在连接之前将字符串文字强制转换为NVARCHAR(MAX)
IF <condition>
SET @SQL = @SQL + CAST(...... AS NVARCHAR(MAX))