问题
I must compare 2 xml strings(varchar(max) in sql) like these ones:
'<table_name id="2" name="Bob" job="student"/>'
'<table_name id="2" name="john" job="teacher"/>'
And the result must be the differences only, which means, ill get 2 strings, the first one will me the original values, and the second one will be the new values. However if there are no differences then there will be an empty string, in this case for example:
output 1: 'name="Bob", job="student"'
output 2: 'name="john", job="teacher"'
As you see, we didn't get the id string attached because there wasn't any change, so naturally, no changes means no string to return.
回答1:
Here is a generic approach up to 100 Attributs:
DECLARE @XML1 XML='<table_name id="2" name="Bob" job="student"/>';
DECLARE @XML2 XML='<table_name id="2" name="john" job="teacher"/>';
WITH CountAttributs AS
(
SELECT LEN(CAST(@XML1 AS VARCHAR(MAX)))-LEN(REPLACE(CAST(@XML1 AS VARCHAR(MAX)),'=','')) AS X
)
, E1(N) AS(SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)) --10 ^ 1
, E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b) -- 10 ^ 2 = 100 rows
, CteTally AS
(
SELECT TOP((SELECT X FROM CountAttributs)) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS Nmbr
FROM E2
)
,AttributNames AS
(
SELECT Nmbr,@XML1.value('local-name((*/@*[sql:column("Nmbr")])[1])', 'varchar(max)') AS AttributName
FROM CteTally
)
SELECT
(
SELECT '' + CASE WHEN @XML1.value('(*/@*[fn:local-name()=sql:column("AttributName")])[1]','varchar(max)')
<> @XML2.value('(*/@*[fn:local-name()=sql:column("AttributName")])[1]','varchar(max)')
THEN AttributName + ': ' + @XML2.value('(*/@*[fn:local-name()=sql:column("AttributName")])[1]','varchar(max)') + ', ' ELSE '' END
FROM AttributNames
FOR XML PATH('')
)
Result:
name: john, job: teacher,
回答2:
Something like this?
Paste this into an empty query window and execute. Adapt to your needs:
DECLARE @XML1 XML='<table_name id="2" name="Bob" job="student"/>';
DECLARE @XML2 XML='<table_name id="2" name="john" job="teacher"/>';
WITH AttributValues AS
(
SELECT @XML1.value('/table_name[1]/@id','varchar(max)') AS id1
,@XML1.value('/table_name[1]/@name','varchar(max)') AS name1
,@XML1.value('/table_name[1]/@job','varchar(max)') AS job1
,@XML2.value('/table_name[1]/@id','varchar(max)') AS id2
,@XML2.value('/table_name[1]/@name','varchar(max)') AS name2
,@XML2.value('/table_name[1]/@job','varchar(max)') AS job2
)
SELECT 'The differences: '
+ CASE WHEN id1<>id2 THEN 'id: ' + id1 + ' or ' + id2 + ' | ' ELSE '' END
+ CASE WHEN name1<>name2 THEN 'name: ' + name1 + ' or ' + name2 + ' | ' ELSE '' END
+ CASE WHEN job1<>job2 THEN 'job: ' + job1 + ' or ' + job2 ELSE '' END
FROM AttributValues
Result
The differences: name: Bob or john | name: student or teacher
来源:https://stackoverflow.com/questions/33377196/finding-the-differences-only-between-2-strings-in-sql