Home > Software engineering >  SQL XML output into file automatically
SQL XML output into file automatically

Time:06-14

I have the code below and works OK, generates the XML output in SQL Server Management Studio. How can i save the result into a file on the drive automatically in order to run every night?

Thank you in advance for your help.

DECLARE @Rechnungen TABLE (id int , Nummer nvarchar(20), Datum datetime);
INSERT INTO @Rechnungen (id, Nummer, Datum) VALUES 
(8, 'R200001', '2020-06-29');

DECLARE @Rechnungpos TABLE (id int, id_Rechnung int, Anzahl float);
INSERT INTO @RechnungPos (id, id_Rechnung, Anzahl) VALUES 
(1, 8, 3),
(5, 8, 1), 
(9, 8, 2);
-- DDL and sample data population, end

DECLARE @ID_Rechnung int = 8;

WITH XMLNAMESPACES ('urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2' as ext
    , 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' as cbc
    , 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' as cac
    , 'http://uri.etsi.org/01903/v1.3.2#' as xades
    , 'http://www.w3.org/2001/XMLSchema-instance' as xsi
    , 'http://www.w3.org/2000/09/xmldsig#' as ds)
SELECT (
SELECT '2.1'               AS [cbc:UBLVersionID],
    'TR1.2'                AS [cbc:CustomizationID],
    ''                     AS [cbc:ProfileID],
    p.Nummer               AS [cbc:ID],
    'false'                AS [cbc:CopyIndicator],
    ''                     AS [cbc:UUID],
    CAST(p.Datum AS Date)  AS [cbc:IssueDate],
    (
        SELECT c.id AS [cbc:ID]
            , CAST(c.Anzahl AS INT) AS [cbc:InvoicedQuantity] 
        FROM @Rechnungpos AS c INNER JOIN 
            @Rechnungen AS p ON p.id = c.id_Rechnung
        FOR XML PATH('r'), TYPE, ROOT('root')
    )
FROM @Rechnungen AS p
WHERE p.id = @ID_Rechnung
FOR XML PATH(''), TYPE, ROOT('Invoice')
).query('<Invoice xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
         xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
         xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
         xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<ext:UBLExtensions>
    <ext:UBLExtension>
        <ext:ExtensionContent/>
    </ext:UBLExtension>
</ext:UBLExtensions>
{
   for $x in /Invoice/*[local-name()!="root"]
   return $x,
     for $x in /Invoice/root/r
     return <cac:InvoiceLine>{$x/*}</cac:InvoiceLine>
}
</Invoice>');

CodePudding user response:

Please try the following solution based on bcp.

First, run it as-is to see how it is working.

Later on package your T-SQL in the question as a stored procedure.

And modify the following variable as follows:

@SQL VARCHAR(2048) = 'EXEC <your_stored_procedure_name>;'

SQL

/*
-T tells BCP to use Windows Authentication to connect to SQL Server. It will operate as the user who's running the command.
-U <login_id> -P <password> tells BCP to use SQL Server account while connecting to SQL Server.
*/
DECLARE @SQLCmd VARCHAR(8000)
   , @outputFileName VARCHAR(256) = 'e:\Temp\SampleXMLOutput.xml'
   , @bcp VARCHAR(256) = 'c:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\bcp.exe'
   , @SQL VARCHAR(2048) = 'SET NOCOUNT ON; SELECT TOP(1) TABLE_SCHEMA, TABLE_NAME FROM master.Information_Schema.Tables FOR XML PATH(''r''), TYPE, ROOT(''root'');'
   , @tcpPort VARCHAR(10) = '1433'
   , @WindowsAuth BIT = 1   -- 1 is for Windows Authentication, 0 is for SQL Server Authentication
   , @loginID VARCHAR(100) = 'loginID'
   , @password VARCHAR(100) = 'password'
   , @serverName VARCHAR(100) = 'realServerName';

-- SQL Server 2016 onwards
--SET @SQLCmd = FORMATMESSAGE('START "" "%s" "%s" queryout "%s" -T -x -c -C 1252 -a 65535 -S "%s,%s"'
--            , @bcp
--            , @SQL
--            , @outputFileName
--            , @@SERVERNAME
--            , @tcpPort);

-- older versions of SQL Server
-- /B "WindowTitle" parameters produce output in the SSSMS !!!
SET @SQLCmd = 'START /B "WindowTitle" "'   @bcp   '"' 
              ' "'   @SQL   '"' 
              ' queryout "'   @outputFileName   '"'
            --  IIF(@WindowsAuth = 1, ' -T', ' -U '  @loginID   ' -P '   @password)
              CASE WHEN @WindowsAuth = 1 THEN ' -T'
               ELSE ' -U '  @loginID   ' -P '   @password
               END
              ' -x -c -C 1252 -a 32768'
              ' -S "'   @serverName   ','   @tcpPort   '"';

-- just to see it
SELECT @SQLCmd AS [Command to execute];

-- create file on the file system
EXECUTE master.sys.xp_cmdshell @SQLCmd;

CodePudding user response:

Or in Powershell like this

$t = invoke-sqlcmd "select * from sys.messages for xml path('row'), root('data')"
$sw = new-object system.io.streamwriter "c:\temp\foo.xml"
foreach($r in $t) { $sw.write($r[0]) }
$sw.close()
  • Related