Этот вопрос на самом деле выглядит так часто здесь. Mark имеет правильный (и наиболее часто используемый) ответ, но позвольте мне попытаться добавить все, что могу, чтобы сделать это понятным.
Сообщение об ошибке немного вводит в заблуждение. SQL Server сообщает вам, что у него недостаточно памяти для . Запустите запрос, но на самом деле это означает, что у него недостаточно памяти для . Проанализируйте запрос.
Когда дело доходит до работает запрос, SQL Server может использовать все, что он хочет - гигабайт, если необходимо. Размышление - это еще одна история; сервер должен построить дерево синтаксического анализа, и для этого имеется только ограниченный объем памяти. Я никогда не обнаружил, что фактический предел документирован где угодно, но для типичной партии, полной INSERT
, она не может обрабатывать более нескольких МБ за раз.
Так что я сожалею об этом, но вы не можете заставить SQL Server выполнить этот скрипт точно так, как он написан. Ни в коем случае, ни как, не важно, какие настройки вы настраиваете.Вы, однако, есть несколько вариантов, чтобы работать вокруг него:
В частности, у вас есть три варианта:
Используйте GO
заявления. Это используется SSMS и другими инструментами в качестве разделителя партий. Вместо единого дерева разбора, сгенерированного для всего сценария, для каждого сегмента партии, разделенного GO
, генерируются отдельные деревья синтаксического анализа. Это то, что делают большинство людей, и очень просто сделать сценарий безопасным для транзакций, как показали другие, и я не буду здесь повторять.
Вместо того, чтобы генерировать массивный скрипт для вставки всех строк, сохраняйте данные в текстовом файле (то есть разделенном запятой). Затем импортируйте его с помощью bcp utility. Если вам нужно, чтобы это было «scriptable», то есть импорт должен происходить в том же скрипте/транзакции, что и оператор CREATE TABLE
, а затем использовать BULK INSERT. Хотя BULK INSERT
является незарегистрированной операцией, верьте или нет, ее все равно можно разместить в блоке BEGIN TRAN
/COMMIT TRAN
.
Если вы действительно, действительно хотите INSERT
быть авторизован операция, и не хотят, чтобы Вставки произойти в партиях, то вы можете использовать OPENROWSET, чтобы открыть текстовый файл, первенствует файл и т.д. как ad-hoc "table", а затем вставьте это в свою недавно созданную таблицу. Обычно я не рекомендую использовать OPENROWSET
, но поскольку это явно административный скрипт, это не является серьезной проблемой.
Предыдущие комментарии предполагают, что вам неудобно с # 1, хотя это может быть просто из-за неправильного предположения, что это не может быть сделано в рамках одной транзакции, в этом случае см Thomas ' ответ. Но если вы мертвы, идя по другому пути, я предлагаю перейти с №2, создав текстовый файл и используя BULK INSERT
. Примером «безопасного» сценария будет:
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
Надеемся, что это поможет поставить вас на правильном пути. Я уверен, что это охватывает все ваши доступные опции «в коробке» - помимо них вам придется начинать писать реальные прикладные программы или сценарии оболочки для выполнения этой работы, и я не думаю, что уровень сложности действительно оправданно здесь.
До тех пор, пока он не будет отредактирован, он означает ДОБАВИТЬ инструкцию 'GO' после каждой тысячи вставки. –
Спасибо Alex - обновлено как предложено – Mark
Я уже использовал операторы GO для решения проблемы, но я не хочу использовать пакетный запуск, потому что, если у меня есть ошибка, у меня будут проблемы с откатом транзакций ... – Tufo