Deze vraag lijkt hier eigenlijk zo nu en dan langs te komen. Mark heeft het juiste (en meest gebruikte) antwoord, maar laat me proberen toe te voegen wat ik kan om dit duidelijker te maken.
De foutmelding is een beetje misleidend. SQL Server vertelt u dat het niet genoeg geheugen heeft om uit te voeren de query, maar wat het echt betekent, is dat het niet genoeg geheugen heeft om te parseren de vraag.
Als het gaat om hardlopen de query kan SQL Server alles gebruiken wat het wil - gigabytes indien nodig. Parseren is een ander verhaal; de server moet een parse tree bouwen en daar is maar een zeer beperkte hoeveelheid geheugen voor beschikbaar. Ik heb nooit de werkelijke limiet ergens anders gedocumenteerd gevonden, behalve voor een typische batch vol INSERT
statements, kan het niet meer dan een paar MB tegelijk aan.
Het spijt me u dit te moeten zeggen, maar u kunt niet laat SQL Server dit script precies uitvoeren zoals het is geschreven. Op geen enkele manier, op geen enkele manier, maakt het niet uit welke instellingen u aanpast. U hebt echter een aantal opties om dit te omzeilen:
Concreet heb je drie opties:
-
Gebruik
GO
verklaringen. Deze wordt door SSMS en diverse andere tools gebruikt als batchscheider. In plaats van dat er een enkele ontledingsboom wordt gegenereerd voor het hele script, worden er afzonderlijke ontledingsbomen gegenereerd voor elk segment van de batch, gescheiden doorGO
. Dit is wat de meeste mensen doen, en het is heel eenvoudig om het script toch transactieveilig te maken, zoals anderen hebben aangetoond en ik zal het hier niet herhalen. -
In plaats van een enorm script te genereren om alle rijen in te voegen, bewaart u de gegevens in een tekstbestand (d.w.z. door komma's gescheiden). Importeer het vervolgens met het bcp-hulpprogramma . Als u wilt dat dit "scriptbaar" is, d.w.z. de import moet in hetzelfde script/dezelfde transactie gebeuren als de
CREATE TABLE
statement, gebruik dan BULK INSERT in plaats van. HoewelBULK INSERT
is een niet-gelogde bewerking, geloof het of niet, het kan nog steeds worden geplaatst in eenBEGIN TRAN
/COMMIT TRAN
blok. -
Als je echt, echt de
INSERT
. wilt om een gelogde bewerking te zijn en niet wilt dat de invoegingen in batches gebeuren, dan kunt u OPENROWSET om een tekstbestand, Excel-bestand, enz. als een ad-hoc "tabel" te openen en deze vervolgens in uw nieuw gemaakte tabel in te voegen. Normaal gesproken vind ik het afschuwelijk om ooit het gebruik vanOPENROWSET
aan te bevelen , maar aangezien dit duidelijk een administratief script is, is het niet echt een groot probleem.
Eerdere opmerkingen suggereren dat u zich niet op uw gemak voelt met #1, hoewel dat misschien komt door een onjuiste veronderstelling dat het niet in één enkele transactie kan worden gedaan, in welk geval Thomas
's antwoord. Maar als je vastbesloten bent om een andere kant op te gaan, raad ik aan om met #2 te gaan, een tekstbestand te maken en BULK INSERT
te gebruiken . Een voorbeeld van een "veilig" script zou zijn:
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
Hopelijk helpt dit je op de goede weg. Ik ben er vrij zeker van dat dit al je beschikbare "in the box" -opties omvat - buiten deze, zou je moeten beginnen met het schrijven van echte applicatieprogramma's of shellscripts om het werk te doen, en ik denk niet dat dat niveau van complexiteit is hier echt gerechtvaardigd.