Encoding a SQL Server SELECT statement for HTML output - sql-server

I have this SELECT statement that I will be using in a SQL Server 2016 stored procedure:
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
DROP Table #TempTable
SELECT DISTINCT
STUFF((SELECT ', '+ CASE WHEN AU1.Color IS NOT NULL THEN +'<b><font color="' + AU1.Color + '">' + AU1.LastName+ ' ' + AU1.Initials + '</font></b>' + CHAR(10) ELSE
AU1.LastName + ' ' + AU1.Initials END AS [text()]
FROM
dbo.[Publication.PubMed.Author] AU1
WHERE
AU1.PMID = 30579772
ORDER BY
AU1.PMID
FOR XML PATH('')), 1, 1, '') AS authorList
INTO
#TempTable
SELECT * FROM #TempTable
And I want to save it with the < and > and when I have this as part of a larger SELECT statement it does but when I pull it out to run on it's own it does not. I have what I through was the answer with the [text()] but that does not help. The code gets put into an Word document as an HTML string and I it to run correctly. Should I store it encoded and worry about decoding on the endusers side? or can I store the html formatted string?
I get
Rodenbach RA, Norton SA, Wittink MN, <b><font color="Blue">Mohile S</font></b>
and I want
Rodenbach RA, Norton SA, Wittink MN, <b><font color="Blue">Mohile S</font></b>
What am I doing wrong? Thanks

Cast the the whole value with markup to xml, don't apply AS [text()].
Demo
select convert(xml, 'my text' + ' <p> my para </p>')
for xml path ('')
result
my text <p> my para </p>

Related

How to insert new line Char(13) in T-SQL

I have applied XML PATH and Stuff to show multiple records in single cell, which is all working fine but I am required to show each record in cell in separate single line i.e char(13) but in my solution I am getting result like
#x0D;; Canvey
; government
; More information needed
; More information required
Script
SELECT
ans.Id
,ans.ResponseId
,STUFF((SELECT DISTINCT
char(13)+char(10) +
'; ' + cod.Name
,' ' + COUNT(cod.Name)
FROM [dbo].[Highlights] as h
INNER JOIN [dbo].[CodedHighlights] as ch on h.Id = ch.HighlightId
INNER JOIN [dbo].[Codes] as cod on ch.CodeId = cod.Id
WHERE h.AnswerId = ans.Id
GROUP BY cod.Name
FOR XML PATH('')), 1, 1, '' ) [ANSWER/CODES]
FROM [dbo].[Answers] as ans
Try this
DECLARE #result VARCHAR(100)=
STUFF(
(
SELECT TOP 5 CHAR(13) + [name]
FROM sys.objects
FOR XML PATH(''),TYPE).value('.','nvarchar(max)'),1,1,'');
PRINT #result;
You must use TYPE to get a natively typed XML in order to use the .value() method. This will implicitly re-escape all entities to their actual string values.
Furthermore, I use PRINT, as the typical grid result would not show the line breaks.
Hint: If you use CHAR(13)+CHAR(10) you'd have to add ,1,2,'') as STUFF()'s paramaters.

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>

Arrow(-->) does not show in SQL Server SELECT when use as xml path

I am trying to get all route path separating with arrow (-->). But the arrow (-->) does not work, it is shown as -->.
SELECT
vrmd.LocationName + '--> '
FROM
dbo.tbl_VehicleRouteMapDetail vrmd
WHERE
vrmd.VrmapId = 1
ORDER BY
vrmd.VrmapId
FOR XML PATH('')
But it's working perfectly this way:
DECLARE #Route VARCHAR(MAX)= ''
SELECT #Route = #Route + vrmd.LocationName + '--> '
FROM dbo.tbl_VehicleRouteMapMaster vrmm
INNER JOIN dbo.tbl_VehicleRouteMapDetail vrmd ON vrmd.VrmapId = vrmm.VrmapId
ORDER BY vrmd.VrmapDetailId ASC
Why choose first query?
I need to use this query as subquery. In this case second query does not work for me:
SELECT
COUNT(ewva.VehicleId) Allocation, vii.Capacity,
STUFF((SELECT vrmd.LocationName + '=> '
FROM dbo.tbl_VehicleRouteMapDetail vrmd
WHERE vrmd.VrmapId = vrmm.VrmapId
ORDER BY vrmd.VrmapId
FOR XML PATH('')), 1, 1, '') AS name_csv
FROM
dbo.tbl_VehicleInfoInternal vii
INNER JOIN
dbo.tbl_EmpWiseVehicleAllocation ewva ON ewva.VehicleId = vii.VehicleId
INNER JOIN
dbo.tbl_VehicleRouteMapMaster vrmm ON vrmm.VehicleId = vii.VehicleId
GROUP BY
ewva.VehicleId, vii.Capacity, vrmm.VrmapId
Any help would be appreciated.
It's as simple as adding the TYPE directive to your FOR XML clause (docs here). This will return the result as an instance of the XML type rather than text. Text will have certain characters (e.g. > and <) translated (> and <) to fit within an XML element.
SELECT
vrmd.LocationName + '--> '
FROM
dbo.tbl_VehicleRouteMapDetail vrmd
WHERE
vrmd.VrmapId = 1
ORDER BY
vrmd.VrmapId
FOR XML
PATH(''), TYPE

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,'')

Not able to remove first comma in string SQL Server

The code works fine except for
SELECT DISTINCT isnull(#FEATURE + ', ', ',') + Feature
FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] as rf2 where (rf2.roomid = rf.roomid)
for xml path('')),
which is giving me problems. I do not know how to get rid of the first comma. I have tried substring but it removes all the commas(I guess since it's in a select statement). I even tried
COALESCE(#FEATURE + ', ', '') + FEATURE but I end up with the same result, either no commas or one extra comma at the end or at the very beginning.
DECLARE #FEATURE VARCHAR(500)
-- INSERT INTO BookableRooms IF NOT EXISTS ROOM NUMBER
INSERT INTO dbo.BookableRooms_test (FK_Building_code,
Room_num,Other_room_name,
Capacity_from,
Capacity_to,
Accessiblity,AV_book_separate,Flooring_type,Features,
Food_drink_allowed, Alcohol_allowed,Internet,
[Owner],FK_BookingContact_ID,
LCD_projector,Computer,FK_SpaceManager_code,Last_updated_date,Last_updated_by,SpecialFlag)
SELECT DISTINCT CASE
WHEN rf.[Building Reference] is null or rf.[Building Reference] = '' THEN 'HH'
ELSE rf.[Building Reference]
END,
[ROOMID],[Description],
(SELECT MIN(rf2.CAPACITY) FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] AS rf2 WHERE rf2.ROOMID = rf.ROOMID),
(SELECT MAX(rf2.CAPACITY) FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] AS rf2 WHERE rf2.ROOMID = rf.ROOMID),
dbo.iszero([Wheelchair Accessible]), dbo.iszero(rf.[Separate AV]),dbo.isflat(rf.[Flat Floor]),
(
SELECT DISTINCT isnull(#FEATURE + ', ', ',') + Feature
FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] as rf2 where (rf2.roomid = rf.roomid)
for xml path('')),
dbo.iszero(rf.[Food and Drink]),dbo.iszero(rf.[Alcohol]),dbo.iszero(rf.[Room Internet]),
'HH',5,
dbo.iszero(rf.[Digital Projector]),dbo.iszero(rf.[Computer]),'HH',GetDate(),'System',dbo.iszero(rf.[Restricted])
FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] as rf where NOT EXISTS(
SELECT 1 FROM dbo.BookableRooms_test b WHERE
b.Room_num = rf.ROOMID);
Use Stuff but on the outer side of subquery:
stuff ((SELECT DISTINCT ',' + Feature
FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] as rf2
WHERE (rf2.roomid = rf.roomid)
for xml path('')), 1, 1, '')
Use the STUFF function to remove the leading comma.
SELECT DISTINCT STUFF(',' + Feature
FROM [128.100.194.219, 1435].[EMSData].[dbo].[vOSLRoomFeatures] as rf2 where (rf2.roomid = rf.roomid)
for xml path('')),1,1,''),
I am not sure what you are trying to achieve. If my guess was wrong, it would good if you told us what results you expect in which situation.
Try this
CASE WHEN #FEATURE IS NULL THEN NULL ELSE #FEATURE + ', ' END

Resources