Generate XML from SQL issue - sql-server

I need to generate XML in the following format :
I haven't gone too far with the xml part of the task as I encountered following situation, you can tell that this obviously was not my intention.
How can I handle this properly considering that BBAN and IBAN need to be inside AccountNoas well as that I want it formatted according to the first picture.
The complete query along with my fair attempt of generating xml looks like this:
DECLARE #AccountType NVARCHAR(3);
DECLARE #kodBanke NVARCHAR(3);
SET #AccountType = 'T';
SET #kodBanke = ( SELECT vrednost FROM dbini WHERE IDENT = 'KOD' AND SECTION = 'PP' );
WITH Ent_Posta
AS
(
SELECT e.naziv,p.posta,e.sifra
FROM entitet AS e
INNER JOIN poste AS p ON e.sifra = p.entitet
)
SELECT (
SELECT
[dbo].[brojracuna](#kodBanke,i.partija) AS 'BBAN',
[dbo].[GENERATEIBAN](i.partija) AS 'IBAN'
FOR XML PATH('AccountNo'), ELEMENTS, ROOT('Account')
),
#accountType AS 'AccountType',
(a.ime + ' ( ' + a.roditel + ' ) ' + a.prezime) AS 'Name',
a.embg AS 'UID',
CASE status
WHEN 2 THEN 'A'
WHEN 4 THEN 'B'
WHEN 8 THEN 'U'
END AS 'Status',
c.sifra AS 'Territory',
#kodBanke as 'ID_Bank',
REPLACE(CONVERT(VARCHAR(10), i.DOTVaRANJE, 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, i.DOTVaRANJE)), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(s, i.DOTVaRANJE)),2) AS OpeningDate,
REPLACE(CONVERT(VARCHAR(10),'2006.09.28 ', 120), '.', '') + '-' + RIGHT( '0' + CONVERT(VARCHAR(2), DATEPART(hh, '2006.09.28' )), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(mi, '2006.09.28 ')), 2) + '' + RIGHT('0' + CONVERT(VARCHAR(2),DATEPART(s,'2006.09.28 ')),2) AS ClosingDate
FROM adresar AS a
INNER JOIN istdden AS i
ON a.embg = i.embg
INNER JOIN Ent_Posta as c
ON a.postbroj = c.posta
FOR XML PATH ('Account'), ROOT('Accounts');
Upon removal of this part I get...
<Accounts>
<Account>
<BBAN>5710543102313248</BBAN>
<IBAN>BA39531231634039248</IBAN>
<AccountType>T</AccountType>
<Name>DARKO ( DRAGAN ) TESIC</Name>
<UID>0000005467234</UID>
<Status>A</Status>
<Territory>1</Territory>
<ID_Bank>571</ID_Bank>
<OpeningDate>20081205-000000</OpeningDate>
<ClosingDate>20060928-000000</ClosingDate>
</Account>
... but now AccountNO is missing.

Your question is not all clear, but - if I get this correctly - you are fighting with 1:1 values, but within some deeper nesting.
You can use an XPath-like expression within [] in connection with FOR XML PATH. Check this out:
SELECT 'blah' AS FirstNode
,'blub' AS [SecondNode/OneDeeper]
,'blib' AS [SecondNode/OneMore]
,'ballaballa' AS [ThirdNode]
FOR XML PATH('row'),ROOT('root');
the resutl (look especially at <SecondNode>:
<root>
<row>
<FirstNode>blah</FirstNode>
<SecondNode>
<OneDeeper>blub</OneDeeper>
<OneMore>blib</OneMore>
</SecondNode>
<ThirdNode>ballaballa</ThirdNode>
</row>
</root>
If this is not what you need, please tag with the actual RDBMS (product and version) and please read How to ask a good SQL question and How to create a MCVE
For your issue it might be enough to use AS [AccountNo/IBAN] in your query.

Related

Split Delimited String into multiple Columns in SQL Server

I want to split a string in a column that is separated by space into multiple column is SQL.
I used the query below, but I get NULL values
select
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 1) AS Country_Code,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 2) AS iso_Code,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 3) AS status,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 5) AS date,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 6) AS rate,
PARSENAME(REPLACE(FX_RAW_DATA, ' ', '.'), 7) AS fx
FROM process.FX_RAW_DATA_OUT;
GO
You don't state what version of SQL Server you are running. If STRING_SPLIT is not available on your version, you can do as follows (I think you are trying to split column FX_RAW_DATA on table process). Basically, you apply the calculation of each space one after the other, then substring each:
SELECT
Country_Code = SUBSTRING(p.FX_RAW_DATA, 1, v1.chr - 1),
iso_Code = SUBSTRING(p.FX_RAW_DATA, v1.chr + 1, v2.chr - v1.chr - 1),
status = SUBSTRING(p.FX_RAW_DATA, v2.chr + 1, v3.chr - v2.chr - 1),
date = SUBSTRING(p.FX_RAW_DATA, v3.chr + 1, v4.chr - v3.chr - 1),
rate = SUBSTRING(p.FX_RAW_DATA, v4.chr + 1, v5.chr - v4.chr - 1),
fx = SUBSTRING(p.FX_RAW_DATA, v5.chr + 1, LEN(p.FX_RAW_DATA))
FROM process p
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA)) v1(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v1.chr + 1)) v2(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v2.chr + 1)) v3(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v3.chr + 1)) v4(chr)
CROSS APPLY (VALUES(CHARINDEX(' ', p.FX_RAW_DATA, v4.chr + 1)) v5(chr);
The first substring always starts at 1 and ends at the first break, the last substring you can just pass the full length to get the remainder of the string.
It's not very clear from your example sample data and expected results what your data looks like. I have made some assumptions and example below should be easy to change to match your data as required.
DECLARE #stringarray varchar(max), --String holding your data
#Splitcharc char(1), --split character, space in your example
#X xml
set #stringarray = '01AED AUD M 30122020 .3541000 11' --example data line
set #Splitcharc = '' -- this can be changed if needed
-- We start off by formatting your string into an XML format
set #X = CONVERT(xml,' <Table> <Row> <col>' +
REPLACE(#stringarray,#Splitcharc,'</col> <col>') + '</col></Row> </Table> ')
-- The below show how you "query" each of the "columns" returned
SELECT
Tbl.cl.value('col[1]','VARCHAR(20)') country_code,
Tbl.cl.value('col[2]','VARCHAR(20)') ISO_code,
Tbl.cl.value('col[3]','VARCHAR(20)') [status],
Tbl.cl.value('col[4]','VARCHAR(20)') [date],
Tbl.cl.value('col[5]','VARCHAR(20)') rate,
Tbl.cl.value('col[6]','VARCHAR(20)') fx
FROM #X.nodes('/Table/Row') as Tbl(cl)

Replace “<” and “>”and "<\" with “<” ,“>” and </ in sql server

I know that Replace < and > with < and > in sql server has been asked at
Replace “<” and “>” with “<” and “>” in sql server
but I need to expand upon it. I am trying to create formatted HTML code from a MS 2016 SQL server.
What I have is:
DECLARE #json nvarchar(max) = (SELECT DISTINCT AU2.PMID,
SUBSTRING(
(
SELECT ', '+ CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</' + AU1.Format + '>' ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM dbo.[Publication.PubMed.Author] AU1
WHERE AU1.PMID = AU2.PMID
ORDER BY AU1.PmPubsAuthorID
FOR XML PATH ('')
), 3, 1000) + '. Journal Name ' [Authors]
FROM dbo.[Publication.PubMed.Author] AU2
WHERE AU2.[PMID] =27702896 FOR JSON AUTO)
SELECT #json
And what I get back is:
Name DG, Name K, Name A, Chen FK, Song X, Pirun M, Santiago PM, Kim-Kiselak C, Platt JT, Lee E, Hodges E, <b>Rosebrock AP</b>, Bronson RT, Socci ND, Hannon GJ, Jacks T, Varmus H Journal Name
If I try to put TYPE into the
FOR XML PATH(''), TYPE
I get an error saying:
Argument data type xml is invalid for argument 1 of substring function.
I've tried to add REPLACE
replace(CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</b>' ELSE
AU1.LastName + ' ' + AU1.Initials END, '<', '<')
But then I get an error
The xml data type cannot be selected as DISTINCT because it is not comparable.
The best that I can come up with is:
SET #json = replace(#json, '<\', '<')
SET #json = replace(#json, '<', '<')
SET #json = replace(#json, '>', '>')
Just before the final SELECT #json.
I will have over a 1000 records that I need to pull. Do I need to do this is steps?
Based upon TT code I changed mine to
DECLARE #json nvarchar(max) = (SELECT DISTINCT AU2.PMID,
SUBSTRING(
(
SELECT ', '+ CASE WHEN AU1.Format IS Not Null Then +'<b>' +
AU1.LastName+ ' ' + AU1.Initials + '</b>' ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM dbo.[Publication.PubMed.Author] AU1
WHERE AU1.PMID = AU2.PMID
ORDER BY AU1.PmPubsAuthorID
FOR XML PATH (''),TYPE).value('.[1]','NVARCHAR(MAX)'
), 1, 1000) + '. Journal Name ' [Authors]
FROM dbo.[Publication.PubMed.Author] AU2
WHERE AU2.[PMID] =27702896 FOR JSON AUTO)
And that woks fine. but see comment below
As far as I can tell you are on the right track with FOR XML PATH(''), TYPE. It's just that you then have an XML text value which you need to convert to a string (i.e. of type [N]VARCHAR(X)). This can be done with the XML value() method.
An example (fiddle):
CREATE TABLE t(s NVARCHAR(16));
INSERT INTO t(s)VALUES(N'1'),(N'2'),(N'3'),(N'4'),(N'5'),(N'6');
SELECT
(
SELECT N'<b>'+s+N'</b>'
FROM t
FOR XML PATH(''),TYPE
).value('.[1]','NVARCHAR(MAX)');
results in
<b>1</b><b>2</b><b>3</b><b>4</b><b>5</b><b>6</b>

Need help adding WHERE clause in pre-written SQL statement

Preface: my SQL is rudimentary. I received a SQL query from a vendor, it selects and exports every single employee comment and other data from a few different DBs as CSV meant for import, it was written by them but they're not helping with this request. The query is pulling so much data it makes a large time consuming file for import. So I want to add to / modify the query to have a "WHERE date > whateverdate" to narrow my results to recent data. For example, I want to pull only comments entered in the past 2 days.
The column I'm looking to add the clause for is the column "A.CMS502", defined as datetime. I believe this is the only relevant column in this query. An example date in this column is "2003-10-06 17:05:21.000". I am using SQL Server 2008 if it helps. Is it possible here? Thank you.
SELECT
'ID,Acct/LnNbr,NoteCreatedDate,CollectorId,ApplytoAll,Note'
UNION ALL
SELECT
ID + ',' + ID + ',' + NoteCreatedDate + ',' + CollectorId + ',' + 'No' + ',' + Note
FROM
(SELECT
CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S'
THEN SUBSTRING(A.CMS301,1,LEN(A.CMS301) - 1)
ELSE A.CMS301
END + '-' +
CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S'
THEN 'S' ELSE 'L'
END AS [ID],
REPLACE(CONVERT(VARCHAR, A.CMS501, 10), '-', '') AS [NoteCreatedDate],
CASE WHEN U.CMS1201 IS NOT NULL
THEN U.CMS1205 + ' ' + U.CMS1204
ELSE (SELECT CMS1205 + ' ' + CMS1204 FROM sysUSER WHERE CMS1201 = 'PSUSER')
END AS CollectorId,
CAST(A.CMS512 AS NVARCHAR(MAX)) AS [Note]
FROM
ACTIVITY AS A
LEFT JOIN
sysUSER AS U ON A.CMS503 = U.CMS1201
WHERE
A.CMS504 NOT IN (411,500,511,711,804,900,901,903,907,2000,999777)
AND A.CMS504 NOT BETWEEN 1102 AND 1199) AS S
Try this, this will output last 2 days.
SELECT 'ID,Acct/LnNbr,NoteCreatedDate,CollectorId,ApplytoAll,Note'
UNION ALL
SELECT ID + ',' + ID + ',' + NoteCreatedDate + ',' + CollectorId + ',' + 'No' + ',' + Note
FROM
(
SELECT CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S' THEN SUBSTRING(A.CMS301,1,LEN(A.CMS301) - 1) ELSE A.CMS301 END
+ '-' + CASE WHEN SUBSTRING(A.CMS301,LEN(A.CMS301),1) = 'S' THEN 'S' ELSE 'L'
END AS [ID]
,REPLACE(CONVERT(varchar,A.CMS501,10),'-','') AS [NoteCreatedDate]
,CASE WHEN U.CMS1201 IS NOT NULL THEN U.CMS1205 + ' ' + U.CMS1204 ELSE
(SELECT CMS1205 + ' ' + CMS1204 FROM sysUSER WHERE CMS1201 = 'PSUSER')
END AS CollectorId
,CAST(A.CMS512 AS nvarchar(max)) AS [Note]
FROM ACTIVITY AS A
LEFT JOIN sysUSER AS U
ON A.CMS503 = U.CMS1201
WHERE A.CMS504 NOT IN (411,500,511,711,804,900,901,903,907,2000,999777)
AND A.CMS504 NOT BETWEEN 1102 AND 1199
AND A.CMS502 >= DATEADD(D, -2, GETDATE())
) AS S

SQL Server build dynamic sql

I have a temp table called #temp, and I need to get all the CDate column from that table, to build a string.
The CDate list in that table is (20171209, 20171210....20171223)
I expected to see
'A.[20171209] as [20171209], A.[20171210] as [20171210],
A.[20171211] as [20171211], A.[20171212] as [20171212],
A.[20171213] as [20171213], A.[20171214] as [20171214],
A.[20171215] as [20171215], A.[20171216] as [20171216],
A.[20171217] as [20171217], A.[20171218] as [20171218],
A.[20171219] as [20171219], A.[20171220] as [20171220],
A.[20171221] as [20171221], A.[20171222] as [20171222],
A.[20171223] as [20171223], '
however the result I got is missing the first date , ie 'A.[20171209] as [20171209]'
Here is my code:
SELECT
#col2 = ISNULL(#col2 + 'A.' + QUOTENAME(CDate) + ' as ' + QUOTENAME(CDate) + ', ' , '')
FROM
(SELECT DISTINCT CDate FROM #temp) AS tmp;
Your current approach will not work in some cases, it is an undocumented feature, always use For Xml path to concatenating the rows into csv.
SET #col2 = stuff((SELECT ', A.' + Quotename(CDate) + ' as '
+ Quotename(CDate)
FROM (SELECT DISTINCT CDate
FROM #temp) a
FOR xml path('')),1,1,'')

sql server query is not working in delphi [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
i have this code:
DECLARE #top VARCHAR(2000)
DECLARE #sql VARCHAR(4000)
SELECT #top =STUFF((SELECT DISTINCT
'],['+ ltrim([itemID])
FROM ARInvDet
ORDER BY '],['+ ltrim([itemID])
FOR XML PATH('')
), 1, 2, '')+']'
SET #sql ='
SELECT ItemID,Quantity,Price FROM(
select * From (
select
a.CustomerID as [CustomerID],
a.DateFinalize as [Date],
ad.Quantity as [Quantity],
ad.UnitPrice as [Price],
i.ItemTypeID as [ItemTypeID],
i.ItemID as [ItemID]
from ARInvDMS a
inner join ARInvDet ad on a.ARInvoiceID = ad.ARInvoiceID
inner join item i on ad.ItemID = i.ItemID
WHERE CustomerID = 10056 and a.[DateFinalize] = CONVERT(DATETIME,''2/28/2014'', 102)
and i.[ItemTypeID] = 1
) src
PIVOT
(
SUM(Quantity)
FOR [ItemID] in ('+#top+')
) as pvt
) as src2
UNPIVOT
(
Quantity FOR ItemID in ('+#top+')
) as unpvt
'
execute(#sql)
the error is Incorrect Syntax near '2': it from the WHERE statement.. but i tried to run this code in sql server 2008 r2..and its working fine.. but when i used this in my delphi program.. this error appears.. please help.
The problem is with the doubled quotes around the date.
If you run this query in SQL Server exactly as you show it here, it will choke on
''2/28/2014''
because it needs to be surrounded with single quotes.
'2/28/2014'
Now let's talk about how you're going to run this query from Delphi.
Are you putting this text into a query object at design time?
Or are you using it as a string constant within your program?
If you're just setting the SQL text at design time, you can enter the raw query directly as is, once you've corrected for the doubled quotes.
If you're using a string constant, you need to double every single quote:
const
sqlSCRIPTXXX =
'DECLARE #top VARCHAR(2000)'
+ #13#10'DECLARE #sql VARCHAR(4000)'
+ #13#10'SELECT #top =STUFF((SELECT DISTINCT'
+ #13#10' ''],[''+ ltrim([itemID])'
+ #13#10' FROM ARInvDet '
+ #13#10' ORDER BY ''],[''+ ltrim([itemID])'
+ #13#10' FOR XML PATH('''')'
+ #13#10' ), 1, 2, '''')+'']'''
+ #13#10''
+ #13#10''
+ #13#10'SET #sql ='''
+ #13#10'SELECT ItemID,Quantity,Price FROM('
+ #13#10'select * From ('
+ #13#10'select '
+ #13#10'a.CustomerID as [CustomerID],'
+ #13#10'a.DateFinalize as [Date],'
+ #13#10'ad.Quantity as [Quantity],'
+ #13#10'ad.UnitPrice as [Price],'
+ #13#10'i.ItemTypeID as [ItemTypeID],'
+ #13#10'i.ItemID as [ItemID]'
+ #13#10'from ARInvDMS a '
+ #13#10'inner join ARInvDet ad on a.ARInvoiceID = ad.ARInvoiceID'
+ #13#10'inner join item i on ad.ItemID = i.ItemID'
+ #13#10'WHERE CustomerID = 10056 and a.[DateFinalize] = CONVERT(DATETIME,''2/28/2014'', 102)'
+ #13#10'and i.[ItemTypeID] = 1'
+ #13#10') src'
+ #13#10''
+ #13#10'PIVOT '
+ #13#10'('
+ #13#10' SUM(Quantity)'
+ #13#10' FOR [ItemID] in (''+#top+'')'
+ #13#10''
+ #13#10') as pvt'
+ #13#10') as src2'
+ #13#10'UNPIVOT'
+ #13#10'('
+ #13#10' Quantity FOR ItemID in (''+#top+'')'
+ #13#10') as unpvt'
+ #13#10''
+ #13#10''''
+ #13#10''
+ #13#10'execute(#sql)';
I have a utility that I wrote just to do these conversions. The code above is the output of that utility.
So, in this case, the quotes around the date are doubled, and so are all the other quotes.

Resources