Refer to UTXO by output index or output full address in blockchain? I'm writing my own simple crypto and wondering whether input in a transaction should refer to unspend output only by it's TXID and vout (index in outputs vector in a transaction) OR by it's TXID and full address in a blockchain - that is block height, transaction index in a block and output index in a transaction.
The first approach seems to have a flaw - it's unlikely but possible for two different outputs to have the same TXID and vout.
But in the second approach I don't even need TXID when I have the full blockchain address right? I don't want to double on bookeeping - when there's duplicate data you need to make sure it's consistent.
So my two question's are:

How to avoid the problem with two transaction's accidentally having the same hashes in an elegant way that - ideally - doesn't require storing full addresses?
How is it done in Bitcoin? (here I guess that bitcoin's Bip34 update was addressing this flaw I mentioned - but I don't understand how)

General advices on solutions are very welcome. Thanks in advance!
In Bitcoin, it was originally an assumption that miners producing blocks would use a unique address per transaction, making sure that the coinbase of each block had a unique TXID. As this was not enforced, users accidentally made duplicate transactions by setting the same destination address for multiple solved blocks. BIP34 simply adds a new field to be validated to the block, requiring that the height is also part of the hash, ensuring uniqueness for all future blocks.
For the two special cased BIP34 blocks, the outcome is rather simple. The first instance of the TXID creates the UTXO, the second invocation does nothing at all because the output already exists, and if they were ever spent the UTXO can only be removed from the database a single time. The money involved in the second instance of the TXID was destroyed, causing a loss of 100 BTC total.