sql >> Base de Datos >  >> RDS >> Sqlserver

SQL Server 2005 Error 701:memoria insuficiente

Esta pregunta en realidad parece surgir de vez en cuando aquí. Marcar tiene la respuesta correcta (y la más utilizada), pero déjame intentar agregar lo que pueda para aclarar esto.

El mensaje de error es un poco engañoso. SQL Server le dice que no tiene suficiente memoria para ejecutar la consulta, pero lo que realmente significa es que no tiene suficiente memoria para analizar la consulta.

Cuando se trata de correr la consulta, SQL Server puede usar todo lo que quiera, gigabytes si es necesario. El análisis es otra historia; el servidor tiene que construir un árbol de análisis y solo hay una cantidad muy limitada de memoria disponible para eso. Nunca encontré el límite real documentado en ninguna parte, excepto para un lote típico lleno de INSERT declaraciones, no puede manejar más de unos pocos MB a la vez.

Lamento decirte esto, pero no puedes haga que SQL Server ejecute este script exactamente como está escrito. De ninguna manera, no importa qué configuración modifiques. Sin embargo, tiene varias opciones para evitarlo:

En concreto, tienes tres opciones:

  1. Usa GO declaraciones. SSMS y varias otras herramientas lo utilizan como separador de lotes. En lugar de generar un solo árbol de análisis para todo el script, se generan árboles de análisis individuales para cada segmento del lote separados por GO . Esto es lo que hace la mayoría de la gente, y es muy simple hacer que el script sea transaccionalmente seguro, como otros han demostrado y no lo repetiré aquí.

  2. En lugar de generar un script masivo para insertar todas las filas, mantenga los datos en un archivo de texto (es decir, separados por comas). Luego impórtelo usando la utilidad bcp . Si necesita que esto sea "programable", es decir, la importación debe ocurrir en el mismo script/transacción que CREATE TABLE declaración, luego use BULK INSERT en cambio. Aunque BULK INSERT es una operación no registrada, créalo o no, todavía se puede colocar dentro de un BEGIN TRAN / COMMIT TRAN bloquear.

  3. Si realmente quieres el INSERT para ser una operación registrada y no desea que las inserciones se realicen en lotes, entonces puede usar CONJUNTO DE FICHAS ABIERTAS para abrir un archivo de texto, archivo de Excel, etc. como una "tabla" ad-hoc, y luego insertarlo en su tabla recién creada. Normalmente detesto recomendar el uso de OPENROWSET , pero como se trata claramente de una secuencia de comandos administrativa, en realidad no es un problema importante.

Los comentarios anteriores sugieren que no se siente cómodo con el n. ° 1, aunque eso puede deberse a una suposición incorrecta de que no se puede hacer en una sola transacción, en cuyo caso consulte Tomás la respuesta Pero si está decidido a ir de otra manera, le sugiero ir con el n. ° 2, crear un archivo de texto y usar BULK INSERT . Un ejemplo de un script "seguro" sería:

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 esto te ayude a ponerte en el camino correcto. Estoy bastante seguro de que esto cubre todas las opciones "en el cuadro" disponibles; más allá de estas, tendría que comenzar a escribir programas de aplicación reales o scripts de shell para hacer el trabajo, y no creo que ese nivel de complejidad sea realmente garantizado aquí.