2009-11-26 2 views
7

Я работаю над приложением, где мне нужно получить ответ SQL как XML в XML-файл (и сохранить его в некотором физическом месте, скажем c: \ xyz.xml) ,Создание файла XML из SQL Server 2008

Я могу сгенерировать XML-контент, используя положения, доступные на SQL Server, как показано ниже.

SELECT * FROM @Table FOR XML AUTO, ELEMENTS 

где: @Table переменная таблицы.

Я хочу знать, как я могу хранить вывод запроса в XML-файл с самого SQL Server.

ответ

0

Если нажать

ctrl + shift + f 

вы выбрали "Результаты в файл." Это можно найти в меню Query на верхней панели Sql Management Studio.

Или поставить что-то вроде этого в вашем SQL скрипт

exec xp_cmdshell 'bcp "select * from suppliers" queryout "c:\suppliers.txt" -S server -T' 

Смотрите this link, есть вопрос о том, является ли это для приложения с диска или с приводом SQL-сервера. Получайте удовольствие, сортируя это.

0

Вы можете создать функцию CLR, которые создают файл, построить его на сервер SQL, и использовать его в хранимой процедуре

Другой способ (я не проверял) - Существует инструмент BCP

bcp "Select * from dbo..table FOR XML RAW" queryout c:\temp\test.xml -Soc-db -Uuser -Ppassword 

Этот пример из here

5

Вам нужно использовать xp_cmdshell, и bcp utility следующим образом

EXEC xp_cmdshell 'bcp "SELECT * FROM @Table FOR XML AUTO, ELEMENTS" queryout "C:\table.xml" -c -T' 

Убейте меня в комментариях, если у вас есть вопросы или вы хотите узнать больше о том, как это работает.

+0

Вам нужно указать каталог и схему таблицы, хотя (т.е. @Table должен иметь формат [база] .dbo. [Таблица]) – Gausie

4

Вы не можете писать в файловую систему с самого SQL Server. По крайней мере, не так легко. Существует три альтернативы:

  • xp_cmdshell. Я бы настоятельно советовал ему. По умолчанию xp_cmdshell is disabled в целях безопасности, и чтобы он включал его только для этой операции, открывает путь к большому отверстию безопасности в вашей системе.

  • использовать FileSystemObject и процедуры автоматизации OLE sp_OACreate/sp_OAMethod. См. Reading and Writing Files in SQL Server using T-SQL. Это, хотя и незначительно лучше, чем опция xp_cmdshell, не дает намного лучшей истории безопасности. Единственная причина, почему лучше, чем xp_cmdshell, - это то, что гораздо менее известно хакерам. Но OLE Automation procedures option в SQL Server также отключен по умолчанию, и включение этого параметра предоставляет те же самые проблемы безопасности, что и у xp_cmdshell.

  • использовать процедуру CLR. Это была бы моя рекомендация. Создайте сборку с цифровой подписью, используйте подпись сборки, чтобы разрешить через подписание кода Transact-SQL EXTERNAL ACCESS, а затем использовать процедуру CLR для записи XML в файловую систему.Хотя это значительно сложнее, чем простые параметры xp_cmdshell или OLE Automation, он является наиболее управляемым и гранулированным с точки зрения безопасности и является самым легким в обслуживании и правильном (это код .Net, а не сценарии оболочки). К сожалению, по умолчанию clr option также отключен на сервере и должен быть включен.

8

Есть еще один вариант - используйте sqlcmd tool.

  1. Добавить :XML ON в качестве первой строки в файле SQL (назовем его input.sql)
  2. команда, как это будет делать трюк:
sqlcmd -S <your-server> -i input.sql -o output.xml 
+0

Спасибо, это работало отлично для того, что мне было нужно. – Mark

0

Простой метод SQL Write to File

DECLARE @xml XML = '<MyXML></MyXMl>' 
DECLARE @strXML varchar(max) = convert(varchar(max),@XML) 

-- Add white space for readability 
SELECT @strxml = replace(@strxml,'</',char(13) + char(10) + '</') 
--- Add Declartives, namespaces and xls 

Create Table dbo.BCP_OUT(contents varchar(max)) 
INSERT INTO dbo.bcp_out(contents) 
SELECT Convert(varchar(max),@strXML) 

EXEC xp_cmdshell N'BCP -S SERVER [database].dbo.bcp_out -T -c -o \\pathto\file.name' 
0

Если ваш вывод XML является относительно небольшим (< 4000 символов), то вы можете использовать этот SP:

IF EXISTS (SELECT TOP 1 1 FROM sys.objects WHERE object_id = OBJECT_ID('dbo.USP_WRITE_UNICODE_STRING_TO_FILE') AND type = 'P') 
BEGIN 
    DROP PROCEDURE dbo.USP_WRITE_UNICODE_STRING_TO_FILE 
END 
GO 

-- ============================================= 
-- Description: Writes the specified Unicode string to the specified file. 
-- Permissions: This stored procedure uses xp_cmdshell which is disabled by default. To enable it: 
--    1. In Management Studio connect to a component of SQL Server. 
--    2. In Object Explorer, right-click the server, and then click Facets. 
--    3. In the View Facets dialog box, expand the Facet list, and select the Surface Area Configuration. 
--    4. In the Facet properties area, select XPCmdShellEnabled property and set its value to True. 
--    5. Click OK. 
-- Example:  EXEC dbo.USP_WRITE_UNICODE_STRING_TO_FILE'<root> <a b="c" /> </root>', 'C:\Test.xml', 1; 
-- ============================================= 
CREATE PROCEDURE dbo.USP_WRITE_UNICODE_STRING_TO_FILE 
(
    @Str   NVARCHAR(4000), 
    @XmlFilePath NVARCHAR(256), 
    @Debug   BIT = 0 
) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @Str1 NVARCHAR(MAX), 
      @Cmd NVARCHAR(4000), 
      @MaxLen int = 4000; 

    --see: http://technet.microsoft.com/en-us/library/bb490897.aspx 
    SET @Str1 = REPLACE(REPLACE(REPLACE(@Str, '>', '^>'), '<', '^<'), '"', '^"'); 
    -- '>' Writes the command output to a file 
    SET @Str1 =N'ECHO ' + @Str1 + N'>"'+ @XmlFilePath + N'"'; 
    IF @Debug = 1 
    BEGIN 
     DECLARE @Msg varchar(128) = 'The total lenght is ' + CAST(LEN(@Str1) AS VARCHAR(10)) + ' characters.' 
     PRINT @Msg; 
     PRINT @Str1; 
    END 

    IF (LEN(@Str1) > @MaxLen) 
     RAISERROR ('The input string is too long', 11, 0); 
    ELSE 
     SET @Cmd = CAST (@Str1 AS NVARCHAR(4000)); 

    EXEC master..xp_cmdshell @Cmd, NO_OUTPUT;   
END 
GO 

--Test 1 
DECLARE @Str NVARCHAR(4000); 
DECLARE @Xml xml = '<root> <a b="c" /> </root>'; 
SET @Str = CAST (@Xml AS NVARCHAR(4000)); 
EXEC dbo.USP_WRITE_UNICODE_STRING_TO_FILE @Str, 'C:\Test.xml', 1; 
GO 
--Test 2 
DECLARE @Str NVARCHAR(4000); 
SET @Str = REPLICATE('a', 4000); 
EXEC dbo.USP_WRITE_UNICODE_STRING_TO_FILE @Str, 'C:\Test.xml', 1; 
GO 

Если вы не работаете с Unicode, то вы можете создать еще один SP: USP_WRITE_NON_UNICODE_STRING_TO_FILE, который будет очень похож на предыдущий со следующими изменениями:

CREATE PROCEDURE dbo.USP_WRITE_NON_UNICODE_STRING_TO_FILE 
    (
     @Str   VARCHAR(8000), 
     @XmlFilePath NVARCHAR(256), 
     @Debug   BIT = 0 
    ) 
    AS 
    BEGIN 
     SET NOCOUNT ON; 

     DECLARE @Str1 VARCHAR(MAX), 
       @Cmd VARCHAR(8000), 
       @MaxLen int = 8000; 
     ... 
     SET @Cmd = CAST (@Str1 AS VARCHAR(8000)); 

Это SP позволяет использовать два раза дольше входной строки (< 8000 символов).

Если ваш XML длиннее 8000, но менее 1 МБ, вы можете использовать sqlcmd utility без команды XML ON. Это значительно упрощает использование утилиты, потому что вам не нужен отдельный файл input_file с включенной командой XML ON. Вот пример:

DECLARE @Cmd NVARCHAR(4000); 
SET @Cmd = N'sqlcmd -S ' + @@SERVERNAME + N' -d ' + DB_NAME() + 
N' -Q "SET NOCOUNT ON; DECLARE @Xml xml = ''<root> <a >b</a> </root>''; SELECT CONVERT(NVARCHAR(MAX), @Xml);" -o "C:\Test.xml" -y 0'; 
PRINT @Cmd; 
EXEC master..xp_cmdshell @Cmd, NO_OUTPUT; 

Вы также можете использовать SP здесь:

CREATE PROCEDURE dbo.USP_SAMPLE_PROCEDURE 
AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @Xml xml; 
    SET @Xml = (SELECT name, type_desc FROM sys.objects FOR XML PATH('object'), ROOT('sys.objects')); 
    SELECT CONVERT(NVARCHAR(MAX), @Xml) 
END 
GO 

DECLARE @Cmd NVARCHAR(4000); 
SET @Cmd = N'sqlcmd -S ' + @@SERVERNAME + N' -d ' + DB_NAME() + 
N' -Q "EXEC dbo.USP_SAMPLE_PROCEDURE;" -o "C:\Test.xml" -y 0'; 
PRINT @Cmd; 
EXEC master..xp_cmdshell @Cmd, NO_OUTPUT; 
GO 

Если ваш XML является более 1Мб, вы должны использовать: XML ON команды в отдельном сценарии и указать его в качестве - i input_file.

0

Я сделал этот SP, поэтому я могу легко извлечь данные из таблицы db или temp в файл XML в файловой системе. Он поддерживает предложение where.

CREATE PROCEDURE dbo.ExportToXMLFile 
     @TableName varchar(1000) 
    , @Where varchar(2000)='' 
    , @TicketNumber varchar(500) 
    , @debug bit=0 
as 
/* 
    Date:2016-03-27 
    Author: BojNed 
    Purpose: Exports data from table to XML file on filesystem. 
    @TableName = name of table to export. 
    @Where = optitional, to set @Where Clause. DO NOT ENTER WHERE at beggining of the string 
    @TicketNumber = To save to folder on filesystem 
    @Debug = Optitional. To debug this SP. 

    Examples: 
    EXEC dbo.ExportToXMLFile '#tt','columnX=2','221',0 
    EXEC dbo.ExportToXMLFile '[Production].[Product]','','252',1 
    EXEC dbo.ExportToXMLFile '[dbo].[DatabaseLog]','ColumnZ=55','351',0 
    EXEC dbo.ExportToXMLFile '[dbo].[DatabaseLog]','','7865',1 
*/ 
begin 

    if @debug=0 
     SET NOCOUNT ON 

    declare @SQL nvarchar(max) 
    declare @IsTempTable bit 
    declare @NewTableName varchar(1000) 
    declare @Xml as XML 

    if (isnull(@TicketNumber,''))='' 
    begin 
     RAISERROR('No ticket number defined',16,1,1) 
     RETURN 
    END 

    --check if table is tmp or variable 
    if (SELECT SUBSTRING(@TableName,1,1))='#' or (SELECT SUBSTRING(@TableName,1,1))='@' 
    BEGIN 
     if @debug=1 
      PRINT 'Source is TMP table' 
     set @NewTableName='TMPTBL_'[email protected] 
    END 
    ELSE 
    BEGIN 
     if @debug=1 
      PRINT 'Source is db table' 
     set @NewTableName=replace(@TableName,'.','_') 
    END 

     --RemoveSpecialChars 
     declare @KeepValues varchar(1000) 
     set @KeepValues = '%[^a-z^0-9^_]%' 
     WHILE PATINDEX(@KeepValues,@NewTableName)>0 
     set @NewTableName = STUFF(@NewTableName, PATINDEX(@KeepValues,@NewTableName),1,'') 

    if @debug=1 
     PRINT 'Node name for XML Header and filename: '[email protected] 

    if ISNULL(@Where,'')='' 
    BEGIN 
     set @SQL= 'SELECT * FROM '+ @TableName+' FOR XML PATH, ROOT ('''[email protected]+'''), ELEMENTS' 
     if @debug=1 
      PRINT 'NO Where condition' 
    END 
    ELSE 
    BEGIN 
     set @SQL= 'SELECT * FROM '+ @TableName+' WHERE '[email protected]+ ' FOR XML PATH, ROOT ('''[email protected]+'''), ELEMENTS' 
     if @debug=1 
      PRINT 'With Where condition' 
    END 

    --Get XML to tbl 
    if ISNULL(OBJECT_ID ('tempdb..##TXML'),0)>0 
    DROP TABLE ##TXML 

    CREATE TABLE ##TXML (XMLText XML) 

    set @SQL = ' insert into ##TXML select ('[email protected]+')' 

    --parse query 
    declare @testsql nvarchar(max) 
    declare @result int 
    set @testsql = N'set parseonly on; ' + @sql 
    exec @result = sp_executesql @testsql 

    -- If it worked, execute it 
    if @result = 0 
     begin 
      if @debug=1 
       PRINT 'Query OK: '+ @SQL 
      exec sp_executesql @sql 
     end 
    else 
    BEGIN 
     DECLARE @msg varchar(2000) 
     set @msg ='Parsing Error on query: ' + @SQL 
     RAISERROR (@msg,16,1,1) 
     RETURN 
    END 

    DECLARE @Tbl TABLE (id int identity(1,1), Dir varchar(256)) 

    --check if dir exsists 
    INSERT into @Tbl 
    EXEC master.dbo.xp_subdirs 'C:\DataCorrectionBackup\' 


    if (SELECT Count(*) from @Tbl WHERE [email protected])=0 
    BEGIN 
     --create new dir 
     DECLARE @t varchar(500) 
     set @t ='C:\DataCorrectionBackup\'[email protected] 

     EXEC master.sys.xp_create_subdir @t 
    END 

    declare @bcp varchar(500) 
    declare @Filename VARCHAR(255) 

    set @Filename =convert(varchar(100),GETDATE(),112)+'_'+replace(convert(varchar(100),GETDATE(),114),':','')+'_'[email protected]+'.xml' 

    set @bcp = 'bcp "SELECT XMLText from ##TXML" queryout C:\DataCorrectionBackup\'[email protected]+'\'[email protected]+' -w -T -S'+ @@servername 

    --save file 
    if @debug=0 
     EXEC xp_cmdshell @bcp, NO_OUTPUT 
    ELSE 
    BEGIN 
     EXEC xp_cmdshell @bcp 
     PRINT @bcp 
    END 

    DROP table ##TXML 

end 

go 
Смежные вопросы