1. 程式人生 > >PostGreSQL資料庫有的為啥找不到資料型別(比如Double)

PostGreSQL資料庫有的為啥找不到資料型別(比如Double)

今天用NavCate建立PostGreSql建標,使用Double發現居然沒有這個型別,百度各種部落格都表示有Double型別,但是我測試就沒了

這裡寫圖片描述

後來發現,這裡面居然有別名

名字 別名 描述
bigint int8 有符號 8 位元組整數
bigserial serial8 自增八位元組整數
bit [ (n) ] 定長位串
bit varying [ (n) ] varbit 變長位串
boolean bool 邏輯布林量 (真/假)
box 平面中的長方形
bytea 二進位制資料(“位元組陣列”)
character varying [ (n) ] varchar [ (n) ] 變長字串
character [ (n) ] char [ (n) ] 定長字串
cidr IPv4 或者 IPv6 網路地址
circle 平面中的圓
date 日曆日期(年,月,日)
inet IPv4 或者 IPv6 網路地址
integer int,int4 四位元組長有符號整數
interval [ (p) ] 時間間隔
line 平面中的無限長直線
lseg 平面中的線段
macaddr MAC 地址
money 貨幣金額
numeric [ (p, s) ] decimal [ (p, s) ] 可選精度的準確數字,
小數點前最多為131072個數字;
小數點後最多為16383個數字。
double precision float8 雙精度浮點數字,小數點前最多為131072個數字;
小數點後最多為16383個數字。
建表格式float8(整數+小數點總體長度,小數點的長度)
前面引數是精度
後面是小數點精度比例
path 平面中的幾何路徑
point 平面中的點
polygon 平面中的封閉幾何路徑
real float4 單精度浮點數
smallint int2 有符號兩位元組整數
serial serial4 自增四位元組整數
text 變長字串
time [ (p) ] [ without time zone ] 一天裡的時間
time [ (p) ] with time zone timetz 一天裡的時間,包括時區
timestamp [ (p) ] [ without time zone ] 日期和時間
timestamp [ (p) ] with time zone timestamptz 日期和時間

1 . 整數型別

型別 smallint,integer,和 bigint 儲存各種範圍的全部是數字的數,也就是沒有小數部分的數字。 試圖儲存超出範圍以外的數值將導致一個錯誤。

常用的型別是 integer,因為它提供了在範圍,儲存空間, 和效能之間的最佳平衡。一般只有在磁碟空間緊張的時候才使用 smallint。而只有在 integer 的範圍不夠的時候才使用 bigint,因為前者絕對快得多。

bigint 型別可能不是在所有平臺上都運轉正確, 因為它依賴編譯器對八位元組整數的支援。在那些沒有這樣支援的機器上, bigint 的作用和 integer 一樣(但是仍然佔據八位元組儲存)。不過,我們還不知道任何有這樣的情況的平臺。

SQL只聲明瞭整數型別 integer(或int)和 smallint。型別 bigint,和型別名 int2,int4,和 int8 都是擴充套件, 也在許多其它 SQL 資料庫系統中使用。

2. 任意精度數值

型別 numeric 可以儲存最多1000位精度的數字並且準確地進行計算。 我們特別建議將它用於貨幣金額和其它要求計算準確的數量。不過,numeric 型別上的算術運算比整數型別或者我們下一節描述的浮點數型別要慢很多。

在隨後的內容裡,我們使用了下述術語: 一個 numeric 的比例是到小數點右邊為止小數部分的位數, numeric 的精度是整個數字裡全部資料位的數目,也就是小數點兩邊的資料數目。 因此數字 23.5141 的精度為6而比例為4。你可以認為整數的比例為零。

numeric 欄位的最大精度和最大比例都是可以配置的。要宣告一個型別為 numeric 的欄位,你可以用下面的語法

NUMERIC(precision, scale)
精度必須為正數,比例可以為零或者正數。 另外,

NUMERIC(precision)
選擇了 0 為比例。不帶任何精度或者比例宣告

NUMERIC
則建立一個可以儲存一個直到實現精度上限的任意精度和比例的數值, 一個這樣型別的欄位將不會把輸入數值轉化成任何特定的比例, 而帶有比例宣告的 numeric 欄位將把輸入值轉化為該比例。 (SQL標準要求預設的比例是 0。也就是轉化成整數精度。 我們覺得這樣做有點沒用。如果你關心移植性,那你最好總是明確宣告精度和比例。)

如果一個要儲存的數值的比例比欄位宣告的比例高, 那麼系統將嘗試圓整(四捨五入)該數值到指定的小數位。 然後,如果小數點左邊的資料位數超過了宣告的精度減去宣告的比例, 那麼丟擲一個錯誤。

數值資料值物理上是不帶任何前導或者字尾零的形式儲存的。 因此,欄位上宣告的精度和比例都是最大值,而不是固定分配的。 (在這個方面,numeric 型別更類似於 varchar(n), 而不像 char(n)。) 實際儲存是每四個十進位制位兩個位元組,然後在整個資料上加上八個位元組的額外開銷。

除了普通的數字值之外,numeric 型別允許特殊值 NaN, 表示”不是一個數字”。任何在 NaN 上面的操作都生成另外一個 NaN。 如果在 SQL 命令裡把這些值當作一個常量寫,你必須在其周圍放上單引號,比如 UPDATE table SET x = ‘NaN’。在輸入時,字串 NaN 當作大小寫無關看待。

型別 decimal 和 numeric 是等效的。 兩種型別都是SQL標準。

3. 浮點數型別

資料型別 real 和 double precision 是不準確的,變精度的數字型別。 實際上,這些型別是 IEEE 標準 754 二進位制浮點數算術(分別對應單和雙精度)的一般實現, 外加下層處理器,作業系統和編譯器對它的支援。

不準確意味著一些數值不能準確地轉換成內部格式並且是以近似的形式儲存的,因此儲存然後把資料再打印出來可能顯示一些缺失。 處理這些錯誤以及這些錯誤是如何在計算中傳播的屬於數學和電腦科學的一個完整的分支, 我們不會在這裡進一步討論它,這裡的討論僅限於如下幾點:

如果你要求準確的計算(比如計算貨幣金額),應使用 numeric 型別。

如果你想用這些型別做任何重要的複雜計算,尤其是那些你對範圍情況(無窮,下溢)嚴重依賴的事情,那你應該仔細評詁你的實現。

拿兩個浮點數值進行相等性比較可能象,也可能不象想像那樣運轉。

通常,real 型別的範圍是至少 -1E+37 到 +1E+37, 精度至少是 6 位小數。double precision 型別通常有 -1E+308 到 +1E+308 的範圍,精度是至少 15 位數字。太大或者太小的數值都會導致錯誤。 如果輸入資料太高,那麼可能發生園整。太接近零的數字,如果無法與零值的表現形式相區分就會產生下溢錯。

除了普通的數字值之外,浮點型別還有幾個特殊值:

Infinity
-Infinity
NaN

這些值分別表示 IEEE 754 特殊值”正無窮大”,”負無窮大”, 以及”不是一個數字”。(在不遵循 IEEE 754 浮點算術的機器上,這些值的含義可能不是預期的。) 如果在 SQL 命令裡把這些數值當作常量寫,你必須在它們周圍放上單引號, 像這樣 UPDATE table SET x = ‘Infinity’。 輸入時,這些值是以大小寫無關的方式識別的。
PostgreSQL 還支援 SQL 標準表示法 float 和 float(p) 用於宣告非精確的數值型別。 在這裡,p 宣告以二進位制位表示的最低可接受精度。 在選取 real 型別的時候,PostgreSQL 接受 float(1) 到 float(24),在選取 double precision 的時候,接受 float(25) 到 float(53)。在允許範圍之外的 p 值將導致一個錯誤。 沒有宣告精度的 float 將被當作是 double precision。

注意: 在 PostgreSQL 7.4 以前,在 float(p) 裡面的精度會被當作是這麼多位數的十進位制位。到 7.4 已經被修改成與 SQL 標準匹配,標準宣告這個精度是以二進位制位度量的。假設 real 和 double precision 分別有 24 和 53 個二進位制位的位數對 IEEE 標準的浮點實現來說是正確的。 在非 IEEE 平臺上,這個數值可能略有偏差,但是為了簡化,我們在所有平臺上都用了同樣的 p 值範圍。

3.1 問題:精度無緣無故丟失

這個預設建表語句不能指定經度,很奇怪,我設計 zbx float8(30,20) 表示儲存地理位置資訊(),經度,22.99865252707371,但是會預設為22.99865252707371後面的一個1無法儲存,而且變成

這裡寫圖片描述

這裡沒有小數點數。

4. Serial(序號)型別

serial 和 bigserial 型別不是真正的型別, 只是為在表中設定唯一標識做的概念上的便利。(類似其它一些資料庫中的 AUTO_INCREMENT 屬性)。 在目前的實現中,下面一句話:

CREATE TABLE tablename (
colname SERIAL
);
等價於宣告下面幾句話:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename(
colname integer DEFAULT nextval(‘tablename_colname_seq’) NOT NULL
);
因此,我們就建立了一個整數字段並且把它的預設數值安排為從一個序列發生器取值。 應用了一個 NOT NULL 約束以確保空值不會被明確地插入。 在大多數情況下你可能還希望附加一個 UNIQUE 或者 PRIMARY KEY 約束避免意外地插入重複的數值,但這個不是自動發生的。

注意: 在 PostgreSQL 7.3 以前,serial 隱含 UNIQUE。但現在不再如此。 如果你希望一個序列欄位有一個唯一約束或者一個主鍵,那麼你現在必須宣告,就像其它資料型別一樣。

要使用 serial 欄位插入序列的下一個數值到表中, 主要是要注意 serial 應該賦予預設值。 我們可以通過在 INSERT 語句中把該欄位排除在欄位列表之外來實現, 也可以通過使用 DEFAULT 關鍵字來實現。

型別名 serial 和 serial4 是等效的: 兩個都建立 integer 欄位。型別名 bigserial 和 serial8 也一樣,只不過它建立一個 bigint 欄位。 如果你預計在表的生存期中使用的標識數目超過 231 個,那麼你應該使用 bigserial。

一個 serial 型別建立的序列在所屬的欄位被刪除的時候自動刪除,其它情況下是不會被刪除的。 (這一點在 PostgreSQL 版本 7.3 之前可不是真的。請注意,這種自動刪除的關聯在通過過載 7.3 以前的資料庫轉儲的時候可不會自動發生; 那樣的轉儲檔案不包含需要建立這種關聯關係的資訊。) 另外,這樣的序列和欄位之間的依賴性只在 serial 欄位本身上有; 如果任何其它欄位引用了序列(可能是手工呼叫 nextval 函式), 那麼,如果這個序列被刪除了,它們就會被破壞。我們認為這樣使用 serial 欄位是一種不好的形式;如果你想用同一個序列發生器給幾個欄位喂資料,那麼還是把序列發生器作為獨立物件建立。