Difference between revisions of "XQuery Update"

From BaseX Documentation
Jump to navigation Jump to search
Line 117: Line 117:
update on a fragment, which would raise an error if applied on a database node.
update on a fragment, which would raise an error if applied on a database node.
;Target is a DOM node:  
;DOM node as target:  
:<pre>insert node attribute id{'1'} into <a id='0'/></pre>
:<pre>insert node attribute id{'1'} into <a id='0'/></pre>
:Result: <pre/>
:Result: <pre/>
;Target is a database node:
;database node as target:
:File 'doc.xml': <pre><n id='1'/></pre>
:File 'doc.xml': <pre><n id='1'/></pre>
:<pre>insert node attribute id{'0'} into doc('doc.xml')//n</pre>
:<pre>insert node attribute id{'0'} into doc('doc.xml')//n</pre>

Revision as of 12:19, 13 December 2010

With the release of version 6.0, BaseX offers a complete implementation of the XQuery Update Facility (XQUF).


This article aims to provide a very quick and basic introduction to the XQUF. First are some examples for new expressions and useful information on each of them. After that a few problems are solved that arise frequently, due to the special nature of the language. These are stated in the Concepts section.

New Functionality

Updating Expressions

There are five new expressions to modify data. While insert, delete, rename and replace basically explain themselves, the transform expression is different. Modified nodes are copied in advance and the original databases remain untouched.

An expression consists of a target node (the node we want to alter) and additional information like insertion nodes, a QName, etc. which depends on the type of expression. You can find a few examples and additional information below.


insert node (attribute {'a'} {5}, 'text', <e/>) as first into /n

You can either insert a single node or a sequence of nodes into a single target node. Several modifiers are available to specify the exact insert location.


delete node //node

The example query deletes all <node> elements in your database. Note that, in contrast to other updating expressions, the delete expression allows multiple nodes as a target.


replace value node /n with <a/>

The target element is replaced by the DOM node <a/>.


for $n in //node
return rename node $n as 'renamedNode' 

All node elements are renamed. An iterative approach helps to modify multiple nodes within a single statement. Nodes on the descendant- or attribute-axis of the target are not affected. This has to be done explicitly as well.

Non-Updating Expressions


copy $c := doc('/doc.xml')//node[@id=1]
modify rename node $c as 'copyOfNode'
return $c

The node element with @id=1 is copied and subsequently assigned a new QName using the rename expression. Note that the transform expression is the only expression which returns an actual XDM instance as a result. You can therefor use it to modify results and especially DOM nodes. This is a frequent issue beginning users are often confronted with. More on this topic can be found in the XQUF Concepts section.



FN:put() is also part of the XQUF and enables the user to serialize XDM instances to secondary storage. It is executed at the end of a snapshot. Serialized documents therefore reflect all changes made effective during a query.

XQUF Concepts

There are a few specialties around XQuery Update that you should know about. In addition to the simple expression, the XQUF adds the updating expression as a new type of expression. An updating expression returns only a PUL as a result which is subsequently applied to addressed databases and DOM nodes. A simple expression cannot perform any permanent changes and returns an empty or non-empty sequence.

Pending Update List

The most important thing to keep in mind when using XQuery Update is the Pending Update List (PUL). Updating statements are not executed immediately, but are first collected as update primitives within a set-like structure, the PUL. At the end of a query, all update primitives on this list are applied in a strict order after some compatibility tests. If a conflict exists, an error message is returned and all accessed databases remain untouched (atomicity). For the user this means updates are only visible after the end of a snapshot.

I we have the document:

<doc> <a/> </doc>

... and perform the following query:

insert node <b/> into /doc,
for $n in /doc/child::node()
   return rename node $n as 'justRenamed'

The document looks like this:

<doc> <justRenamed/><b/> </doc>

Despite explicitly renaming all child nodes of <doc/>, the former <a/> element is the only one to be renamed. The element is inserted within the same snapshot and is therefore not yet visible to the user.

Returning Results shows how to access updated nodes and return query results.

Returning Results

It is not possible to mix different types of expressions in a query result. The outermost expression of a query must either be a collection of updating or non-updating expressions. Generally there is no way to perform any updating queries and return a result at the same time, as you cannot access your own changes during a single query. Regarding database nodes, you can update your nodes within the first query and access modifications in subsequent queries.

But trying to modify and return a DOM node within the same snapshot is another story. As changes on DOM nodes are non-persistent, you cannot access them in a subsequent query. This is where the transform expression comes into play.

Function Declaration

To use updating expressions within a function, the 'updating' flag has to be added to the function declaration. A correct declaration of a function that contains updating expressions (or one that calls updating functions) looks like this:

declare updating function { ... }

Effects on Your Documents

In BaseX, all updates are performed on database nodes. Update operations thus never affect the original input file. You can, however, use the EXPORT command or the fn:put() function to create an updated XML file. Activating the WRITEBACK property (SET Command) directly propagates changes of your database to the original input file. Make sure you back up your data in advance, as this approach modifies the underlying XML file.


As BaseX aims mainly for efficiency, the maintenance of indexes is left to the user. This requires the user to call the Optimize command if up-to-date index structures are necessary. Using this approach guarantees fast updates and fast access at the same time.

DOM Nodes

So far BaseX differentiates between fragments and database nodes. Updates on fragments have no effect on any existing databases and are therefore not applied at all. This includes the test for violation of any constraints. Thus it is possible to execute an update on a fragment, which would raise an error if applied on a database node.

DOM node as target
insert node attribute id{'1'} into <a id='0'/>
database node as target
File 'doc.xml':
<n id='1'/>
insert node attribute id{'0'} into doc('doc.xml')//n
Result: [XUDY0021] Duplicate attribute "id".

Fragments & fn:put()

As a consequence, updates on a fragment are not visible in an XML file created with fn:put(). If this functionality is required, the transform expression can be applied. The copied nodes in a transform expression are internally treated like database nodes and are updatable as a result.

Example 1
let $n := <n/> 
 return (insert node <x/> into $n, put($n,'doc.xml'))
Resulting File 'doc.xml': <n/>
Example 2
 copy $nn := <n/> 
 modify insert node <x/> into $nn 
 return $nn, 'doc.xml' 
Resulting File 'doc.xml': <n> <x/> </n>