我正在开发一个应用程序,我需要将SQL响应作为XML转换为XML文件(并将其存储在某个物理位置,例如 c:\ xyz.xml )。 / p>
我可以使用SQL Server中提供的规定生成XML内容,如下所示。
SELECT * FROM @Table FOR XML AUTO, ELEMENTS
其中:@Table
是表变量。
我想知道如何将查询输出存储到SQL Server本身的XML文件中。
答案 0 :(得分:8)
还有一个选项 - 使用sqlcmd tool。
:XML ON
添加为SQL文件的第一行(让我们称之为 input.sql )sqlcmd -S <your-server> -i input.sql -o output.xml
答案 1 :(得分:5)
您需要以下列方式使用xp_cmdshell和bcp utility
EXEC xp_cmdshell 'bcp "SELECT * FROM @Table FOR XML AUTO, ELEMENTS" queryout "C:\table.xml" -c -T'
如果您有任何问题或希望了解更多有关其工作原理的信息,请在评论中回复。
答案 2 :(得分:5)
您无法从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更好的是黑客知道这一点。但是默认情况下,SQL Server中的OLE Automation procedures option也被禁用,启用此选项会暴露xp_cmdshell所具有的相同安全问题。
使用CLR程序。这是我的建议。使用数字签名创建程序集,使用程序集签名允许通过Transact-SQL代码签名,EXTERNAL ACCESS,然后使用CLR过程将XML写入文件系统。虽然这比简单的xp_cmdshell或OLE自动化选项复杂得多,但从安全的角度来看,它是最容易控制和最精细的,并且最容易维护和正确(是.Net代码而不是shell脚本)。不幸的是,默认情况下,clr option也在服务器中禁用,必须启用。
答案 3 :(得分:0)
如果按
ctrl + shift + f
您将选择“结果存档”。这可以在Sql Management Studio顶部栏的“查询”菜单中找到。
或者把这样的东西放到你的sql脚本中
exec xp_cmdshell 'bcp "select * from suppliers" queryout "c:\suppliers.txt" -S server -T'
请参阅this link,是否有应用程序的c驱动器或sql server的c驱动器存在问题。尽情排序。
答案 4 :(得分:0)
您可以创建CLR函数来创建文件,将其构建到sql server中,并从存储过程中使用它
另一种方式(我还没有测试过) - 有一个工具bcp
bcp "Select * from dbo..table FOR XML RAW" queryout c:\temp\test.xml -Soc-db -Uuser -Ppassword
此示例来自here
答案 5 :(得分:0)
简单的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'
答案 6 :(得分: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但小于1MB,则可以使用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超过1MB,则应在单独的脚本中使用:XML ON命令,并将其指定为-i input_file参数。
答案 7 :(得分: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_'+@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