Esta pregunta parece surgir cada cierto tiempo aquí. Mark tiene la respuesta correcta (y más comúnmente empleada), pero déjame intentar agregar lo que pueda para que quede más claro.
El mensaje de error es un poco engañoso. SQL Server le dice que no tiene memoria suficiente para ejecutar la consulta, pero lo que realmente significa es que no tiene suficiente memoria para analizar la consulta.
Cuando se trata de ejecutando 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 sintáctico y solo hay una cantidad muy limitada de memoria disponible para eso. Nunca he encontrado el límite real documentado en ninguna parte excepto para un lote típico lleno de declaraciones INSERT
, no puede manejar más de unos pocos MB a la vez.
Así que lamento decirte esto pero no se puede hacer que SQL Server ejecute este script exactamente como está escrito. De ninguna manera, de ninguna manera, no importa qué ajustes modifiques.Usted, sin embargo, tiene una serie de opciones para trabajar alrededor de ella:
Específicamente, usted tiene tres opciones:
Uso GO
declaraciones. Esto es utilizado por SSMS y varias otras herramientas como un separador de lotes. En lugar de generar un único á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 sencillo hacer que el guión sea seguro para las transacciones, como otros han demostrado y no repetiré aquí.
En lugar de generar un script masivo para insertar todas las filas, conserve los datos en un archivo de texto (es decir, separados por comas). Luego impórtelo usando el bcp utility. Si necesita que esto sea "secuencia de comandos", es decir, la importación debe realizarse en la misma secuencia de comandos/transacción que la instrucción CREATE TABLE
, utilice el BULK INSERT. Aunque BULK INSERT
es una operación no registrada, lo crea o no, todavía se puede colocar dentro de un bloque BEGIN TRAN
/COMMIT TRAN
.
Si realmente, realmente desea el INSERT
a ser una operación registrada, y no quieren las inserciones que sucedan en lotes, a continuación, puede utilizar OPENROWSET para abrir un archivo de texto, archivo de Excel, etc. como una "tabla" ad-hoc, y luego insertar esto en su tabla recién creada. Normalmente soy reacio a recomendar el uso de OPENROWSET
, pero como esto es claramente un script administrativo, no es realmente un problema importante.
comentarios anteriores sugieren que se siente incómodo con # 1, a pesar de que sólo puede ser debido a una incorrecta suposición de que no se puede hacer en una sola transacción, en cuyo caso ver Thomas ' s respuesta. Pero si está decidido a seguir de otra manera, le sugiero ir con el n. ° 2, crear un archivo de texto y usar BULK INSERT
. Un ejemplo de un guión "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
Esperemos que esto le ayuda a poner en el camino correcto. Estoy bastante seguro de que esto cubre todas las opciones disponibles "en la caja". Más allá de esto, tendrías que empezar a escribir programas de aplicaciones reales o scripts de shell para hacer el trabajo, y no creo que ese nivel de complejidad sea realmente garantizado aquí.
Hasta que se edite, significa AGREGAR una instrucción 'GO' después de cada mil insertos. –
Gracias Alex - actualizado como sugerido – Mark
Ya utilicé declaraciones GO para resolver el problema, pero no quiero usar la ejecución por lotes porque si tengo algún error tendré problemas rodando la transacción ... – Tufo