ได้แรงบันดาลใจจากคำตอบของ@Paulฉันได้ทำการวิจัยบางอย่างและพบว่าแม้ว่าจะเป็นจริงที่พื้นที่สแต็กจะ จำกัด จำนวนการต่อข้อมูลและพื้นที่สแต็กนั้นเป็นฟังก์ชันของหน่วยความจำที่มีอยู่และแตกต่างกันไป :
- มีวิธีการบีบอัดการต่อข้อมูลเพิ่มเติมลงในคำสั่งเดียวและ
- การใช้วิธีนี้นอกเหนือไปจากการ จำกัด พื้นที่สแต็กเริ่มต้นจะพบข้อ จำกัด ทางตรรกะที่แท้จริง (ซึ่งไม่ปรากฏว่ามีการเปลี่ยนแปลง)
ก่อนอื่นฉันปรับรหัสทดสอบของพอลให้เป็นสตริงที่ต่อกัน:
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);
จากการทดสอบนี้จำนวนสูงสุดที่ฉันจะได้รับเมื่อใช้งานบนแล็ปท็อปที่ไม่ค่อยดี (RAM เพียง 6 GB) คือ:
- 3311 (ส่งกลับ 3312 ตัวอักษรทั้งหมด) โดยใช้ SQL Server 2017 Express Edition LocalDB (14.0.3006)
- 3512 (ส่งคืน 354 ตัวอักษรทั้งหมด) โดยใช้ SQL Server 2012 Developer Edition SP4 (KB4018073) (11.0.7001)
ก่อนที่จะรับข้อผิดพลาด8631
ถัดไปฉันลองจัดกลุ่มการต่อข้อมูลโดยใช้วงเล็บเพื่อให้การดำเนินการเรียงต่อกันเป็นกลุ่มหลายกลุ่ม ตัวอย่างเช่น:
SET @S = (@A + @A + @A + @A) + (@A + @A + @A + @A) + (@A + @A + @A + @A);
การทำเช่นนั้นฉันสามารถทำได้ดีกว่าขีด จำกัด ก่อนหน้าของตัวแปร 3312 และ 3513 รหัสที่อัพเดทคือ:
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);
ค่าสูงสุด (สำหรับฉัน) ตอนนี้จะใช้42
สำหรับครั้งแรกREPLICATE
ดังนั้นการใช้ 43 ตัวแปรต่อกลุ่มและจากนั้นใช้762
สำหรับที่สองREPLICATE
จึงใช้ 762 กลุ่ม 43 ตัวแปรแต่ละ กลุ่มเริ่มต้นถูกฮาร์ดโค้ดด้วยตัวแปรสองตัว
ตอนนี้ผลลัพธ์แสดงให้เห็นว่ามี@S
ตัวแปรในอักขระ 32,768 ตัว หากฉันอัปเดตกลุ่มเริ่มต้นให้เป็น(@A+@A+@A)
เพียงแค่(@A+@A)
ฉันจะได้รับข้อผิดพลาดต่อไปนี้:
ข่าวสารเกี่ยวกับ 8632, ระดับ 17, สถานะ 2,
ข้อผิดพลาดภายในบรรทัด XXXXX : ข้อ จำกัด ของนิพจน์บริการถึงแล้ว โปรดค้นหานิพจน์ที่ซับซ้อนที่อาจเกิดขึ้นในแบบสอบถามของคุณและลองทำให้มันง่ายขึ้น
ขอให้สังเกตว่าหมายเลขข้อผิดพลาดแตกต่างจากก่อนหน้านี้ คือตอนนี้: 8632 และฉันมีข้อ จำกัด เดียวกันนี้ไม่ว่าฉันจะใช้อินสแตนซ์ SQL Server 2012 ของฉันหรืออินสแตนซ์ของ SQL Server 2017
อาจไม่ใช่เรื่องบังเอิญที่ขีด จำกัด สูงสุดที่นี่ - 32,768 - คือความจุสูงสุดของSMALLINT
( Int16
ใน. NET) หากเริ่มต้นที่0
(ค่าสูงสุดคือ 32,767 แต่อาร์เรย์ในภาษาการเขียนโปรแกรมส่วนใหญ่ / ส่วนใหญ่เป็นแบบ 0)