Terinspirasi oleh @ Paulus 's jawaban , saya melakukan penelitian dan menemukan bahwa sementara itu benar bahwa ruang stack tidak membatasi jumlah concatenations, dan bahwa ruang stack adalah fungsi memori yang tersedia dan dengan demikian bervariasi, dua hal berikut juga benar :
- ada cara untuk menjejalkan rangkaian tambahan ke dalam satu pernyataan, DAN
- menggunakan metode ini untuk melampaui batasan ruang stack awal, batas logis aktual (yang tampaknya tidak bervariasi) dapat ditemukan
Pertama, saya mengadaptasi kode tes Paul untuk merangkai string:
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'
DECLARE @S VARCHAR(MAX), @A VARCHAR(MAX) = ''a'';
SET @S = @A';
SET @SQL += REPLICATE(CONVERT(NVARCHAR(MAX), N' + @A'), 3312) + N';';
-- SET @S = @A + @A + @A...
SET @SQL += N'SELECT DATALENGTH(@S) AS [Chars In @S];';
EXECUTE (@SQL);
Dengan tes ini, nilai tertinggi yang bisa saya dapatkan ketika menjalankan laptop saya yang tidak terlalu bagus (hanya 6 GB RAM) adalah:
- 3311 (mengembalikan 3312 total karakter) menggunakan SQL Server 2017 Express Edition LocalDB (14.0.3006)
- 3512 (mengembalikan 3513 total karakter) menggunakan SQL Server 2012 Developer Edition SP4 (KB4018073) (11.0.7001)
sebelum mendapatkan error 8631 .
Selanjutnya, saya mencoba mengelompokkan concatenations dengan menggunakan tanda kurung sehingga operasi akan menyatukan beberapa grup concatenations. Sebagai contoh:
SET @S = (@A + @A + @A + @A) + (@A + @A + @A + @A) + (@A + @A + @A + @A);
Melakukan itu saya bisa melampaui batas sebelumnya 3312 dan 3513 variabel. Kode yang diperbarui adalah:
DECLARE @SQL VARCHAR(MAX), @Chunk VARCHAR(MAX);
SET @SQL = '
DECLARE @S VARCHAR(MAX), @A VARCHAR(MAX) = ''a'';
SET @S = (@A+@A)';
SET @Chunk = ' + (@A' + REPLICATE(CONVERT(VARCHAR(MAX), '+@A'), 42) + ')';
SET @SQL += REPLICATE(CONVERT(VARCHAR(MAX), @Chunk), 762) + ';';
SET @SQL += 'SELECT DATALENGTH(@S) AS [Chars In @S];';
-- PRINT @SQL; -- for debug
-- SET @S = (@A+@A) + (@A + @A...) + ...
EXECUTE (@SQL);
Nilai maksimum (untuk saya) sekarang adalah yang digunakan 42
untuk yang pertama REPLICATE
, dengan demikian menggunakan 43 variabel per grup, dan kemudian menggunakan 762
untuk yang kedua REPLICATE
, dengan demikian menggunakan 762 grup dengan masing-masing 43 variabel. Kelompok awal adalah hard-coded dengan dua variabel.
Output sekarang menunjukkan bahwa ada 32.768 karakter dalam @S
variabel. Jika saya memperbarui grup awal menjadi (@A+@A+@A)
bukan hanya (@A+@A)
, maka saya mendapatkan kesalahan berikut:
Msg 8632, Level 17, Negara 2, Jalur XXXXX
Kesalahan internal: Batas layanan ekspresi telah tercapai. Harap cari kemungkinan ekspresi kompleks dalam kueri Anda, dan cobalah untuk menyederhanakannya.
Perhatikan bahwa nomor kesalahan berbeda dari sebelumnya. Sekarang: 8632 . DAN, saya memiliki batas yang sama ini apakah saya menggunakan contoh SQL Server 2012 atau contoh SQL Server 2017.
Hal ini mungkin kebetulan bahwa atas-batas di sini - 32.768 - adalah max kapasitas dari SMALLINT
( Int16
NET) IF mulai 0
(nilai max adalah 32.767 tapi array dalam banyak bahasa pemrograman / sebagian besar berbasis 0).