Search code examples
sqlsql-servert-sqlsql-server-2012sqlxml

Raise exception if XML element does not exist


I have multiple procedures that accept XML parameters (I know I could use a TVP instead, but it fits with an older approach where the application also passes XML).

The following code populates a table from XML:

DECLARE @tmp TABLE (userID int, colA int);
DECLARE @xml XML = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rows>
    <row userId="1" colA="234" />
    <row userId="1" colB="564" />
    <row userId="1" colA="252" />
</rows>';

INSERT INTO @tmp 
    (userID, colA) 
SELECT 
    u.n.value('@userId', 'int'),
    u.n.value('@colA', 'int')
FROM
    @xml.nodes('/rows/row') AS u (n);

SELECT * FROM @tmp;

Note however that the second line of XML doesn't actually have a colA element. I know this creates a NULL in the table, but in my app, NULL values are permitted.

userID      colA
----------- -----------
1           234
1           NULL
1           252

So, is there any way to perform some type of check in TSQL (like this) before the data is populated?

For each XML row
    If (userId element does not exist) OR (colA element does not exist) Then
        RAISERROR (caught by BEGIN/END TRAN within procedures/calling procedure)

Solution

  • You can use SQLXML exist for that:

    select @xml.exist('rows/row[not(@colA)]')
    

    will return 1 if there's a row which doesn't have colA attribute. So you can use something like

    if @xml.exist('rows/row[not(@colA)]') = 1
        ...
        -- raiserror here
        ...
    

    sql fiddle demo