PostgreSQL 9.2 新特性之:范圍類型 (Range Types)

jopen 13年前發布 | 32K 次閱讀 PostgreSQL 數據庫服務器

PostgreSQL 9.2 的一項新特性就是范圍類型 range types,通過這個名字你可以輕松猜出該類型的用途,它可讓你為某列數據定義數值范圍。

這個簡單的特性可以讓我們不需要定義兩個字段來描述數值的開始值和結束值,一個最直觀的例子就是:

postgres# CREATE TABLE salary_grid (id int, position_name text, start_salary int, end_salary int);
CREATE TABLE
postgres# INSERT INTO salary_grid VALUES (1, 'junior developper', 20000, 30000);
INSERT 0 1
postgres# INSERT INTO salary_grid VALUES (2, 'senior developper', 28000, 35000);
INSERT 0 1
postgres# INSERT INTO salary_grid VALUES (3, 'postgres developper', 50000, 70000);
INSERT 0 1

這個簡單的關系用于存儲一個給定的職位和待遇的范圍(你還需要確定工資的貨幣單位),重要的是你必須實現一些系統函數或者外部程序 API 來執行例如范圍的交叉或者聯合。

Postgres 9.2 允許你的應用直接在數據庫端實現范圍值,范圍類型包括:

  • 4 位整數范圍, int4range
  • 8 位整數范圍, int8range
  • 數值范圍, numrange
  • 無時區的時間戳范圍, tsrange
  • 帶時間戳的時間范圍, tstzrange
  • 日期范圍, daterange
  • </ul>

    你也可以定義自己的范圍類型,Postgre 官網文檔給出了 float 的示例:

    postgres# CREATE TYPE floatrange AS RANGE (
    postgres# subtype = float8,
    postgres# subtype_diff = float8mi);
    有了這樣一個功能,我們前面提到的工資表格例子就可以改為:
    postgres=# create table salary_grid (id int, position_name text, salary_range int4range);
    CREATE TABLE
    postgres=# INSERT INTO salary_grid VALUES (1, 'junior developper', '[20000, 30000]');
    INSERT 0 1
    postgres=# INSERT INTO salary_grid VALUES (2, 'senior developper', '[28000, 35000]');
    INSERT 0 1
    postgres=# INSERT INTO salary_grid VALUES (3, 'postgres developper', '[50000, 70000]');
    INSERT 0 1
    postgres=# select * from salary_grid;
    id | position_name | salary_range
    ----+---------------------+---------------
    1 | junior developper | [20000,30001)
    2 | senior developper | [28000,35001)
    3 | postgres developper | [50000,70001)
    (3 rows)

    很重要的一點是,如果使用的是括號(),元組數據的上界是排除在外的,而中括號[]則上界包含其中。

    數據庫本身也包含不同的用于處理范圍類型的函數。

    你可直接獲取一個給定范圍的最低和最高值:

    postgres=# SELECT upper(salary_range), lower(salary_range) FROM salary_grid;
    upper | lower
    -------+-------
    30001 | 20000
    35001 | 28000
    70001 | 50000
    (3 rows)
    你可以檢查某個值是否包含在給定范圍內:
    postgres=# SELECT salary_range @> 4000 as check
    postgres=# FROM salary_grid
    postgres=# WHERE position_name = 'junior developper';

    check

    f (1 row)</pre>

    這里顯示 4000 并不包含在初級職位的待遇里 [20000,30000].

    這里稍微復雜了一些,你還可以檢查兩個范圍之間的重疊的部分,這里的 salary_range 使用的是 int4,因此 int4range 函數可用于此操作:

    postgres=# WITH junior_salary AS (
     SELECT salary_range as junior
     FROM salary_grid
     WHERE position_name = 'junior developper'),
    senior_salary AS (
     SELECT salary_range as senior
     FROM salary_grid
     WHERE position_name = 'senior developper')
    SELECT int4range(junior) && int4range(senior) as check
     FROM junior_salary, senior_salary;

    check

    t (1 row)</pre>

    這里顯示的是初級和高級職位之間的工資重疊部分。

    你還可以設定無上下限的范圍類型,或者是只有上限或者下限的范圍類型,讓我們來看一個非常現實的例子:

    postgres# UPDATE salary_grid SET salary_range = '[50000,)' WHERE position_name = 'postgres developper';
    UPDATE 0 1
    postgres=# SELECT salary_range @> 60000000 as check
    postgres-# FROM salary_grid WHERE position_name = 'postgres developper';

    check

    t (1 row)</pre>

    你可以使用 lower_inf 或者 upper_inf 來檢查范圍的無限值。

    Postgres 還有其他一些內嵌的函數(如 isempty),這個可以直接從官方文檔中獲取詳細信息。


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!