The UTXO database starts empty and then is updated while the blockchain is parsed in the manner that you described. Only, there can be more than one input and more than one output for a transaction, so I'd put it like this:
for block in blocks:
for transaction in block:
for(input in transaction):
utxoset.remove(input)
for(output in transaction):
utxoset.add(output)
Obviously, the block is checked for validity and therefore we know that the inputs and outputs are legit.
The UTXO set then stores the UTXOs referenced by outpoints as key, where an outpoint consists of:
- TXID: Unique hash identifier of the transaction that created the output
- index: the position of the output in the transaction's output list
And the information stored in the Transaction Outputs is:
- value: number of satoshis the output is good for
- pubkey script: the conditions the output can be spent under
Finally, for each block undo data is generated, in the case that a reorganization occurs.