A piece of tsql code doesnt behave the same from production to Test environment. When the code below is executed on prod it brings back data
SELECT [col1xml]
In SQL Server you should store XML in a column typed XML
. This native type has a got a lot of advantages. It is much faster and has implicit validity checks.
From your question I take, that you store your XML in NTEXT
. This type is deprecated for centuries and will not be supported in future versions! You ought to change this soon!
SQL-Server knows two kinds of strings:
CHAR
or VARCHAR
), which is extended ASCIINCHAR
or NVARCHAR
), which is UTF-16 (UCS-2)If the XML has a leading declaration with an encoding (in most cases this is utf-8
or utf-16
) you can get into troubles.
If the XML is stored as 2-byte-string (at least the NTEXT
tells me this), the declaration has to be utf-16
. With a 1-byte-string it should be utf-8
.
The best (and easiest) was to ommit the declaration completely. You do not need it. Storing the XML in the appropriate type will kill this declaration automatically.
What you should do: Create a new column of type XML
and shuffle all your XMLs to this column. Get rid of any TEXT
, NTEXT
and IMAGE
columns you might have!
The next step is: Be happy and enjoy the fast and easy going with the native XML type :-D
You write: Data between environments is different
The error happens here:
cast([col1xml] as xml)
If your column would store the XML in the native type, you would not need a cast (which is very expensive!!) at all. But in your case this cast depends on the actual XML. As this is stored in NTEXT
it is 2-byte-string. If your XML starts with a declaration stating a non-supported encoding (in most cases utf-8
), this will fail.
Try this:
This works
DECLARE @xml2Byte_UTF16 NVARCHAR(100)='<?xml version="1.0" encoding="utf-16"?><root>test1</root>';
SELECT CAST(@xml2Byte_UTF16 AS XML);
DECLARE @xml1Byte_UTF8 VARCHAR(100)='<?xml version="1.0" encoding="utf-8"?><root>test2</root>';
SELECT CAST(@xml1Byte_UTF8 AS XML);
This fails
DECLARE @xml2Byte_UTF8 NVARCHAR(100)='<?xml version="1.0" encoding="utf-8"?><root>test3</root>';
SELECT CAST(@xml2Byte_UTF8 AS XML);
DECLARE @xml1Byte_UTF16 VARCHAR(100)='<?xml version="1.0" encoding="utf-16"?><root>test4</root>';
SELECT CAST(@xml1Byte_UTF16 AS XML);
Play around with VARCHAR
and NVARCHAR
and utf-8
and utf-16
...