Wszystko, mam duże (nieuniknione) dynamiczne zapytanie SQL. Ze względu na liczbę pól w kryteriach selekcji ciąg znaków zawierający dynamiczny SQL rośnie o ponad 4000 znaków. Teraz rozumiem, że istnieje ustawione maks. 4000 dla NVARCHAR(MAX)
, ale patrząc na wykonanie instrukcji SQL w Server Profiler dla instrukcji
DELARE @SQL NVARCHAR(MAX);
SET @SQL = 'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO
Wydaje się, że działa (!?), dla innego zapytania, które również jest duże, generuje błąd, który jest powiązany z tym limitem 4000 (!?), w zasadzie obcina cały SQL po tym limicie 4000 i zostawia mnie z błędem składniowym. Mimo to w profilerze pokazuje to dynamiczne zapytanie SQL w całości (!?).
Co dokładnie się tutaj dzieje i czy powinienem po prostu przekonwertować tę zmienną @SQL na VARCHAR i zająć się tym?
Dziękuję za Twój czas.
Ps. Byłoby również miło móc wydrukować ponad 4000 znaków, aby spojrzeć na te duże zapytania. Poniższe są ograniczone do 4000
SELECT CONVERT(XML, @SQL);
PRINT(@SQL);
czy jest jakiś inny fajny sposób?
źródło
Odpowiedzi:
Twoje rozumienie jest błędne.
nvarchar(max)
może przechowywać do (a czasami więcej) 2 GB danych (1 miliard znaków dwubajtowych).Od nchar i nvarchar w Book online gramatyka jest
Te
|
środki te mają charakter alternatywy. tzn. określasz albon
albo literałmax
.Jeśli zdecydujesz się określić konkretny,
n
musi to być od 1 do 4000, ale użyciemax
definiuje go jako typ danych dużego obiektu (zamiennikntext
jest przestarzały).W rzeczywistości w SQL Server 2008 wydaje się, że dla zmiennej limit 2 GB może zostać przekroczony w nieskończoność, z zastrzeżeniem wystarczającej ilości miejsca w
tempdb
( pokazane tutaj )Odnośnie innych części twojego pytania
Obcinanie przy konkatenacji zależy od typu danych.
varchar(n) + varchar(n)
zostanie obcięty do 8 000 znaków.nvarchar(n) + nvarchar(n)
zostanie obcięty do 4000 znaków.varchar(n) + nvarchar(n)
zostanie obcięty do 4000 znaków.nvarchar
ma wyższy priorytet, więc wynik jestnvarchar(4,000)
[n]varchar(max)
+[n]varchar(max)
nie zostanie obcięty (dla <2 GB).varchar(max)
+varchar(n)
nie zostanie obcięty (dla <2 GB), a wynik zostanie wpisany jakovarchar(max)
.varchar(max)
+nvarchar(n)
nie zostanie obcięty (dla <2 GB), a wynik zostanie wpisany jakonvarchar(max)
.nvarchar(max)
+varchar(n)
najpierw przekonwertuje danevarchar(n)
wejściowe,nvarchar(n)
a następnie dokona konkatenacji. Jeśli długośćvarchar(n)
ciągu jest większa niż 4000 znaków, rzutowanie zostanie skierowane nanvarchar(4000)
i nastąpi obcięcie .Typy danych literałów łańcuchowych
Jeśli użyjesz
N
prefiksu, a ciąg ma <= 4000 znaków, zostanie on wpisany jakonvarchar(n)
gdzien
jest długością ciągu. TakN'Foo'
będzie traktowane jaknvarchar(3)
np. Jeśli ciąg jest dłuższy niż 4000 znaków, zostanie potraktowany jakonvarchar(max)
Jeśli nie użyjesz
N
prefiksu, a ciąg ma <= 8000 znaków, zostanie on wpisany jakovarchar(n)
gdzien
jest długością łańcucha. Jeśli dłużej jakvarchar(max)
Dla obu powyższych, jeśli długość łańcucha wynosi zero, to
n
jest ustawiana na 1.Nowsze elementy składni.
1.
CONCAT
funkcja nie pomaga tutajPowyższe zwraca 8000 dla obu metod konkatenacji.
2. Uważaj z
+=
Zwroty
Zauważ, że
@A
napotkano obcięcie.Jak rozwiązać napotkany problem.
Otrzymujesz obcięcie, ponieważ łączysz ze sobą dwa
max
typy niebędące typami danych lub ponieważ łączyszvarchar(4001 - 8000)
łańcuch znvarchar
wpisanym ciągiem (parzystymnvarchar(max)
).Aby uniknąć drugiego problemu, po prostu upewnij się, że wszystkie literały łańcuchowe (lub przynajmniej te o długościach z zakresu 4001 - 8000) są poprzedzone
N
.Aby uniknąć pierwszego problemu, zmień przydział z
Do
tak, aby an
NVARCHAR(MAX)
był zaangażowany w konkatenację od początku (w wyniku każdego konkatenacji będzie to również sięNVARCHAR(MAX)
propagować)Unikanie obcinania podczas przeglądania
Upewnij się, że masz wybrany tryb „wyniki do siatki”, a następnie możesz go użyć
Opcje SSMS pozwalają ustawić nieograniczoną długość
XML
wyników. Tenprocessing-instruction
bit pozwala uniknąć problemów ze znakami, takimi jak<
wyświetlanie jako<
.źródło
nvarchar(4000)
. Jeśli literał ciągu ma mniej niż 4000 znaków, jest traktowany jakonvarchar(x)
. Łączenie z nim innejnvarchar(x)
wartości zostanie obcięte, a nie przesłane donvarchar(max)
DECLARE @SQL NVARCHAR(MAX) = ''; SET @SQL = @SQL +
tak, abyNVARCHAR(MAX)
w konkatenacji był zaangażowany element.N
przedrostkiem, który będzie traktowany jakonvarchar(max)
bez niego, będzie traktowany jakovarchar(n)
następnie domyślnie rzutowany,nvarchar(4000)
gdy łączysz się znvarchar
Okay, więc jeśli później problem będzie polegał na tym, że masz zapytanie, które jest większe niż dopuszczalny rozmiar (co może się zdarzyć, jeśli będzie rosło), będziesz musiał podzielić je na fragmenty i wykonać wartości ciągu. Załóżmy więc, że masz procedurę składowaną, taką jak:
źródło
Musisz też użyć tekstu nvarchar. to znaczy, że musisz po prostu mieć „N” przed swoją masywną struną i to wszystko! nie ma już ograniczeń
źródło
nvarchar(n)
gdzie n jest długością łańcucha. Więc N'Foo 'będzie traktowane jaknvarchar(3)
na przykład. Jeśli ciąg jest dłuższy niż 4000 znaków, zostanie potraktowany jakonvarchar(max)
. Jeśli nie użyjesz przedrostka N, a ciąg ma <= 8000 znaków, zostanie wpisany tak, jakvarchar(n)
gdzie n jest długością łańcucha. Jeśli dłużej jakvarchar(max)
. W obu powyższych przypadkach, jeśli długość łańcucha wynosi zero, wówczas n jest ustawione na 1.Zaakceptowana odpowiedź pomogła mi, ale potknąłem się podczas wykonywania konkatenacji varcharów obejmujących opisy przypadków. Wiem, że pytanie OP nie obejmuje opisów przypadków, ale pomyślałem, że byłoby to pomocne dla innych, takich jak ja, którzy znaleźli się tutaj, walcząc z budowaniem długich dynamicznych instrukcji SQL zawierających opisy przypadków.
W przypadku stosowania instrukcji case z konkatenacją ciągów zasady wymienione w zaakceptowanej odpowiedzi mają zastosowanie do każdej sekcji opisu przypadku niezależnie.
źródło
źródło