What is the difference between decimal and numeric in Postgres? - postgresql

I'm changing a column in the database from "money" to "numeric" per some previous advice here.
Looking through the data types in postgres -- https://www.postgresql.org/docs/current/static/datatype-numeric.html -- I can't see any differences between numeric and decimal in the descriptions.
What is the difference between decimal and numeric, and is there any reason I should use numeric instead of decimal for prices in my database?

According to the manual they are the same.
The types decimal and numeric are equivalent. Both types are part of
the SQL standard.
https://www.postgresql.org/docs/current/static/datatype-numeric.html
The difference lies in the SQL standard which allows for different behaviour:
NUMERIC must be exactly as precise as it is defined — so if you define 4 decimal places, the DB must always store 4 decimal places.
DECIMAL must be at least as precise as it is defined. This means that the database can actually store more digits than specified (due to the behind-the-scenes storage having space for extra digits). This means the database might store 1.00005 instead of 1.0000, affecting future calculations.
Difference between DECIMAL and NUMERIC

Related

Oracle to_char numeric masking to postgres

I'm porting a procedure from Oracle to Postgres.
In select of a query, I have TO_CHAR(v_numeric, '990.000')
It seems, the same TO_CHAR(v_numeric, '990.000') works in Postgres with same result.
Can someone please explain what the '990.000' in the query does?
TO_CHAR(123.4, '990.000') returns 123.400 in both Oracle and Postgres. Whereas TO_CHAR(1234.400, '990.000') returns ######## in Oracle and ###.### in Postgres. Does this ######## and ###.### hold the same numeric value which is inputted?
to_char is a function to format a number as string for output. The PostgreSQL function is there expressly for Oracle compatibility, but it is not totally compatible, as you see.
The format 990.000 means that there will be one to three digits before the decimal point and three digits after it. 9 means that a value of 0 in that position will result in a blank rather than a 0.
The # characters signify that the number cannot be represented in that format. The reason is that there are more than three digits before the decimal point.
The resulting string does not "hold" a number, it is the rendering of a number as a string. It doesn't hold anything but the characters it consists of.

How to handle NaNs in pandas dataframe integer column to postgresql database

I have a pandas dataframe with a "year" column. However some rows have a np.NaN value due to an outer merge. The data type of the column in pandas is therefore converted to float64 instead of integer (integer cannot store NaNs?). Next, I want to store the dataframe on a postGreSQL database. For this I use:
df.to_sql()
Everything works fine but my postGreSQL column is now type "double precision" and the np.NaN values are now [null]. This all makes sense since the input column type was float64 and not integer type.
I was wondering if there is a way to store the results in an integer type column with [nans].
Example Notebook
Result of Ami's answer:
(integer cannot store NaNs?)
No, they cannot. If you look at the postgresql numeric documentation, you can see that the number of bytes, and ranges, are completely specified, and integers cannot store this.
A common solution in this case is to decide, by convention, that some number is logically a nan. In your case, if it is year, you might choose a negative value (or just -1) as that. Before writing, you could use
df.year = df.year.fillna(-1).astype(int)
Alternatively, you can define another column as year_is_none.
Alternatively, you can store them as floats.
These solutions range from most efficient, to least efficient in terms of memory.
You should use it;
df.year = df.year.fillna(-1) OR 0

Money type: remove currency symbol without type casts

I'm using MONEY type for currency data in my Postgres table. When I select data, postgres formats values according to system's lc_monetary setting.
I would like to get rid of currency symbol in the query result without using explicit type casts (I'm using Laravel's query builder currently. Type casts will require raw queries).
Is there a way to setup lc_monetary config setting so that currency values in query results are formatted exactly like simple floats with 2-digit precision and without thousands separator (so that I would be able to use it as a string/float in my PHP code)?
Most people I have talked to reccommend not using the money type. Typically MONEY types get output as strings by your local implementation becuase of the LC_MONETARY formatting. Most people (myself included) recommend using a NUMERIC for your monetary values.
Also you mentioned placing your money values in a float. Floats on computers have rounding errors naturally and can cause issues with monetary amounts, so be careful.
In Python we use the decimal class when we need to do math on money, I assume that PHP has something similar.
Is select money_column/1::money safe...
According to the doc the result of dividing by money is double precision.... (The currency cancels out).

saving data like 2.3214E7 into postgresql

am new to postgresql (redshift)
i am copying CSV files from S3 to RedShift and there's an error about trying to save 2.35555E7 number into a numeric | 18, 0 column . what is the right datatype for this datum ?
thanks
numeric (18,0) implies a scale of zero, which is a way of saying no decimals -- it's a bit like a smaller bigint.
http://www.postgresql.org/docs/current/static/datatype-numeric.html
If you want to keep it as numeric, you want to use numeric instead -- with no precision or scale.
If not, just use a real or a double precision type, depending on the number of significant digits (6 vs 15, respectively) you want to keep around.
Your example data (2.35555E7) suggests you're using real, so probably try that one first.
Note: select 2.35555E7::numeric(18,0) works fine per the comments, but I assume there's some other data in your set that is causing issues.

Is it possible to store commas instead of points for decimal fields in a PostgreSQL database?

Is it possible to store commas instead of points for decimal fields in a PostgreSQL database?
That has nothing to do with PostgreSQL. PostgreSQL does not store commas or points for decimal fields. It uses an internal number representation for numbers (int, floats, numeric).
If you need to format numeric information with PostgreSQL, you can use to_char function or use your client side programming language to format numbers.
Why? No programming language will accept decimals using comma's as a seperator. Presentation should be done in the presentation layer of your application, not in the storage layer.
http://www.php.net/manual/en/language.types.float.php