views:

412

answers:

3

I have a table with two columns: price (int) and price_display (varchar).

price is the actual numerical price, e.g. "9990"

price_display is the visual representation, e.g. "$9.99" or "9.99Fr"

I've been able to confirm the two columns match via regexp:

price_display not regexp format(price/1000, 2)

But in the case of a mismatch, I want to extract the value from the price_display column and set it into the price column, all within the context of an update statement. I've not been able to figure out how.

Thanks.

A: 

This is a "coding horror", relational database schemas should NOT be written like this!

Your having to write complex and unnecessary code to validate the data.

Try something like this:

SELECT CONCAT('$',(price/1000)) AS Price FROM ...

In addition, you can use a float, double or real instead of a integer.

If you need to store currency data, you might consider adding a currency field or use the systems locale functions to display it in the correct format.

rjstelling
Thank you for the response. Unfortunately I have no control over the schema; I simply inherited it and I must now correct the contained data.
Teflon Ted
+1  A: 

One approach would be to use REPLACE() function:

UPDATE my_table
SET    price = replace(replace(replace(price_display,'Fr',''),'$',''),'.','')
WHERE  price_display not regexp format(price/1000, 2);

This works for the examples data you gave:

'$9.99'
'9.99Fr'

Both result in 999 in my test. With an update like this, it's important to be sure to back up the database first, and be cognizant of the formats of the items. You can see all the "baddies" by doing this query:

SELECT   DISTINCT price_display
FROM     my_table
WHERE    price_display not regexp format(price/1000, 2)
ORDER BY price_display;
artlung
Thanks, this is good stuff, but I of course have a lot more currency symbols than just "$" and "Fr" so that replace chain would be out of control.
Teflon Ted
I'd be interested to see some representative results from the last query I posted. How many distinct items are there? Perhaps with a few more examples I or someone else can make a more informed piece of code. One thing I thought of is if you have items formatted like "$10" representing $10.00 then my method fails. But then you did not post that as a possibility. The last query I posted would be helpful in nailing down the query that will do the magic.
artlung
+2  A: 

This function does the job of only returning the digits 0-9 from the string, which does the job nicely to solve your issue, regardless of what prefixes or postfixes you have.

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#815

Copied here for reference:

SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS digits;
DELIMITER |
CREATE FUNCTION digits( str CHAR(32) ) RETURNS CHAR(32)
BEGIN
  DECLARE i, len SMALLINT DEFAULT 1;
  DECLARE ret CHAR(32) DEFAULT '';
  DECLARE c CHAR(1);
  SET len = CHAR_LENGTH( str );
  REPEAT
    BEGIN
      SET c = MID( str, i, 1 );
      IF c BETWEEN '0' AND '9' THEN 
        SET ret=CONCAT(ret,c);
      END IF;
      SET i = i + 1;
    END;
  UNTIL i > len END REPEAT;
  RETURN ret;
END |
DELIMITER ;

SELECT digits('$10.00Fr'); 
#returns 1000
Vladiat0r