![](/img/trans.png)
[英]SQL Server 2008 inconsistent results when converting datetime to varchar
[英]Concatenating SQL Server VARCHAR(N), results with unexpected and inconsistent truncated results when converted to NVARCHAR(MAX)
在下面的代碼中,我們看到 varchar(n) 的串聯(其中 n>4000)在轉換為 nvarchar(max) 時會產生意外且不一致的截斷結果:
我想隱式轉換是按連接順序完成的,但我會說 (1) 的行為符合預期,(2) 應該被截斷為 8000,而 (3) 根本不應該被截斷。
似乎有某種(錯誤的)長度轉換為 4000,這是在連接順序之外完成的,這在某種程度上與結果類型 NVARCHAR 相關。 但是如果意圖是根據結果類型轉換所有連接,那么,因為它是 MAXed,所以不會有任何截斷(這會給出最好的結果)。
我哪里錯了?
DECLARE @x AS NVARCHAR(MAX)
DECLARE @y AS NVARCHAR(MAX) = '_10 chars_'
DECLARE @z AS VARCHAR(4200) = replicate('_', 4200)
SET @x = @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 4200'
SET @x = @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 8400 = 4200 * 2'
SET @x = @z + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 12600 = 4200 * 3'
SET @x = @z + @y
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 4210 = 4200 + 10'
SET @x = @z + @z + @y
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 8410 = 4200 * 2 + 10'
SET @x = @z + @z + @z + @y
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 12610 = 4200 * 3 + 10'
SET @x = @y + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 4210 = 10 + 4200'
SET @x = @y + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 8410 = 10 + 4200 * 2'
SET @x = @y + @z + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 12610 = 10 + 4200 * 3'
SET @x = @z + @z + @z + @y + @z + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 25210 = 4200 * 3 + 10 + 4200 * 3'
當您將兩個varchar
值連接在一起時,數據類型的結果長度是兩者的總和,最大為 8000 ,超過的長度將被截斷。
當您將兩個nvarchar
值連接在一起時,數據類型的結果長度是兩者的總和,最大為 4000 ,超過的長度將被截斷。
只有當您將它存儲在max
變量中時,該值才會變為max
,截斷會在此之前發生
此外,您在這里進行了第二次隱式轉換,從varchar
到nvarchar
,這本身會導致截斷,因為nvarchar
最多只能是 4000。
如果您連接一個nvarchar
和一個varchar
,則varchar
將轉換為匹配,但上限為 4000。最終結果在存儲到變量中之前不會變為max
。 所以隱式轉換將在截斷之后完成。
您的結果現在非常有意義:
max
。SET @x = @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 4200'
max
SET @x = @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 8400 = 4200 * 2'
SET @x = @z + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 12600 = 4200 * 3'
nvarchar
的隱式轉換,然后再與max
連接,因此首先截斷原始@z
值。SET @x = @z + @y
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 4210 = 4200 + 10'
SET @x = @z + @z + @y
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 8410 = 4200 * 2 + 10'
SET @x = @z + @z + @z + @y
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 12610 = 4200 * 3 + 10'
SET @x = @y + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 4210 = 10 + 4200'
SET @x = @y + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 8410 = 10 + 4200 * 2'
SET @x = @y + @z + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 12610 = 10 + 4200 * 3'
SET @x = @z + @z + @z + @y + @z + @z + @z
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 25210 = 4200 * 3 + 10 + 4200 * 3'
保證正確結果的唯一方法是首先將您的值轉換為nvarchar(max)
SET @x = CAST(@z AS nvarchar(max)) + CAST(@z AS nvarchar(max)) + CAST(@z AS nvarchar(max)) + @y + CAST(@z AS nvarchar(max)) + CAST(@z AS nvarchar(max)) + CAST(@z AS nvarchar(max))
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 25210 = 4200 * 3 + 10 + 4200 * 3'
或者,只需使用CONCAT
,它無論如何都能正確處理所有這些
SET @x = CONCAT(@z, @z, @z, @y, @z, @z, @z);
print CAST(len(@x) AS NVARCHAR(MAX)) + ' Expected 25210 = 4200 * 3 + 10 + 4200 * 3'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.