从SQL Server 2008生成XML文件

时间:2022-07-10 23:48:22

I am working on an application where I need to get the SQL response as XML into an XML file (and to store it in some physical location, say c:\xyz.xml).

我正在开发一个应用程序,我需要将SQL响应作为XML获取到XML文件中(并将其存储在某个物理位置,例如c:\ xyz.xml)。

I am able to generate the XML content using the provisions available in SQL Server as shown below.

我可以使用SQL Server中提供的规定生成XML内容,如下所示。

 SELECT * FROM @Table FOR XML AUTO, ELEMENTS

where: @Table is a table variable.

其中:@Table是一个表变量。

I want to know how I can store the query output to an XML file from SQL Server itself.

我想知道如何将查询输出存储到SQL Server本身的XML文件中。

8 个解决方案

#1


8  

There's one more option - use sqlcmd tool.

还有一个选项 - 使用sqlcmd工具。

  1. Add :XML ON as a first line in your SQL file (let's call it input.sql)
  2. 添加:XML ON作为SQL文件的第一行(我们称之为input.sql)
  3. A command like this will do the trick:
  4. 这样的命令可以解决这个问题:
sqlcmd -S <your-server> -i input.sql -o output.xml

#2


5  

You need to use xp_cmdshell, and the bcp utility in the following way

您需要以下列方式使用xp_cmdshell和bcp实用程序

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

Hit me back in the comments if you've got any questions or want to know anything more about how this works.

如果您有任何问题或希望了解更多有关其工作原理的信息,请在评论中回复我。

#3


5  

You can't write to the file system from SQL Server itself. At least not that easily. There are three alternatives:

您无法从SQL Server本身写入文件系统。至少不那么容易。有三种选择:

  • use xp_cmdshell. I would strongly advise against it. By default xp_cmdshell is disabled for security purposes, and to have it enabled it just for this operation opens a way to big security hole in your system.

    使用xp_cmdshell。我强烈建议不要这样做。默认情况下,xp_cmdshell被禁用用于安全目的,并且仅为此操作启用它会打开一种方法来解决系统中的大安全漏洞。

  • use the FileSystemObject and the OLE Automation procedures sp_OACreate/sp_OAMethod. See Reading and Writing Files in SQL Server using T-SQL. This, while marginally better than the xp_cmdshell option, it doesn't give a much better security story. The only reason why is better than xp_cmdshell is that is by far less known by hackers. But the OLE Automation procedures option in SQL Server is also disabled by default and enabling this option exposes the very same security problems xp_cmdshell has.

    使用FileSystemObject和OLE自动化过程sp_OACreate / sp_OAMethod。请参阅使用T-SQL在SQL Server中读取和写入文件。这虽然略微优于xp_cmdshell选项,但它没有提供更好的安全性故事。唯一的原因是比xp_cmdshell更好的是黑客知道的更少。但是,默认情况下也禁用SQL Server中的OLE自动化过程选项,并且启用此选项会暴露xp_cmdshell具有的相同安全问题。

  • use a CLR procedure. This would be my recommendation. Create an assembly with digital signature, use the assembly signature to allow, through Transact-SQL code signing, EXTERNAL ACCESS, then use the CLR procedure to write the XML into the file system. While this is significantly more complex than the simple xp_cmdshell or OLE Automation options, it is the most controlable and granular one from a security point of view and is the easiest to maintain and get right (is .Net code as opposed to shell scripts). Unfortunately, by default the clr option is also disabled in the server and has to be enabled.

    使用CLR程序。这是我的建议。使用数字签名创建程序集,使用程序集签名允许通过Transact-SQL代码签名,EXTERNAL ACCESS,然后使用CLR过程将XML写入文件系统。虽然这比简单的xp_cmdshell或OLE自动化选项复杂得多,但从安全的角度来看,它是最容易控制和最精细的,并且最容易维护和正确(是.Net代码而不是shell脚本)。不幸的是,默认情况下,clr选项也在服务器中禁用,必须启用。

#4


0  

If you press

如果按

ctrl + shift + f

you will have selected "Results To File." This can be found in the Query menu on the top bar of Sql Management Studio.

您将选择“结果存档”。这可以在Sql Management Studio顶部栏的“查询”菜单中找到。

Or put something like this into your sql script

或者把这样的东西放到你的sql脚本中

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

See this link, there is an issue about whether it is the app's c drive or the sql server's c drive. Have fun sorting that out.

看到此链接,有一个问题是它是应用程序的c驱动器还是sql server的c驱动器。有趣的排序。

#5


0  

You can create CLR function that create the file, build it into the sql server, and use it from a stored procedure

您可以创建CLR函数来创建文件,将其构建到sql server中,并从存储过程中使用它

Another way( I haven't tested it ) - There is a tool bcp

另一种方式(我还没有测试过) - 有一个工具bcp

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

This example is from here

这个例子来自这里

#6


0  

Simple SQL Write to File method

简单的SQL写入文件方法

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' 

#7


0  

If your xml output is relatively small (<4000 characters), then you can use this SP:

如果您的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

If you don't work with Unicode, then you can create another SP: USP_WRITE_NON_UNICODE_STRING_TO_FILE, which will be very similar to the previous one with the following changes:

如果您不使用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));

That SP allows the use of two times longer the input string (<8000 characters).

该SP允许使用两倍长的输入字符串(<8000个字符)。

If your XML is longer than 8000 but less than 1MB you can use sqlcmd utility without :XML ON command. It greatly simplify the usage of the utility because you don't need a separate input_file with :XML ON command included. Here is an example:

如果您的XML超过8000但小于1MB,则可以使用sqlcmd实用程序而不使用: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;

You can also use an SP here:

你也可以在这里使用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

If your XML is more than 1MB you should use :XML ON command in a separate script and specify it as -i input_file parameter.

如果XML大于1MB,则应在单独的脚本中使用:XML ON命令,并将其指定为-i input_file参数。

#8


0  

I made this SP so I can easily extract data from db or temp table to XML file on file system. It supports where clause.

我制作了这个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_'+@TableName
    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: '+@NewTableName

    if ISNULL(@Where,'')=''
    BEGIN
        set @SQL= 'SELECT * FROM '+ @TableName+' FOR XML PATH, ROOT ('''+@NewTableName+'''), ELEMENTS'
        if @debug=1
            PRINT 'NO Where condition'
    END
    ELSE
    BEGIN
        set @SQL= 'SELECT * FROM '+ @TableName+' WHERE '+@Where+ ' FOR XML PATH, ROOT ('''+@NewTableName+'''), 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 ('+@SQL+')'

    --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 Dir=@TicketNumber)=0
    BEGIN
        --create new dir
        DECLARE @t varchar(500)
        set @t ='C:\DataCorrectionBackup\'+@TicketNumber

        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),':','')+'_'+@NewTableName+'.xml'

    set @bcp = 'bcp "SELECT XMLText from ##TXML" queryout C:\DataCorrectionBackup\'+@TicketNumber+'\'+@Filename+' -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

#1


8  

There's one more option - use sqlcmd tool.

还有一个选项 - 使用sqlcmd工具。

  1. Add :XML ON as a first line in your SQL file (let's call it input.sql)
  2. 添加:XML ON作为SQL文件的第一行(我们称之为input.sql)
  3. A command like this will do the trick:
  4. 这样的命令可以解决这个问题:
sqlcmd -S <your-server> -i input.sql -o output.xml

#2


5  

You need to use xp_cmdshell, and the bcp utility in the following way

您需要以下列方式使用xp_cmdshell和bcp实用程序

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

Hit me back in the comments if you've got any questions or want to know anything more about how this works.

如果您有任何问题或希望了解更多有关其工作原理的信息,请在评论中回复我。

#3


5  

You can't write to the file system from SQL Server itself. At least not that easily. There are three alternatives:

您无法从SQL Server本身写入文件系统。至少不那么容易。有三种选择:

  • use xp_cmdshell. I would strongly advise against it. By default xp_cmdshell is disabled for security purposes, and to have it enabled it just for this operation opens a way to big security hole in your system.

    使用xp_cmdshell。我强烈建议不要这样做。默认情况下,xp_cmdshell被禁用用于安全目的,并且仅为此操作启用它会打开一种方法来解决系统中的大安全漏洞。

  • use the FileSystemObject and the OLE Automation procedures sp_OACreate/sp_OAMethod. See Reading and Writing Files in SQL Server using T-SQL. This, while marginally better than the xp_cmdshell option, it doesn't give a much better security story. The only reason why is better than xp_cmdshell is that is by far less known by hackers. But the OLE Automation procedures option in SQL Server is also disabled by default and enabling this option exposes the very same security problems xp_cmdshell has.

    使用FileSystemObject和OLE自动化过程sp_OACreate / sp_OAMethod。请参阅使用T-SQL在SQL Server中读取和写入文件。这虽然略微优于xp_cmdshell选项,但它没有提供更好的安全性故事。唯一的原因是比xp_cmdshell更好的是黑客知道的更少。但是,默认情况下也禁用SQL Server中的OLE自动化过程选项,并且启用此选项会暴露xp_cmdshell具有的相同安全问题。

  • use a CLR procedure. This would be my recommendation. Create an assembly with digital signature, use the assembly signature to allow, through Transact-SQL code signing, EXTERNAL ACCESS, then use the CLR procedure to write the XML into the file system. While this is significantly more complex than the simple xp_cmdshell or OLE Automation options, it is the most controlable and granular one from a security point of view and is the easiest to maintain and get right (is .Net code as opposed to shell scripts). Unfortunately, by default the clr option is also disabled in the server and has to be enabled.

    使用CLR程序。这是我的建议。使用数字签名创建程序集,使用程序集签名允许通过Transact-SQL代码签名,EXTERNAL ACCESS,然后使用CLR过程将XML写入文件系统。虽然这比简单的xp_cmdshell或OLE自动化选项复杂得多,但从安全的角度来看,它是最容易控制和最精细的,并且最容易维护和正确(是.Net代码而不是shell脚本)。不幸的是,默认情况下,clr选项也在服务器中禁用,必须启用。

#4


0  

If you press

如果按

ctrl + shift + f

you will have selected "Results To File." This can be found in the Query menu on the top bar of Sql Management Studio.

您将选择“结果存档”。这可以在Sql Management Studio顶部栏的“查询”菜单中找到。

Or put something like this into your sql script

或者把这样的东西放到你的sql脚本中

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

See this link, there is an issue about whether it is the app's c drive or the sql server's c drive. Have fun sorting that out.

看到此链接,有一个问题是它是应用程序的c驱动器还是sql server的c驱动器。有趣的排序。

#5


0  

You can create CLR function that create the file, build it into the sql server, and use it from a stored procedure

您可以创建CLR函数来创建文件,将其构建到sql server中,并从存储过程中使用它

Another way( I haven't tested it ) - There is a tool bcp

另一种方式(我还没有测试过) - 有一个工具bcp

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

This example is from here

这个例子来自这里

#6


0  

Simple SQL Write to File method

简单的SQL写入文件方法

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' 

#7


0  

If your xml output is relatively small (<4000 characters), then you can use this SP:

如果您的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

If you don't work with Unicode, then you can create another SP: USP_WRITE_NON_UNICODE_STRING_TO_FILE, which will be very similar to the previous one with the following changes:

如果您不使用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));

That SP allows the use of two times longer the input string (<8000 characters).

该SP允许使用两倍长的输入字符串(<8000个字符)。

If your XML is longer than 8000 but less than 1MB you can use sqlcmd utility without :XML ON command. It greatly simplify the usage of the utility because you don't need a separate input_file with :XML ON command included. Here is an example:

如果您的XML超过8000但小于1MB,则可以使用sqlcmd实用程序而不使用: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;

You can also use an SP here:

你也可以在这里使用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

If your XML is more than 1MB you should use :XML ON command in a separate script and specify it as -i input_file parameter.

如果XML大于1MB,则应在单独的脚本中使用:XML ON命令,并将其指定为-i input_file参数。

#8


0  

I made this SP so I can easily extract data from db or temp table to XML file on file system. It supports where clause.

我制作了这个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_'+@TableName
    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: '+@NewTableName

    if ISNULL(@Where,'')=''
    BEGIN
        set @SQL= 'SELECT * FROM '+ @TableName+' FOR XML PATH, ROOT ('''+@NewTableName+'''), ELEMENTS'
        if @debug=1
            PRINT 'NO Where condition'
    END
    ELSE
    BEGIN
        set @SQL= 'SELECT * FROM '+ @TableName+' WHERE '+@Where+ ' FOR XML PATH, ROOT ('''+@NewTableName+'''), 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 ('+@SQL+')'

    --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 Dir=@TicketNumber)=0
    BEGIN
        --create new dir
        DECLARE @t varchar(500)
        set @t ='C:\DataCorrectionBackup\'+@TicketNumber

        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),':','')+'_'+@NewTableName+'.xml'

    set @bcp = 'bcp "SELECT XMLText from ##TXML" queryout C:\DataCorrectionBackup\'+@TicketNumber+'\'+@Filename+' -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