Inspiriert von der Antwort von @Paul , habe ich einige Nachforschungen angestellt und festgestellt, dass der Stapelspeicher zwar die Anzahl der Verkettungen begrenzt, und der Stapelspeicher eine Funktion des verfügbaren Speichers ist und daher variiert. Die folgenden beiden Punkte sind jedoch ebenfalls zutreffend ::
- Es gibt eine Möglichkeit, zusätzliche Verkettungen in eine einzige Anweisung UND zu packen
- Wenn Sie diese Methode verwenden, um über die anfängliche Stapelplatzbeschränkung hinauszugehen, kann eine tatsächliche logische Grenze (die nicht zu variieren scheint) gefunden werden
Zuerst habe ich Pauls Testcode angepasst, um Zeichenfolgen zu verketten:
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);
Mit diesem Test konnte ich auf meinem nicht so großartigen Laptop (nur 6 GB RAM) höchstens Folgendes erreichen:
- 3311 (gibt insgesamt 3312 Zeichen zurück) mit SQL Server 2017 Express Edition LocalDB (14.0.3006)
- 3512 (gibt insgesamt 3513 Zeichen zurück) mit SQL Server 2012 Developer Edition SP4 (KB4018073) (11.0.7001)
bevor Fehler 8631 angezeigt wird .
Als nächstes habe ich versucht, die Verkettungen mithilfe von Klammern so zu gruppieren, dass die Operation mehrere Gruppen von Verkettungen verkettet. Beispielsweise:
SET @S = (@A + @A + @A + @A) + (@A + @A + @A + @A) + (@A + @A + @A + @A);
Auf diese Weise konnte ich die bisherigen Grenzen von 3312 und 3513 Variablen weit überschreiten. Der aktualisierte Code lautet:
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);
Die Maximalwerte (für mich) sind jetzt 42
für die erste zu verwenden REPLICATE
, also 43 Variablen pro Gruppe, und dann 762
für die zweite REPLICATE
, also 762 Gruppen mit jeweils 43 Variablen. Die Anfangsgruppe ist mit zwei Variablen fest codiert.
Die Ausgabe zeigt nun, dass die @S
Variable 32.768 Zeichen enthält . Wenn ich die ursprüngliche Gruppe so aktualisiere, dass sie (@A+@A+@A)
nicht nur ist (@A+@A)
, wird folgende Fehlermeldung angezeigt:
Meldung 8632, Ebene 17, Status 2, Zeile XXXXX
Interner Fehler: Ein Limit für Ausdrucksdienste wurde erreicht. Suchen Sie in Ihrer Abfrage nach potenziell komplexen Ausdrücken und versuchen Sie, diese zu vereinfachen.
Beachten Sie, dass die Fehlernummer anders ist als zuvor. Es ist jetzt: 8632 . UND, ich habe das gleiche Limit, unabhängig davon, ob ich meine SQL Server 2012-Instanz oder die SQL Server 2017-Instanz verwende.
Es ist wahrscheinlich kein Zufall, dass die Obergrenze hier - 32.768 - die maximale Kapazität von SMALLINT
( Int16
in .NET) IF ab 0
(der maximale Wert ist 32.767, aber Arrays in vielen / den meisten Programmiersprachen sind 0-basiert) ist.