Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Erro 701 do SQL Server 2005 - memória insuficiente


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:

  1. Use GO 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 por GO . 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.

  2. 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 o CREATE TABLE declaração e use BULK INSERT em vez de. Embora BULK INSERT é uma operação não registrada, acredite ou não, ela ainda pode ser colocada dentro de um BEGIN TRAN / COMMIT TRAN quadra.

  3. Se você realmente quer o INSERT 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 de OPENROWSET , 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.