在下面的代碼中,我們看到 varchar(n) 的串聯,其中 n>4000,在轉換為 nvarchar(max) 時會導致意外和不一致的截斷結果:
- 當連接中僅涉及 v??archar(n) 值時,結果將被截斷為 8000 個字符。
- 在連接到 nvarchar(max) 之前完成的一系列 varchar(n) 連接在連接到 nvarchar(max) 之前被截斷為 4000 個字符。
- 一系列 varchar(n) 連接,在連接到 nvarchar(max) 之后完成,每個 varchar(n) 在連接之前被截斷為 4000 個字符
我猜隱式轉換是按連接順序完成的,但是我會說(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'
uj5u.com熱心網友回復:
當您將兩個varchar
值連接在一起時,資料型別的結果長度是兩者的總和,最大為 8000,將被截斷。
當您將兩個nvarchar
值連接在一起時,資料型別的結果長度是兩者的總和,最大為 4000,將被截斷。
只有當您將其存盤在max
變數中時,值才會變為max
,截斷會在此之前發生
此外,這里還有第二個隱式轉換, from varchar
to nvarchar
,它本身會導致截斷,因為nvarchar
最多只能是 4000。
如果連接 anvarchar
和 a varchar
,則將varchar
轉換為匹配,但上限為 4000。最終結果將不會變為max
直到它存盤在變數中。所以隱式轉換將在截斷之后完成。
您的結果現在非常有意義:
- 長度已經是 4200,并且擴展為
max
.
SET @x = @z
print CAST(len(@x) AS NVARCHAR(MAX)) ' Expected 4200'
- 在這些情況下,中間值的上限為 8000,然后才轉換為
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
,然后與 after 連接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'
db<>小提琴
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/514583.html
上一篇:每天選擇平均連接數
下一篇:將不同的科學記數法轉換為數字