Esta questão realmente parece surgir de vez em quando aqui. Marcar tem a resposta correta (e mais comumente empregada), mas deixe-me tentar adicionar o que puder para tornar isso mais claro.
A mensagem de erro é um pouco enganosa. O SQL Server informa que não tem memória suficiente para executar a consulta, mas o que realmente significa é que não tem memória suficiente para analisar A pergunta.
Quando se trata de executar a consulta, o SQL Server pode usar tudo o que quiser - gigabytes, se necessário. A análise é outra história; o servidor precisa construir uma árvore de análise e há apenas uma quantidade muito limitada de memória disponível para isso. Eu nunca encontrei o limite real documentado em nenhum lugar, exceto para um lote típico cheio de
INSERT
instruções, ele não pode lidar com mais do que alguns MB de cada vez. Sinto informar isso, mas você não pode faça o SQL Server executar este script exatamente como está escrito. De jeito nenhum, de jeito nenhum, não importa quais configurações você ajuste. No entanto, você tem várias opções para contornar isso:
Especificamente, você tem três opções:
-
UseGO
declarações. Isso é usado pelo SSMS e várias outras ferramentas como separador de lote. Em vez de uma única árvore de análise ser gerada para todo o script, árvores de análise individuais são geradas para cada segmento do lote separado porGO
. Isso é o que a maioria das pessoas faz, e é muito simples ainda tornar o script transacionalmente seguro, como outros demonstraram e não vou repetir aqui.
-
Em vez de gerar um script massivo para inserir todas as linhas, mantenha os dados em um arquivo de texto (ou seja, separados por vírgula). Em seguida, importe-o usando o utilitário bcp . Se você precisar que isso seja "scriptável" - ou seja, a importação precisa acontecer no mesmo script/transação que oCREATE TABLE
declaração e use BULK INSERT em vez de. EmboraBULK INSERT
é uma operação não registrada, acredite ou não, ela ainda pode ser colocada dentro de umBEGIN TRAN
/COMMIT TRAN
quadra.
-
Se você realmente quer oINSERT
para ser uma operação registrada e não quiser que as inserções aconteçam em lotes, você pode usar OPENROWSET para abrir um arquivo de texto, arquivo excel, etc. como uma "tabela" ad-hoc e, em seguida, insira-o em sua tabela recém-criada. Normalmente sou relutante em recomendar o uso deOPENROWSET
, mas como este é claramente um script administrativo, não é realmente um grande problema.
Comentários anteriores sugerem que você não se sente à vontade com o número 1, embora isso possa ser apenas devido a uma suposição incorreta de que isso não pode ser feito em uma única transação. Nesse caso, consulte Thomas a resposta de. Mas se você está decidido a seguir outro caminho, sugiro seguir o nº 2, criando um arquivo de texto e usando
BULK INSERT
. Um exemplo de script "seguro" seria: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
Espero que isso ajude a colocá-lo no caminho certo. Tenho certeza de que isso abrange todas as opções disponíveis "na caixa" - além dessas, você teria que começar a escrever programas de aplicativos reais ou scripts de shell para fazer o trabalho, e não acho que esse nível de complexidade seja realmente justificado aqui.