QUESTION: How to create a sequence between multiple functions?
I have various functions which create xml data and each function can create multiple sets of "Party" nodes. All of the functions start of with the same parent node. I want the output to look like the following where each party regardless of what function it comes from has the continuing sequence number. DESIRED OUTPUT:
<PARTIES>
<PARTY SequenceNumber="1" label="PARTY_1">
...
<PARTY SequenceNumber="2" label="PARTY_2">
...
<PARTY SequenceNumber="3" label="PARTY_3">
...
</PARTIES>
Right now I am outputting my xml through a function that returns xml, and the functions I want to sequence are grouped together under PARTIES node:
SELECT [dbo].[GetFunction1Xml](@Id),
[dbo].[GetFunction2Xml](@Id),
[dbo].[GetFunction3Xml](@Id)
FOR XML PATH(''), ROOT('PARTIES'), TYPE
Each function collects information from different places and could look like this:
ALTER GetFunction1XML
...
RETURNS XML (
SELECT [label] = 'PARTY_' + CONVERT(NVARCHAR,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)))
[Var1] = ....,
[Var2] = ....,
FROM [Table]
FOR XML PATH('PARTY'), TYPE)
END;
I attempted to use a Sequence however it is not allowed in user-defined functions.
CREATE SEQUENCE Party_Seq
AS INTEGER
START WITH 1
INCREMENT BY 1
MINVALUE 1
NO CYCLE;
I also attempted the following inside each function since it works if I were to have two parties in the same function connected by a UNION ALL. However it restarts to PARTY_1 everytime since all the parties are in different functions.
SELECT [@label] = 'PARTY_' + CONVERT(NVARCHAR,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)))
So for example if i were to replace 2 functions with 1 generic one it would look like this and it print out the information correctly; however I have way too many functions to do this.
ALTER GetGenericFunctionXML
...
RETURNS XML (
SELECT [@seq] = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
[@label] = 'PARTY_' + CONVERT(NVARCHAR,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)))
[Var1] = [food].[fruit],
[Var2] = [food].[meat]
FROM ( SELECT 'Apple' AS [fruit],
'Bacon' AS [meat]
FROM [Table1]
UNION ALL
SELECT 'Grape',
'Pork'
FROM [Table2]
) AS [food]
FOR XML PATH('PARTY'), TYPE)
END;
Output:
<PARTIES>
<PARTY SequenceNumber="1" label="PARTY_1">
<Var1>Apple</Var1>
<Var2>Bacon</Var2>
<PARTY SequenceNumber="2" label="PARTY_2">
<Var1>Grape</Var1>
<Var2>Pork</Var2>
<PARTY SequenceNumber="3" label="PARTY_3">
</PARTIES>
I also tried passing a parameter to the functions but since they are functions they can't output the value (I believe only stored procedures can do this. Correct me if I'm wrong.).
AS BEGIN...END), but a scalar function returning one single XML should be OK. One most be aware, that the calls are not fully inlined and therefore the optimizer might not find the best execution plan. This depends on the kind of data you are pulling for your XML...