Type-Safe Arithmetic
Adding EUR + USD throws an error instead of silently corrupting your data. Catch currency bugs at query time, not in production.
Storing money as DECIMAL(10,2) causes real bugs:
-- Mixing currencies silently corrupts dataSELECT SUM(amount) FROM transactions; -- 💥 USD + EUR + JPY = ???
-- Japanese Yen has no decimals, Kuwaiti Dinar has 3INSERT INTO prices VALUES (100.50, 'JPY'); -- Wrong! JPY has 0 decimals
-- Currency symbols are ambiguousSELECT '$100'; -- USD? CAD? AUD? SGD?INSTALL monetary FROM community;LOAD monetary;Type-Safe Arithmetic
Adding EUR + USD throws an error instead of silently corrupting your data. Catch currency bugs at query time, not in production.
Smart Parsing
Understands $99.99, €100, ¥10000, 100 USD, and USD 100. Rejects ambiguous symbols like S$ with helpful errors.
Correct Precision
JPY/KRW: 0 decimals. USD/EUR: 2 decimals. KWD/BHD: 3 decimals. BTC: 8 decimals. All handled automatically.
10 Rate Sources
ECB, Bank of Canada, RBA, Norges Bank, CNB, SNB, and more. 7 free sources, 3 paid for real-time data.
These examples run in your browser using DuckDB WASM:
-- 1. Load exchange rates (free, no API key)CREATE TABLE exchange_rates ASSELECT * FROM ecb_exchange_rates();
-- 2. Configure the extensionSET monetary_exchange_table = 'exchange_rates';
-- 3. Convert with arrow operator or macrosSELECT '100 EUR'::monetary ->> 'USD' AS arrow_syntax, USD('100 EUR'::monetary) AS macro_syntax;-- E-commerce: prices in local currency, reports in USDCREATE TABLE orders ( id INTEGER, customer_country VARCHAR, amount monetary);
INSERT INTO orders VALUES (1, 'DE', '99.99 EUR'), (2, 'JP', '15000 JPY'), (3, 'GB', '79.99 GBP');
-- Convert everything to USD for reporting-- Note: Requires exchange_rates table configuredSELECT id, amount, amount ->> 'USD' AS amount_usdFROM orders;
-- Safe conversion with fallback for missing ratesSELECT id, amount, TRY(amount ->> 'USD') AS amount_usd, CASE WHEN TRY(amount ->> 'USD') IS NULL THEN 'Rate unavailable' END AS statusFROM orders;| Source | API Key | Base | Update | Best For |
|---|---|---|---|---|
| ECB | Free | EUR | Daily | EU businesses |
| Bank of Canada | Free | CAD | Daily | Canadian businesses |
| RBA | Free | AUD | Daily | Australian businesses |
| Norges Bank | Free | NOK | Daily | Nordic businesses |
| Czech National Bank | Free | CZK | Daily | Czech businesses |
| Swiss National Bank | Free | CHF | Daily | Swiss businesses |
| FreeGoldAPI | Free | XAU | Daily | Precious metals |
| Twelve Data | Paid | Any | Real-time | Trading apps |
| Open Exchange Rates | Paid | USD | Hourly | Global apps |
| GoldAPI | Paid | XAU | Real-time | Precious metals trading |
| Feature | DECIMAL(10,2) | monetary |
|---|---|---|
| Currency stored with value | ❌ Separate column | ✅ Built-in |
| Prevents mixing currencies | ❌ Silent corruption | ✅ Throws error |
| Correct decimals per currency | ❌ Manual | ✅ Automatic |
Parse $99 or €100 | ❌ Manual | ✅ Built-in |
| Exchange rate conversion | ❌ Manual joins | ✅ price ->> 'USD' |
| Ambiguous symbol detection | ❌ No | ✅ Helpful errors |
Use Cases
See real-world examples for e-commerce, finance, and crypto.
Exchange Rates
Set up automatic rate fetching from 10 different sources.
All Functions
Complete reference for all functions, operators, and aggregates.
Double-Entry Ledgers
Build accounting systems with currency-validated transactions.