Pada setiap waktu di masa lalu, jika seseorang telah meminta saya ukuran maksimum untuk varchar(max)
, saya akan mengatakan 2GB, atau mendongak lebih tepat angka (2 ^ 31-1, atau 2147483647).
Namun, dalam beberapa pengujian baru-baru ini, saya menemukan bahwa varchar(max)
variabel ternyata dapat melebihi ukuran ini:
create table T (
Val1 varchar(max) not null
)
go
declare @KMsg varchar(max) = REPLICATE('a',1024);
declare @MMsg varchar(max) = REPLICATE(@KMsg,1024);
declare @GMsg varchar(max) = REPLICATE(@MMsg,1024);
declare @GGMMsg varchar(max) = @GMsg + @GMsg + @MMsg;
select LEN(@GGMMsg)
insert into T(Val1) select @GGMMsg
select LEN(Val1) from T
Hasil:
(no column name)
2148532224
(1 row(s) affected)
Msg 7119, Level 16, State 1, Line 6
Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
The statement has been terminated.
(no column name)
(0 row(s) affected)
Jadi, mengingat sekarang saya tahu bahwa variabel dapat melebihi penghalang 2GB - apakah ada yang tahu berapa batas sebenarnya untuk varchar(max)
variabel?
(Tes di atas diselesaikan di SQL Server 2008 (bukan R2). Saya tertarik untuk mengetahui apakah ini berlaku untuk versi lain)
sql-server
tsql
Damien_The_Tidak percaya
sumber
sumber
declare @x varchar(max) = 'XX'; SELECT LEN(REPLICATE(@x,2147483647))
memberi4294967294
untuk saya tetapi membutuhkan waktu lama untuk menjalankan - bahkan setelahSELECT
telah kembali jadi tidak yakin apa waktu ekstra yang dihabiskan untuk melakukannya.Jawaban:
Sejauh yang saya tahu tidak ada batas atas di tahun 2008.
Di SQL Server 2005, kode di pertanyaan Anda gagal pada tugas ke
@GGMMsg
variabel dengankode di bawah ini gagal dengan
Namun tampaknya batasan ini diam-diam telah dicabut. Pada 2008
DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681); SET @y = REPLICATE(@y,92681); SELECT LEN(@y)
Kembali
Saya menjalankan ini di mesin desktop 32 bit saya sehingga string 8GB ini jauh melebihi memori yang dapat dialamatkan
Lari
select internal_objects_alloc_page_count from sys.dm_db_task_space_usage WHERE session_id = @@spid
Dikembalikan
internal_objects_alloc_page_co ------------------------------ 2144456
jadi saya menganggap ini semua hanya disimpan di
LOB
halamantempdb
tanpa validasi panjangnya. Pertumbuhan jumlah halaman semuanya terkait denganSET @y = REPLICATE(@y,92681);
pernyataan itu. Penugasan variabel awal@y
danLEN
penghitungan tidak meningkatkan ini.Alasan untuk menyebutkan ini adalah karena jumlah halaman jauh lebih banyak dari yang saya harapkan. Dengan asumsi halaman 8KB maka ini bekerja pada 16,36 GB yang jelas lebih atau kurang dua kali lipat dari apa yang tampaknya diperlukan. Saya berspekulasi bahwa ini kemungkinan karena inefisiensi dari operasi penggabungan string yang perlu menyalin seluruh string besar dan menambahkan potongan ke bagian akhir daripada dapat menambahkan ke akhir string yang ada. Sayangnya saat ini
.WRITE
metode tersebut tidak didukung untuk variabel varchar (max).Tambahan
Saya juga telah menguji perilaku tersebut dengan penggabungan
nvarchar(max) + nvarchar(max)
dannvarchar(max) + varchar(max)
. Keduanya memungkinkan terlampaui batas 2GB. Mencoba untuk kemudian menyimpan hasil ini dalam tabel kemudian gagal namun dengan pesan kesalahanAttempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
lagi. Script untuk itu ada di bawah (mungkin butuh waktu lama untuk dijalankan).DECLARE @y1 VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),2147483647); SET @y1 = @y1 + @y1; SELECT LEN(@y1), DATALENGTH(@y1) /*4294967294, 4294967292*/ DECLARE @y2 NVARCHAR(MAX) = REPLICATE(CAST('X' AS NVARCHAR(MAX)),1073741823); SET @y2 = @y2 + @y2; SELECT LEN(@y2), DATALENGTH(@y2) /*2147483646, 4294967292*/ DECLARE @y3 NVARCHAR(MAX) = @y2 + @y1 SELECT LEN(@y3), DATALENGTH(@y3) /*6442450940, 12884901880*/ /*This attempt fails*/ SELECT @y1 y1, @y2 y2, @y3 y3 INTO Test
sumber
varchar
nilai lebih dari 8000 karakter dalam string literal dalam kode, selama Anda tidak mencoba memasukkannya ke dalam variabel atauvarchar
kolom.EDIT : Setelah penyelidikan lebih lanjut, asumsi awal saya bahwa ini adalah anomali (bug?)
declare @var datatype = value
Sintaks tidak benar.Saya memodifikasi skrip Anda untuk tahun 2005 karena sintaks tersebut tidak didukung, kemudian mencoba versi modifikasi pada tahun 2008. Pada tahun 2005, saya mendapatkan
Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
pesan kesalahan. Pada 2008, skrip yang dimodifikasi masih berhasil.declare @KMsg varchar(max); set @KMsg = REPLICATE('a',1024); declare @MMsg varchar(max); set @MMsg = REPLICATE(@KMsg,1024); declare @GMsg varchar(max); set @GMsg = REPLICATE(@MMsg,1024); declare @GGMMsg varchar(max); set @GGMMsg = @GMsg + @GMsg + @MMsg; select LEN(@GGMMsg)
sumber
Attempting to grow...
error padaset @GGMMsg=...
pernyataan tersebut. Pada tahun 2008, skrip tersebut berhasil.