views:

352

answers:

3

I need to store multiple currencies in SQL server. I understand that SQL won't support all different types of currencies (unless I store it as a string, but I don't want to do that).

My idea was to convert all the values from their currency format to a standard double and store that instead. Then just re-format based on the culture info when displaying. However, I have tried doing something like e.g.

var cultureInfo = new System.Globalization.CultureInfo("en-US");
double plain = return Double.Parse("$20,000.00", cultureInfo);

This doesn't ever seem to work it always throws a FormatException. Even removing the currency symbol and just trying to do this based on the number alone does the same thing. This is just an example I want to support pretty much any type of currency.

Is there a standard way of stripping out currency and getting the value as a double?

+3  A: 

I think this should work:

double.Parse(currencyValue, NumberStyles.Currency);

Here you can see more about the NumberStyles:
http://msdn.microsoft.com/en-us/library/7yd1h1be.aspx

ho1
Yeah, or `double.Parse(currencyValue, NumberStyles.Currency, cultureInfo`) for a given culture.
Noldorin
@ho: Damn, I was passing in `NumberStyles.Any` originally! Was close....thanks.
James
+1  A: 

Unless I'm misunderstanding the intent behind your question...

Why not create two fields:

Amount MONEY
CurrencyID INTEGER

These records would look like:

(12.34, 1), (10000000000000000, 3)

CurrencyID is a foreign key into a table that looks like this:

CurrencyID INTEGER PRIMARY KEY NOT NULL
ISOSymbol NCHAR(3) NOT NULL
DisplayName NVARCHAR(50)

For example (1, USD, US Dollar), (2, CAD, Canadian Dollar), ( 3, ZWD, Zimbabwe Dollar)...

Here's a Link to the Authoritative List of ISO 4217 Currency Symbols

Bob Kaufman
I've used a CLR UDT for Currency before where I have had multiple fields in a table accepting currency values that might differ between rows and column and it would have been tedious to add a second ancillary column for each field giving the currency code. This way you can store the code and value in the same field and enforce things like throwing an error or doing automatic conversion if there is an attempt to add dollars and euros for example.
Martin Smith
+3  A: 

You should pass NumberStyles to the Parse function

Decimal.Parse("$20,000.00", NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, new CultureInfo("en-US"));

A few other things, for currencies I would suggest you use Decimal. And this might be way off, but it might be better to store the currency data as Money in the DB and add a currency code to identify the currency of the value.

Yes, and the answers suggestung NumberStyles.Currency that would be better. It is a pre-Or'd value, if you still think you want to use the strings.

Chris Taylor
I was currently using `float` as the DB type? Is this not a good idea?
James
@Chris: reason being the column holds other information i.e. not everything stored is monetary, would it still be safe to store non-monetary values using this type?
James
@James, so as a rule I do not think that storing different kinds of data in a field is good, but of course I do not know your design and you might have a very good reason. So I offer this advice, I guess you have an indicator that will indicate the data type in the field? I suggest you store the numeric values using a consistent Invariant culture string format and use the indicator to decide you to present the data. So you can always extract the data and convert to numeric/decimal consistently and then make decision about presentation when you need to present the data.
Chris Taylor
Probably didn't explain my comment properly. All datatypes that are stored in that column are of number value, however, some are just plain integers, where as some might be monetary. The more I think about it the more I think it should be ok to store integers as decimals as I can just round the number up.
James