Insgesamt habe ich eine große (unvermeidbare) dynamische SQL-Abfrage. Aufgrund der Anzahl der Felder in den Auswahlkriterien wächst die Zeichenfolge mit dem dynamischen SQL um mehr als 4000 Zeichen. Jetzt verstehe ich, dass für maximal 4000 festgelegt ist NVARCHAR(MAX)
, aber wenn Sie sich die ausgeführte SQL in Server Profiler für die Anweisung ansehen
DELARE @SQL NVARCHAR(MAX);
SET @SQL = 'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO
Scheint zu funktionieren (!?). Bei einer anderen Abfrage, die ebenfalls groß ist, wird ein Fehler ausgegeben, der mit diesem 4000-Limit (!?) Verbunden ist. Im Grunde genommen wird die gesamte SQL nach diesem 4000-Limit gekürzt und es tritt ein Syntaxfehler auf. Trotzdem wird im Profiler diese dynamische SQL-Abfrage vollständig (!?) Angezeigt.
Was genau passiert hier und sollte ich diese @ SQL-Variable einfach in VARCHAR konvertieren und damit weitermachen?
Vielen Dank für Ihre Zeit.
Ps. Es wäre auch schön, mehr als 4000 Zeichen ausdrucken zu können, um diese großen Fragen zu beantworten. Die folgenden sind auf 4000 begrenzt
SELECT CONVERT(XML, @SQL);
PRINT(@SQL);
Gibt es einen anderen coolen Weg?
quelle
Antworten:
Dein Verständnis ist falsch.
nvarchar(max)
kann bis zu (und manchmal auch darüber hinaus) 2 GB Daten (1 Milliarde Doppelbyte-Zeichen) speichern.Von nchar und nvarchar in Books online ist die Grammatik
Der
|
Charakter bedeutet, dass dies Alternativen sind. dh Sie geben entwedern
oder das Literal anmax
.Wenn Sie sich für die Angabe eines bestimmten Objekts entscheiden,
n
muss dieses zwischen 1 und 4.000 liegen. Bei Verwendung wirdmax
es jedoch als Datentyp für große Objekte definiert (dessen Ersatzntext
veraltet ist).Tatsächlich scheint es in SQL Server 2008 so zu sein, dass für eine Variable das 2-GB-Limit auf unbestimmte Zeit überschritten werden kann, sofern genügend Speicherplatz in
tempdb
( hier gezeigt ) vorhanden ist.In Bezug auf die anderen Teile Ihrer Frage
Das Abschneiden beim Verketten hängt vom Datentyp ab.
varchar(n) + varchar(n)
wird bei 8.000 Zeichen abgeschnitten.nvarchar(n) + nvarchar(n)
wird bei 4.000 Zeichen abgeschnitten.varchar(n) + nvarchar(n)
wird bei 4.000 Zeichen abgeschnitten.nvarchar
hat eine höhere Priorität, so dass das Ergebnis istnvarchar(4,000)
[n]varchar(max)
+[n]varchar(max)
wird nicht abgeschnitten (für <2 GB).varchar(max)
+varchar(n)
wird nicht abgeschnitten (für <2 GB) und das Ergebnis wird wie folgt eingegebenvarchar(max)
.varchar(max)
+nvarchar(n)
wird nicht abgeschnitten (für <2 GB) und das Ergebnis wird wie folgt eingegebennvarchar(max)
.nvarchar(max)
+varchar(n)
konvertiert zuerst dievarchar(n)
Eingabe innvarchar(n)
und führt dann die Verkettung durch. Wenn die Länge dervarchar(n)
Zeichenfolge größer als 4.000 Zeichen ist, erfolgt dienvarchar(4000)
Umwandlung und es kommt zu einem Abschneiden .Datentypen von String-Literalen
Wenn Sie die Verwendung
N
Präfix und die Zeichenfolge <= 4.000 Zeichen lange wird es als eingegeben werden ,nvarchar(n)
won
die Länge der Saite. SoN'Foo'
wird wienvarchar(3)
zum Beispiel behandelt . Wenn die Zeichenfolge länger als 4.000 Zeichen ist, wird sie als behandeltnvarchar(max)
Wenn Sie nicht über die Verwendung
N
Präfix und die Zeichenfolge <= 8.000 Zeichen lange wird es als eingegeben werden ,varchar(n)
won
die Länge der Saite. Wenn länger alsvarchar(max)
Wenn für beide oben genannten Punkte die Länge der Zeichenfolge Null
n
ist, wird sie auf 1 gesetzt.Neuere Syntaxelemente.
1. Die
CONCAT
Funktion hilft hier nichtDas Obige gibt 8000 für beide Verkettungsmethoden zurück.
2. Seien Sie vorsichtig mit
+=
Kehrt zurück
Beachten Sie, dass
@A
eine Kürzung aufgetreten ist.So lösen Sie das aufgetretene Problem.
Sie werden entweder abgeschnitten, weil Sie zwei Nicht-
max
Datentypen miteinander verketten oder weil Sie einevarchar(4001 - 8000)
Zeichenfolge mit einernvarchar
typisierten Zeichenfolge (geradenvarchar(max)
) verknüpfen .Um das zweite Problem zu vermeiden, stellen Sie einfach sicher, dass alle Zeichenfolgenliterale (oder zumindest diejenigen mit Längen im Bereich von 4001 bis 8000) vorangestellt sind
N
.Um das erste Problem zu vermeiden, ändern Sie die Zuordnung von
Zu
so dass ein
NVARCHAR(MAX)
von Anfang an an der Verkettung beteiligt ist (als Ergebnis jeder Verkettung wird sichNVARCHAR(MAX)
dies auch ausbreiten)Vermeiden von Kürzungen beim Anzeigen
Stellen Sie sicher, dass der Modus "Ergebnisse in Raster" ausgewählt ist, den Sie verwenden können
Mit den SSMS-Optionen können Sie eine unbegrenzte Länge für
XML
Ergebnisse festlegen . Dasprocessing-instruction
Bit vermeidet Probleme mit Zeichen wie<
das Anzeigen als<
.quelle
nvarchar(4000)
unterwegs eine implizite Besetzung . Wenn ein Zeichenfolgenliteral weniger als 4.000 Zeichen enthält, wird es als behandeltnvarchar(x)
. Wenn Sie einen anderennvarchar(x)
Wert damit verketten, wird dieser eher abgeschnitten als gesendetnvarchar(max)
DECLARE @SQL NVARCHAR(MAX) = ''; SET @SQL = @SQL +
so zu ändern, dassNVARCHAR(MAX)
an der Verkettung beteiligt ist.N
Präfix, das alsnvarchar(max)
ohne behandelt wird, wird es so behandelt, als würde esvarchar(n)
implizit umgewandelt,nvarchar(4000)
wenn Sie sich mit einemnvarchar
Okay, wenn Sie später das Problem haben, dass Sie eine Abfrage haben, die größer als die zulässige Größe ist (was passieren kann, wenn sie weiter wächst), müssen Sie sie in Blöcke aufteilen und die Zeichenfolgenwerte ausführen. Angenommen, Sie haben eine gespeicherte Prozedur wie die folgende:
quelle
Sie müssen auch nvarchar-Text verwenden. Das heißt, Sie müssen einfach ein "N" vor Ihrer massiven Saite haben und das war's! Keine Einschränkung mehr
quelle
nvarchar(n)
wobei n die Länge der Zeichenfolge ist. So wird N'Foo 'wienvarchar(3)
zum Beispiel behandelt . Wenn die Zeichenfolge länger als 4.000 Zeichen ist, wird sie als behandeltnvarchar(max)
. Wenn Sie das Präfix N nicht verwenden und die Zeichenfolge <= 8.000 Zeichen lang ist, wird Folgendes eingegeben,varchar(n)
wobei n die Länge der Zeichenfolge ist. Wenn länger alsvarchar(max)
. Wenn für beide oben genanntenDie akzeptierte Antwort hat mir geholfen, aber ich bin beim Verketten von Varcharen mit Fallaussagen gestolpert. Ich weiß, dass die Frage des OP keine case-Anweisungen beinhaltet, aber ich dachte, dies wäre hilfreich, um sie hier für andere wie mich zu posten, die hier gelandet sind, während sie Schwierigkeiten hatten, lange dynamische SQL-Anweisungen mit case-Anweisungen zu erstellen.
Bei Verwendung von case-Anweisungen mit Zeichenfolgenverkettung gelten die in der akzeptierten Antwort genannten Regeln für jeden Abschnitt der case-Anweisung unabhängig.
quelle
quelle