Можно ли заставить SQL Server войти в SFTP и загрузить файл просто с помощью команд T-SQL, без SSIS? - PullRequest
4 голосов
/ 24 октября 2019

У меня есть пакет служб SSIS, который регистрируется на SFTP-сайте моего клиента и загружает файл с помощью команд, отправляемых в WinSCP.

Этот пакет часто выходит из строя и с ним трудно работать. Visual Studio дает сбой настолько часто, что моя команда отказывается использовать его больше. Мы переносим все автоматизированные задачи на хранимые процедуры и задания агента SQL, поскольку они работают намного лучше, чем SSIS.

Однако это не дает нам хорошего решения для автоматизации выгрузки файлов отчетов по FTP, созданных на SQL Server. ,

Я делал это, используя PSFTP и командные файлы, вызываемые из сценариев VB. Сценарий проверяет определенную папку, чтобы увидеть, есть ли файл, и загружает его, если он есть. Это работает, но не элегантно, и мне нужно планировать эти сценарии для поиска файла в папке каждые 15 минут, а не просто вызывать команду «upload» из моей хранимой процедуры на SQL Server. Существует вероятность того, что что-то пойдет не так, если кто-то переименует файл в этой папке или поместит туда два файла и т. Д.

Я могу легко создать файл .CSV как часть хранимой процедуры в определенной папке. используя BCP, например:

--Create Client Update .CSV File if there are any rows in the CLIENT_UPDATE table
IF EXISTS(SELECT 1 FROM CLIENT_UPDATE)
BEGIN
DECLARE @ColumnHeader VARCHAR(8000)
    SET @FileName = @DataPath + '\Output File.csv'
 SELECT @ColumnHeader = COALESCE(@ColumnHeader+',' ,'')+''''+column_name+'''' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='CLIENT_UPDATE'
    SET @BCPCommand = 'bcp "SELECT '+ @ColumnHeader +' UNION ALL SELECT * FROM CLIENT_UPDATE" queryout "' + @FileName + '" -c -t , -r \n  -S . -T'
   EXEC master..xp_cmdshell @bcpCommand
END

Я бы хотел, чтобы следующим шагом в этой хранимой процедуре было «Загрузка файла .CSV на клиентский SFTP-сайт». Как мне это сделать?

1 Ответ

1 голос
/ 29 октября 2019

Успех!

Я создал сохраненный процесс в моей базе данных с именем sp_UploadFileToSFTP , который использует PSFTP.EXE для отправки файлов.

-- ================================================================================================================================
-- Description: Upload File to SFTP
--              - Creates "SFTPUploadScript.bat" and "SFTPUploadScript.txt" scripting files to control psftp.exe, then executes the batch file
--              - Requires a local @ScriptFolder on the SQL Server to create files inside, and which contains psftp.exe
--              - "SFTPUploadScript.bat" needs to be run once manually from the SQL Server desktop to capture the keypair of the SFTP site
--                After this, the script will work automatically
-- ================================================================================================================================
CREATE PROCEDURE sp_UploadFileToSFTP 

    @FilePathToUpload varchar(1000),
    @SFTPSiteAddress varchar(1000),
    @SFTPLogin varchar(1000),
    @SFTPPassword varchar(1000),
    @SFTPRemoteFolder varchar(1000)

AS
BEGIN
SET NOCOUNT ON;

--Declare Variables
 DECLARE @ScriptFolder varchar(1000)
     SET @ScriptFolder = 'C:\SFTPBatchFiles\'
 DECLARE @CommandString AS varchar(8000)

--Delete Existing files if they exist
     SET @CommandString = 'del "'+ @ScriptFolder + 'SFTPUploadScript.txt"'
    EXEC master..xp_cmdshell @CommandString
     SET @CommandString = 'del "'+ @ScriptFolder + 'SFTPUploadScript.bat"'
    EXEC master..xp_cmdshell @CommandString

--Create Batch fle with login credentials
     SET @CommandString = 'echo "'+ @ScriptFolder +'psftp.exe" ' + @SFTPSiteAddress + ' -l ' + @SFTPLogin + ' -pw ' + @SFTPPassword + ' -b "' + @ScriptFolder + 'SFTPUploadScript.txt" > "' + @ScriptFolder + 'SFTPUploadScript.bat"'
    EXEC master..xp_cmdshell @CommandString

--Create SFTP upload script file
     SET @CommandString = 'echo cd "' + @SFTPRemoteFolder + '" > "' + @ScriptFolder + 'SFTPUploadScript.txt"'
    EXEC master..xp_cmdshell @CommandString
     SET @CommandString = 'echo put "' + @FilePathToUpload + '" >> "' + @ScriptFolder + 'SFTPUploadScript.txt"'
    EXEC master..xp_cmdshell @CommandString

--Run the Batch File
     SET @CommandString = @ScriptFolder + 'SFTPUploadScript.bat'
    EXEC master..xp_cmdshell @CommandString

END
GO

Затем я могу позвонитьэто изнутри другого хранимого процесса, например:

sp_UploadFileToSFTP 'C:\FileToUpload\Test.txt','sftp.mysite.com','Login@domain.com','Password1234','UploadFolder/In here/'

Все работает отлично, для запуска требуется около четверти секунды, очень аккуратное и стабильное решение.

По сравнению с тем, что я делал до этого, когда SQL Server перетаскивал файл в папку, а затем проверял эту папку на наличие новых файлов каждые 15 минут с помощью сценария загрузки Visual Basic SFTP, это намного лучше:)

Если вы хотите попробовать это сами, все, что вам нужно, - это папка на диске C: \ вашего SQL Server с именем «SFTPBatchFiles», и вы помещаете туда psftp.exe, который является частью PuTTY.

Вам также понадобится доверенный администратор сервера, который позволит вам запускать команды psftp и ваши собственные пакетные файлы с помощью xp_cmdshell, и им, вероятно, потребуется открыть маршрут в брандмауэре, чтобы вы могли подключиться к удаленному сайту. прямо с SQL Server.

Наконец, вам также понадобится иметь возможность удаленного рабочего стола на вашем SQL Server, так как вам нужно будет запустить пакетный файл, который он создает вручную, один раз и нажать «Y», когда psftp попросит вас принять новыйпара ключей. После этого все просто.

Нет служб SSIS, нет WINSCP, нет Visual Studio, нет многочасовых сбоев и отладки!

Единственная проблема сейчас заключается в том, что если передача по FTP по какой-либо причине завершается неудачно, хранимая процедуравсе еще сообщает об успехе, я не возвращаю сообщения об ошибках psftp обратно в SQL Server.

Моя следующая задача - перехватывать сообщения о состоянии и ошибках, которые генерируются из xp_cmdshell, и давать пользователю некоторые подробные отзывы игенерировать ошибки в случае сбоя процесса.

ОБНОВЛЕНИЕ:

Ошибки перехвата и обратная связь с удаленного FTP-сайта

--Run the Batch File
  DROP TABLE IF EXISTS #CommandOutput
CREATE TABLE #CommandOutput (ReadLine varchar(1000))
         SET @CommandString = @ScriptFolder + 'SFTPUploadScript.bat'
      INSERT #CommandOutput
        EXEC master..xp_cmdshell @CommandString

--Check for Invalid Password error  
IF EXISTS (SELECT ReadLine 
            FROM #CommandOutput 
           WHERE ReadLine LIKE '%Invalid Password%')
    BEGIN
          PRINT 'Invalid Password Error!'
      END

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

После запуска пакетного файла вы можете затемзапрос #CommandOutput, чтобы увидеть, что случилось с вашим переводом.

Я добавил простую проверку слов "Неверный пароль" в любом случаее в выводе, так как это типичная ошибка, которая может у вас возникнуть. Вы можете добавить столько проверок, сколько захотите, или импортировать всю таблицу в электронное письмо, которое будет отправляться вам при каждом запуске задания, вносить таблицу в таблицу регистрации событий FTP или в любое другое число.

...