opc.three (6/29/2013)
Solomon Rutzky (6/29/2013)
This is a little more flexible, and straight-forward, than using FOR XML as that might not be desirable when debugging a query.As with most solutions to a given problem there are trade offs. If any of these characters appear in the text you're trying to view you'll have a harder time using the XML data type:
SELECT CAST('<' AS XML)
GO
SELECT CAST('&' AS XML)
GO
SELECT CAST('<' AS XML)
GO
Thanks for pointing that out. I had completely forgotten about encoding certain characters. I can find only 2 that truly need to be converted. You listed 3 but the < was in there twice and while you might have meant >, that character is auto-converted. So the following adaptation of the overly-simplistic CONVERT should work in most cases:
SELECT CONVERT(XML, REPLACE(REPLACE(N'test < & > me', N'&', N'&'), N'<', N'<'))
I say "most cases" as there is a subset of the UCS-2 character set that is not as easily convertible, at least not without a lot of additional REPLACE() functions that realistically won't be used that much. Fortunately the white-space control characters (13 = Carriage Return, 10 = Line Feed, and 9 = Tab) come through just fine.
To make the updated CONVERT more usable / less cumbersome, it can be encapsulated in a UDF as follows:
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
IF (OBJECT_ID('dbo.ShowEntireString') IS NOT NULL)
BEGIN
DROP FUNCTION dbo.ShowEntireString
END
GO
CREATE FUNCTION dbo.ShowEntireString (@String NVARCHAR(MAX))
RETURNS XML
WITH SCHEMABINDING
AS
BEGIN
RETURN CONVERT(XML, REPLACE(REPLACE(@String, N'&', N'&'), N'<', N'<'))
END
GO
So first a simple test:
SELECT dbo.ShowEntireString(N'test < string for & invalid > chars' + NCHAR(13) + NCHAR(10) + N'new line?' + NCHAR(9) + 'and tabbed?')
And now the full test, showing both a) nearly all of the UCS-2 character set represented [only missing 2078 of the 65,535 characters], and b) a sizable string fully represented [in Grid mode].
DECLARE @String NVARCHAR(MAX)
SET @String = N'A' + NCHAR(13) + N'B' + NCHAR(10) + N'C' + NCHAR(9) + N'D'
;WITH cte AS
(
SELECTTOP (65535) ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [TheNumber]
FROMmaster.sys.all_columns sc1
CROSS JOINmaster.sys.all_columns sc2
)
SELECT@String = @String + NCHAR(cte.TheNumber)
FROMcte
WHEREcte.TheNumber BETWEEN 32 AND 65533 -- 0 through 31 error (well, except 9, 10, and 13)
ANDcte.TheNumber NOT BETWEEN 55296 AND 57343 -- invalid in XML
SELECT LEN(@String), DATALENGTH(@String)
-- 63461 and 126922
SET @String = REPLICATE(@String, 20)
SELECT LEN(@String), DATALENGTH(@String)
-- 1269220 and 2538440
SELECT dbo.ShowEntireString(@String)
Can you now find a case where this method does not work? Including the case where the other method does not work? If so, please let me know how to duplicate the test. Thanks.
Take care,
Solomon...
SQL# — https://SQLsharp.com/ ( SQLCLR library ofover 340 Functions and Procedures)
Sql Quantum Lift — https://SqlQuantumLift.com/ ( company )
Sql Quantum Leap — https://SqlQuantumLeap.com/ ( blog )
Info sites — Collations • Module Signing • SQLCLR