XQuery Comparisons: General Equality Is Not Singleton Equality

XQuery Comparisons use different rules for general sequence operators and singleton value operators. I make equality and inequality visible side by side. A general unequal-pair result is not always the inverse of an equal-pair result.

The two sequences below contain an equal pair and several unequal pairs. Their general equality and inequality can therefore both be true. That result becomes easier to understand when each operator’s question is stated explicitly.

Three pale ceramic bowls, two filled with blue and terracotta stones and one empty, beside two loose stones.
Three pale ceramic bowls, two filled with blue and terracotta stones.

Use fixed sequences and an empty path

The populated inputs are sequences containing one and two, and two and three. Their shared value is two. The singleton examples compare two with itself.

The XML document is a small root element with no missing child. The missing path therefore supplies an empty node sequence. It adds a boundary case without requiring an intentional runtime error.

Each XQuery expression returns one or zero through an explicit conditional. The SQL result contains eight integer diagnostics in one row. The query creates no objects and changes no source document.

WITH Input AS
(
    SELECT CAST('<root/>' AS xml) AS Doc
)
SELECT Doc.value('if ((1,2) = (2,3)) then 1 else 0', 'int') AS GeneralEqual,
       Doc.value('if ((1,2) != (2,3)) then 1 else 0', 'int') AS GeneralNotEqual,
       Doc.value('if (not((1,2) = (2,3))) then 1 else 0', 'int') AS NegatedEqual,
       Doc.value('if (2 eq 2) then 1 else 0', 'int') AS SingletonEqual,
       Doc.value('if (2 ne 2) then 1 else 0', 'int') AS SingletonNotEqual,
       Doc.value('if (/root/missing = 2) then 1 else 0', 'int') AS EmptyEqual,
       Doc.value('if (/root/missing != 2) then 1 else 0', 'int') AS EmptyNotEqual,
       Doc.value('if (not(/root/missing = 2)) then 1 else 0', 'int') AS NegatedEmptyEqual
FROM Input;
Native SSMS results show that general equality and inequality can both be true for overlapping sequences. Empty comparisons and negation produce different results.
Native SSMS results show that general equality and inequality can both be true for overlapping sequences. Empty comparisons and negation produce different results. Open the results at full size.

Explain why both general flags are one

GeneralEqual should be one because the pair two and two is equal. GeneralNotEqual should also be one because another pair, such as one and three, is unequal. The operators find a qualifying pair independently.

NegatedEqual should be zero because the general equality already succeeds. It asks whether that equality result is false. It does not search for a separate unequal pair.

The singleton expressions should return one for two eq two and zero for two ne two. Both operands contain one atomic value. These operators are intended for that singleton comparison contract.

The example deliberately avoids passing multiple values to eq or ne. Such expressions violate their singleton requirement. Documenting the restriction does not require including a failing statement in the copyable demonstration.

General, singleton and empty

Keep the empty case in the model

The missing path has no value that can form an equal pair with two. It also has no value that can form an unequal pair. EmptyEqual and EmptyNotEqual should therefore both be zero.

NegatedEmptyEqual should be one because the corresponding general equality is false. That is another direct difference from the general inequality operator. Keeping all three columns makes the missing case explicit.

I don’t replace the missing sequence with a fabricated value. A fallback would change the question and its result. Decide separately whether an absent XML value should pass, fail or be reported by a business rule.

The fixed numeric values avoid an additional string-comparison issue. Real XML values can require explicit typing or conversion. Check those rules before transferring the result to mixed numeric and textual content.

Write the intended predicate

A requirement that any values match is different from a requirement that no values match. A requirement that any values differ is different again. Name those questions before choosing the operator.

The query is not a relational SQL NULL comparison example. These are XQuery sequence operations inside XML methods. Their empty-sequence behavior should be tested in that context.

The full expected row preserves populated, singleton and empty cases together. It establishes no performance claim. Keep these distinctions when adapting a predicate to an XML filter or validation rule.

Want to run it yourself? Copy the query above into any query window. It needs no tables.

Say the question out loud, and the operator picks itself.

General inequality is not negated equality, it is a test for any differing pair.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.


Discover more from SQL Authority with Pinal Dave

Subscribe to get the latest posts sent to your email.

SQL Function, SQL Scripts, SQL Server, SQL XML
Previous Post
SQL SERVER – vCPUs – How Many Are Too Many CPU for SQL Server Virtualization ? – Notes from the Field #003
Next Post
SQL SERVER – FIX : Error 3154: The backup set holds a backup of a database other than the existing database – SSMS

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.