Wydaje się, że to pytanie pojawia się tu od czasu do czasu. Mark ma poprawną (i najczęściej używaną) odpowiedź, ale spróbuję dodać, co mogę, aby to było jaśniejsze.
Komunikat o błędzie jest trochę mylący. SQL Server informuje, że nie ma wystarczającej ilości pamięci, aby uruchomić zapytanie, ale tak naprawdę oznacza to, że nie ma wystarczającej ilości pamięci, aby przeanalizować zapytanie.
Jeśli chodzi o bieganie kwerendy SQL Server może wykorzystać wszystko, czego chce - w razie potrzeby gigabajty. Parsowanie to inna historia; serwer musi zbudować drzewo parsowania, a na to dostępna jest tylko bardzo ograniczona ilość pamięci. Nigdy nie znalazłem faktycznego udokumentowanego limitu nigdzie poza typową partią pełną INSERT
oświadczenia, nie może obsłużyć więcej niż kilka MB na raz.
Przykro mi, że ci to mówię, ale nie możesz sprawiają, że SQL Server wykonuje ten skrypt dokładnie tak, jak jest napisany. Nie ma mowy, nie ma jak, nie ma znaczenia, jakie ustawienia dostosujesz. Masz jednak kilka możliwości obejścia tego problemu:
W szczególności masz trzy opcje:
-
Użyj
GO
sprawozdania. Jest to używane przez SSMS i różne inne narzędzia jako separator wsadowy. Zamiast pojedynczego drzewa analizowania generowanego dla całego skryptu, dla każdego segmentu wsadu oddzielonego znakiemGO
generowane są pojedyncze drzewa analizowania . To jest to, co robi większość ludzi, i nadal bardzo łatwo jest uczynić skrypt bezpiecznym transakcyjnie, jak pokazali inni i nie będę tutaj powtarzał. -
Zamiast generować ogromny skrypt do wstawiania wszystkich wierszy, zachowaj dane w pliku tekstowym (tj. oddzielone przecinkami). Następnie zaimportuj go za pomocą narzędzia bcp . Jeśli potrzebujesz, aby było to „skryptowalne” – tj. import musi odbywać się w tym samym skrypcie/transakcji, co
CREATE TABLE
oświadczenie, a następnie użyj WKŁADKA ZBIORCZA zamiast. ChociażBULK INSERT
jest operacją niezarejestrowaną, wierzcie lub nie, nadal można ją umieścić wBEGIN TRAN
/COMMIT TRAN
blokować. -
Jeśli naprawdę, naprawdę chcesz
INSERT
aby być zarejestrowaną operacją i nie chcesz, aby wstawienia odbywały się partiami, możesz użyć OPENROWSET aby otworzyć plik tekstowy, plik Excela itp. jako „tablicę” ad-hoc, a następnie wstawić go do nowo utworzonej tabeli. Zwykle niechętnie zalecam użycieOPENROWSET
, ale ponieważ jest to wyraźnie skrypt administracyjny, nie stanowi to większego problemu.
Poprzednie komentarze sugerują, że czujesz się niekomfortowo z #1, chociaż może to wynikać tylko z błędnego założenia, że nie można tego zrobić w pojedynczej transakcji, w takim przypadku zobacz Thomas
odpowiedź. Ale jeśli nie masz ochoty iść w inną stronę, sugeruję przejście do punktu 2, utworzenie pliku tekstowego i użycie BULK INSERT
. Przykładem „bezpiecznego” skryptu będzie:
BEGIN TRAN
BEGIN TRY
CREATE TABLE MyTable (...)
BULK INSERT MyTable
FROM 'C:\Scripts\Data\MyTableData.txt'
WITH (
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\r\n',
BATCHSIZE = 1000,
MAXERRORS = 1
)
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
END CATCH
Mam nadzieję, że to pomoże Ci na właściwej drodze. Jestem prawie pewien, że obejmuje to wszystkie dostępne opcje "w pudełku" - poza nimi musiałbyś zacząć pisać rzeczywiste aplikacje lub skrypty powłoki, aby wykonać pracę, i nie sądzę, aby poziom złożoności był naprawdę uzasadnione.