Questa domanda sembra davvero venire ogni tanto qui. Mark ha la risposta corretta (e più comunemente utilizzata), ma lascia che provi ad aggiungere ciò che posso per renderlo più chiaro.
Il messaggio di errore è leggermente fuorviante. SQL Server indica che non ha memoria sufficiente per eseguire la query, ma cosa significa in realtà è che non ha memoria sufficiente per parsing la query.
Quando si tratta di in esecuzione la query, SQL Server può utilizzare tutto ciò che desidera - gigabyte se necessario. L'analisi è un'altra storia; il server deve costruire un albero di analisi e c'è solo una quantità molto limitata di memoria disponibile per quello. Non ho mai trovato il limite effettivo documentato da nessuna parte, ma per un tipico lotto pieno di dichiarazioni INSERT
, non può gestire più di pochi MB alla volta.
Quindi, mi spiace dirti questo ma tu non puoi rendere SQL Server eseguire questo script esattamente come è scritto. Assolutamente no, non importa quali impostazioni modifichi.Tu, invece, dispone di una serie di opzioni per lavorare intorno ad esso:
In particolare, sono disponibili tre opzioni:
Usa GO
dichiarazioni. Questo è usato da SSMS e vari altri strumenti come un separatore di lotti. Invece di un singolo albero di analisi generato per l'intero script, vengono generati alberi di analisi individuali per ogni segmento del batch separati da GO
. Questo è quello che fa la maggior parte delle persone, ed è molto semplice rendere lo script transazionale sicuro, come altri hanno dimostrato e non ripeterò qui.
Invece di generare un enorme script per inserire tutte le righe, mantenere i dati in un file di testo (cioè separati da virgola). Quindi importarlo utilizzando bcp utility. Se è necessario che questo sia "scriptable", vale a dire che l'importazione deve avvenire nello stesso script/transazione dell'istruzione CREATE TABLE
, quindi utilizzare BULK INSERT. Anche se BULK INSERT
è un'operazione non registrata, che ci crediate o meno, è comunque possibile inserirla all'interno di un blocco BEGIN TRAN
/COMMIT TRAN
.
Se davvero, vuole veramente il INSERT
di essere un'operazione registrata, e non vogliono le inserzioni per accadere in batch, quindi è possibile utilizzare OPENROWSET per aprire un file di testo, file excel, ecc come "tabella" ad-hoc, quindi inserirla nella tabella appena creata. Normalmente sono riluttante a raccomandare l'uso di OPENROWSET
, ma poiché questo è chiaramente uno script amministrativo, non è davvero un grosso problema.
commenti precedenti suggeriscono che sei a disagio con # 1, anche se questo può essere solo a causa di un presupposto errato che non può essere fatto in una singola transazione, nel qual caso vedi Thomas ' risposta. Ma se sei morto per andare in un altro modo, ti suggerisco di andare con # 2, creando un file di testo e usando BULK INSERT
. Un esempio di script "sicuro" sarebbe:
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
Speriamo che questo ti aiuti a metterti sulla giusta strada. Sono abbastanza sicuro che questo copra tutte le opzioni disponibili "nella scatola" - oltre a queste, dovresti iniziare a scrivere programmi applicativi o script di shell per fare il lavoro, e non penso che quel livello di complessità sia davvero giustificato qui.
Fino a quando non viene modificato, significa AGGIUNGERE una dichiarazione 'GO' dopo ogni mille inserti. –
Grazie Alex - aggiornato come suggerito – Mark
Ho già utilizzato le istruzioni GO per risolvere il problema, ma non voglio utilizzare l'esecuzione in batch perché se ho qualche errore avrò problemi nella transazione di rollbacking ... – Tufo