Динамически читать файлы в VS DBPro (используя SQLCMD)

Я использую VS2008 DBPro. В моем файле PostDeploy у меня есть много строк, как эта

:r .\Data\Test\Classifiers.CodeType.data.sql
:r .\Data\Test\Classifiers.Currency.data.sql
:r .\Data\Test\Classifiers.LOB.data.sql

Я хотел бы создать переменную ProjectName, чтобы можно было легко развертывать различные данные проекта. Как то так (не работает)

:setvar ProjectName "Test"

:r .\Data\$(ProjectName)\Classifiers.CodeType.data.sql
:r .\Data\$(ProjectName)\Classifiers.Currency.data.sql
:r .\Data\$(ProjectName)\Classifiers.LOB.data.sql

Было бы еще лучше, если бы я мог читать ВСЕ файлы в папке без указания пути к ней.

1 ответ

Я узнал, как это можно сделать.

Сначала вам нужно включить утилиту xp_cmdshell

RAISERROR ('Enabling xp_cmdshell utility...', 0, 1) WITH NOWAIT
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO

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

CREATE PROCEDURE [Builder].[RunScriptsInFolder]
    @scriptsDir varchar(255)
AS

IF len(@scriptsDir) = 0
    RETURN 0

DECLARE @Message VARCHAR(254)
SET @Message = 'Loading files in ' + @scriptsDir + ' directory...'
RAISERROR (@Message, 0, 1) WITH NOWAIT 

DECLARE @FileList Table (FileNumber int identity(1,1), FileName varchar(255), Command varchar(2048))
DECLARE @OutputTable Table (Output varchar(MAX))
DECLARE @FileName varchar(255)
DECLARE @Command varchar(2048) 
DECLARE @FileNum int
DECLARE @databaseName varchar(255)

SET @databaseName = db_name()

SET @Command = 'DIR /B /O:-N ' + @scriptsDir + '*.sql'
INSERT INTO @FileList (FileName) EXEC xp_cmdshell @Command 
UPDATE @FileList SET Command = 'sqlcmd -d ' + @databaseName + ' -i "' + @scriptsDir + FileName + '"'

WHILE EXISTS(SELECT * FROM @FileList)
BEGIN
    SELECT TOP(1) @FileNum = FileNumber, @FileName = FileName, @Command = Command FROM @FileList 

    SET @FileName = '  :r ' + @FileName
    RAISERROR (@FileName, 0, 1) WITH NOWAIT 
    EXEC xp_cmdshell @Command

    DELETE FROM @FileList WHERE FileNumber = @FileNum
END
RETURN 0;

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

RAISERROR ('Disabling all constraints...', 0, 1) WITH NOWAIT 
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

---- Run all files specified folder
BEGIN TRANSACTION
EXEC [Builder].[RunScriptsInFolder] '$(ProjectDir)Scripts\Post-Deployment\Data\'
COMMIT TRANSACTION

---- Enable all constraints
RAISERROR ('Re-enabling all constraints...', 0, 1) WITH NOWAIT 
exec sp_msforeachtable @command1="print '?'", @command2='ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'

Вы также можете спросить, почему переменная $(ProjectDir) не работает для вас. Чтобы включить его, откройте файл *.dbproj в текстовом редакторе и добавьте этот код в конце.

<PropertyGroup>
  <SetVariables>
    <Variable Name="ProjectDir" Value="$(ProjectDir)" />
  </SetVariables>
</PropertyGroup>

В качестве альтернативы вы можете открыть свойства вашего проекта БД, найти вкладку Variables и добавить переменную set ProjectDir=$(ProjectDir)

Другие вопросы по тегам