To provide a general answer to this question, I did the following (all the code below is available on the fiddle here).
- Just a note before we start. This is a signal lesson about UI design. NEVER, EVER let users enter text (if at all possible)! For example, the currency, if there's a choice, have a dropdown - don't let users enter a three-letter code! Likewise with the amount - validate it:
- validate it on data-entry at the first point of sale/contact - e.g. amount >= 0, correct number of decimal points, commas &c., no trailing or leading spaces...
and
- validate on INSERTion into to the database (amount >= 0, formatting is not for the database - just store a number in a field of the appropriate type for your currency - leave any formatting to your app/Excel... enforce any other minimum and/or maximum constraints also. Put as much control into the table's DDL as possible. You could use
ON INSERT
triggers for even more control!
The Golden Rule (of UI design) is that if you allow users the possibility of messing up, then they will find a way of doing so!
Final word on this matter - store relevant datums together - the currency field in its own 3 letter code field - the actual amount in a DOUBLE PRECISION or REAL or whatever. Avoid VARCHAR()/TEXT
fields with a mix of data.
Anyway now, down to brass tacks!
I created a sample table:
CREATE TABLE payment
(
amount TEXT NOT NULL
);
and populated it with "data":
INSERT INTO payment VALUES
('KES 0.80'),
('KES 0.80'),
('KES .80'),
('xyzKES 0.80'),
('KES . 0.80'),
('KES 0.80afasf'),
('KES 0.80__asdfa'),
('KES 0.80..asdfasdf'),
('KES 0.8.0..asdfasdf'),
('KES 0.8.0..asdfasdf');
Then, the tidying up step uses the REGEXP_REPLACE()
function. The key thing about this function is to remember that the 'g'
flag is important - with it, everything that matches is replaced, without, only the first occurrence of the pattern is replaced!
SELECT
REGEXP_REPLACE(amount, '[^0-9\.]+|\. +|\.0|\.{2,}', '', 'g')::DOUBLE PRECISION
FROM payment;
Result:
regexp_replace
0.8
0.8
0.8
0.8
0.8
0.8
0.8
0.8
0.8
0.8
It's not perfect, but should do the job adequately. If you're interested, you can check out the wreckage of my previous attempts here. I would urge you to check out regular expressions here - they are tricky as you will see if you check out my previous efforts. There are many other regular expression sites.