Использование пакетных сценариев и SQLCMD для записи данных базы данных

Tags: database, SQLCMD

Эта статья посвящена использованию средства сценария DOS Batch командной строки Windows вместе с SQLCMD для записи содержимого каждой таблицы в базе данных в локальную файловую систему. Он показывает, как использовать временные хранимые процедуры для получения преимущества.

Просто чтобы сделать это немного сложнее, мы делаем это в расширенном JSON (формат MongoDB), но мы включили доступ к файлам с процедурами для выполнения этого в обычном JSON или массиве JSON. Также будут размещены файлы схемы JSON. При настройке он также будет выполнять вывод в формате XML или табуляции.

Первоначально это было сделано, потому что нужно было написать утилиту для копирования базы данных SQL Server в MongoDB. Утилита MongoImport не хотела играть с PowerShell, который является предпочтительным способом сценариев любого разработчика Windows. Поэтому это было сделано как старомодный пакетный файл, командный файл, назовите его как хотите.

В этом сценарии мы объединим три слегка нестандартных метода: пакетные сценарии Dos, сценарии SQLCMD и использование временных процедур в SQL Server.

Пакетные сценарии Dos

Пакетные файлы написаны на языке сценариев для оболочки командной строки Microsoft. Он произошел от языка пакетных сценариев MS-DOS, COMMAND.EXE и CMD.EXE. Обычно они имеют расширение .BAT или .CMD. Пакетные файлы должны были быть заменены PowerShell. Проблема с пакетными файлами заключается в том, что этот формат со временем развивался разработчиками MSDOS / Windows, которые не имеют общего представления о том, как должен работать язык сценариев, так что теперь возникла эта путаница переключателей, загадочная пунктуация, странные условности и взломы. Если вам кажется, что мы преувеличиваем, просто прочитайте отличную документацию, встроенную в командную оболочку. Если вас это не ужасает, значит вы не читаете его правильно. Чтобы прочитать полный текст, введите в командной оболочке имена всех команд, за которыми следует /?

Несмотря на все ожидания, сценарии DOS процветали. На сайте Rosetta Code сценарии пакетных файлов DOS конкурируют с другими языками для решения компьютерных задач и задач. Старые группы новостей MSDOS Batch все еще активны. Существует множество архивов сценариев DOS и менеджер пакетов для пакетных сценариев Windows, написанных, конечно, в виде пакетного файла. Множество людей с серой мордой накопили опыт работы с пакетами оболочек DOS и не видят причин для изменений или преобразования своих бесчисленных сценариев. Переполнение стека полно полезных вопросов и ответов. Кто-то даже написал приключенческие игры, ролевые игры и трехмерное моделирование в пакетных сценариях DOS: не потому, что это мудро, а потому, что это сложно и вдохновляюще.

SQLCMD

Исполняемый файл командной строки SQLCMD - замечательный инструмент, но вам действительно нужно часто его использовать, чтобы запомнить все важные параметры, параметры командной строки, переменные сценариев и команды sqlcmd. Самый важный совет, который дает MSDN, - это делать как можно больше за один сеанс SQLCMD и полностью использовать команды sqlcmd, многие из которых работают в режиме SQLCMD SSMS. Вам понадобятся инструкции MSDN по SQLCMD, когда вы будете работать.

Временные процедуры

Мы упоминали об этом в предыдущей статье. Эту технику хорошо использовать, загружая все необходимые процедуры в начале сценария sqlcmd, и процедуры остаются на протяжении всего сценария, поскольку все они выполняются в одном соединении. Разрыв не требуется, поскольку временные процедуры удаляются вместе с временными таблицами при закрытии соединения.

Сценарий

Сценарий хранит учетные данные в виде простого текста в пользовательской области, полагаясь на безопасность NTFS для предотвращения их раскрытия. Это не так хорошо, но намного лучше, чем встраивание пользовательских идентификаторов или паролей в скрипт.

Сценарий связывается с базой данных, чтобы получить список таблиц в базе данных, которую вы хотите использовать, и получает список схем и имен таблиц в виде табличной спецификации. С помощью этого списка он создает сценарий SQLCMD, который записывает результаты для каждой таблицы в отдельный файл в указанном вами каталоге. Затем он выполняет этот скрипт.

Сценарий записывает несколько предварительных данных в файл SQL, которые в конечном итоге будут выполнены. Источник для этой процедуры здесь

--specify the name of the error file

:Error "C:\Users\phil\RunBatch\error.log"

--Execute preliminary script to add the temp procedure(s)

:r MyPath\JSONSQLServerRoutines\SaveExtendedJsonDataFromTable.sql

USE AdventureWorks2016

:XML on

set nocount on


Затем для каждой таблицы он делает, в данном случае,
Person.PhoneNumberType, который записывает в файл SQL, который затем выполняется, инструкции в командах SQL и SQLCMD, чтобы записать JSON-представление содержимого таблиц в файл.

GO

:Out MyDirectoryPath\AdventureWorks2016\Person.PhoneNumberType.json

DECLARE @Json NVARCHAR(MAX)

EXECUTE #SaveExtendedJsonDataFromTable @TableSpec='Person.PhoneNumberType',@JSONData=@json OUTPUT

Select @json

Процедура #SaveExtendedJSONDataFromTable выполняет большую часть работы. Она создает документ JSON, содержащий данные из таблицы, написанные на диалекте MongoDB JSON, вызываемые Extended JSON. Если вы хотите экспортировать обычный JSON, используйте взамен SaveJsonDataFromTable.sql. Когда этот сценарий выполняется SQLCMD в качестве заключительной части пакетного сценария DOS, он заканчивается всеми файлами, записанными в выбранный вами каталог.

 

Вот сценарий. Во-первых, вам нужно изменить параметры в начале скрипта, чтобы указать ваш рабочий каталог, имя, которое вы хотите для своего файла SQLCMD, имя вашего файла ошибок, путь к вашему предварительному файлу SQL (с процедурами или средствами инициализации) и имя базы данных, для которой вы хотите выполнить скрипт. Затем вам нужно создать файл учетных данных вместе с именем вашего сервера. Вы делаете это, выполняя закомментированный раздел в начале, заполняя учетные данные и выполняя только этот пакет.

 

echo -S Bluebottle/Fly -U Queen -P NotAPassword9>%userProfile%\MyServerSqlCmd.txt

REM Test out that it was properly saved

Set /p TheServer=<%userProfile%\MyServerSqlCmd.txt

echo %TheServer%


Теперь мы готовы попробовать это. Такова небольшая своенравность пакетных файлов DOS, что они могут не запуститься полностью с первого раза. К счастью, ваш журнал ошибок расскажет вам совсем немного, и если вы прочитаете попытку, сделанную в файле SQLCMD, она должна указать, где что-то сломалось. Для отладки сначала удалите @echo в автономном режиме, чтобы увидеть, как выполнялся пакет.
Здесь вы найдете больше подсказок.

@echo off

VERIFY errors 2>nul

  SETLOCAL ENABLEEXTENSIONS

  IF ERRORLEVEL 1 echo Unable to enable extensions

REM before you start, you need to write out your SQLCMD credentials to a file in your user

rem area using code like this, if you use SQL Server Credentials ...

Rem echo -S MyServer -U MyUserName -P MyPassword>%userProfile%\MyServerSqlCmd.txt

REM ... or like this if you use windows security

REM echo -S MyServer  >%userProfile%\MyServerSqlCmd.txt

REM

REM read in your SQLCMD command and credentials

Set /p TheServer=<%userProfile%\MyServerSqlCmd.txt

REM Specify your work directory. I chose 'RunBatch' in my user area

Set workpath=%userProfile%\RunBatch

REM specify the name of your SQLCMD file

Set TheSQLCMDFileToExecute=%workpath%\SQLCMDFile.sql

REM Specify what preliminary file you need to set up

Set PreliminarySQL=S:\work\Github\JSONSQLServerRoutines\SaveExtendedJsonDataFromTable.sql

REM choose the name of your error file

Set Errorfile=%workpath%\error.log

REM and specify the name of your database that you want to use

Set Database=AdventureWorks2016

REM check whether the workpath directory exists

if not exist "%workpath%\" (md %workpath%)

if ERRORLEVEL 1 (

 echo An error creating "%workpath%" directory occurred

 goto bombsite)

REM check whether the database directory within the workpath directory exists

if not exist "%workpath%\%Database%\" (md %workpath%\%Database%)

if ERRORLEVEL 1 (

echo An error creating "%workpath%\%Database%" occurred

goto bombsite)

rem Write out the header to the SQLCMD file to execute

(

echo --specify the name of the error file

echo :Error "%Errorfile%"

echo --Execute prelimiary

echo :r %PreliminarySQL%

echo USE %Database%

echo :XML on

echo set nocount on

) >%TheSQLCMDFileToExecute%

Rem Create the query that brings you the list of tables

Set QUERY="SET NOCOUNT ON; SELECT Object_Schema_Name(object_id)+'.'+name AS The_Tables FROM sys.tables WHERE is_ms_shipped=0;"

REM Execute the query and create the entire SQL Command file that will be executed

for /F usebackq %%i in (`sqlcmd %TheServer% -d %Database% -h -1  -f 65001 -Q %QUERY%`) do (

rem for every tablespec in the list append the following text ....

       if ERRORLEVEL 1 (

 echo An error accessing  %Database% to get the list of tables occurred

         goto bombsite)

(

echo :Out %workpath%\%Database%\%%i.json

echo DECLARE @Json NVARCHAR^(MAX^)

       echo EXECUTE #SaveExtendedJsonDataFromTable @TableSpec=^'%%i^',@JSONData=@json OUTPUT

       echo Select @json

echo GO

) >>%TheSQLCMDFileToExecute%

)

Rem Now that is done, we just execute the file

sqlcmd %TheServer% -d %Database% -f 65001 -y 0 -i %TheSQLCMDFileToExecute%

if ERRORLEVEL 1 (

 echo An error running the script %TheSQLCMDFileToExecute% on %TheServer% occurred

 goto bombsite)

goto end

:bombsite

Echo We bombed!

color 0C

ENDLOCAL

Exit /b 1

:end

Echo Yes! We got here at last!!

ENDLOCAL

Exit /b 0


Как только сценарий становится подобным этому, он запускается последовательно. Он работает быстро, и объем кода кажется меньше, чем в PowerShell. Однако, для большинства целей лучше придерживаться PowerShell. Обратите внимание, что командлет Invoke-SQLCMD не реализует команду: OUT SQLCMD, поэтому вы застряли бы при выполнении команды SQLCMD.exe.

No Comments

Add a Comment