Oracle index by table(Associative array) used in PostgreSQL

Postgres2015全國用戶大會將於11月20至21日在北京麗亭華苑酒店召開。本次大會嘉賓陣容強大,國內頂級PostgreSQL數據庫專家將悉數到場,並特邀歐洲、俄羅斯、日本、美國等國家和地區的數據庫方面專家助陣:

  • Postgres-XC項目的發起人鈴木市一(SUZUKI Koichi)
  • Postgres-XL的項目發起人Mason Sharp
  • pgpool的作者石井達夫(Tatsuo Ishii)
  • PG-Strom的作者海外浩平(Kaigai Kohei)
  • Greenplum研發總監姚延棟
  • 周正中(德哥), PostgreSQL中國用戶會創始人之一
  • 汪洋,平安科技數據庫技術部經理
  • ……
 
2015年度PG大象會報名地址:http://postgres2015.eventdove.com/PostgreSQL中國社區: http://postgres.cn/PostgreSQL專業1羣: 3336901(已滿)PostgreSQL專業2羣: 100910388PostgreSQL專業3羣: 150657323


Oracle plSQL中支持3種集合變量, index-by table, varray, nest table。
Oracle index by table(Associative array) used in PostgreSQL - 德哥@Digoal - PostgreSQL research
其中index-by table是不限元素個數,支持字符串或INT下標。
用法舉例:

DECLARE
  -- Associative array indexed by string:
  
  TYPE population IS TABLE OF NUMBER  -- Associative array type
    INDEX BY VARCHAR2(64);            --  indexed by string
  
  city_population  population;        -- Associative array variable
  i  VARCHAR2(64);                    -- Scalar variable
  
BEGIN
  -- Add elements (key-value pairs) to associative array:
 
  city_population('Smallville')  := 2000;
  city_population('Midland')     := 750000;
  city_population('Megalopolis') := 1000000;
 
  -- Change value associated with key 'Smallville':
 
  city_population('Smallville') := 2001;
 
  -- Print associative array:
 
  i := city_population.FIRST;  -- Get first element of array
 
  WHILE i IS NOT NULL LOOP
    DBMS_Output.PUT_LINE
      ('Population of ' || i || ' is ' || city_population(i));
    i := city_population.NEXT(i);  -- Get next element of array
  END LOOP;
END;
/
Result:

Population of Megalopolis is 1000000
Population of Midland is 750000
Population of Smallville is 2001
Example 5-2 defines a type of associative array indexed by PLS_INTEGER and a function that returns an associative array of that type.

Example 5-2 Function Returns Associative Array Indexed by PLS_INTEGER

DECLARE
  TYPE sum_multiples IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;
  n  PLS_INTEGER := 5;   -- number of multiples to sum for display
  sn PLS_INTEGER := 10;  -- number of multiples to sum
  m  PLS_INTEGER := 3;   -- multiple

  FUNCTION get_sum_multiples (
    multiple IN PLS_INTEGER,
    num      IN PLS_INTEGER
  ) RETURN sum_multiples
  IS
    s sum_multiples;
  BEGIN
    FOR i IN 1..num LOOP
      s(i) := multiple * ((i * (i + 1)) / 2);  -- sum of multiples
    END LOOP;
    RETURN s;
  END get_sum_multiples;

BEGIN
  DBMS_OUTPUT.PUT_LINE (
    'Sum of the first ' || TO_CHAR(n) || ' multiples of ' ||
    TO_CHAR(m) || ' is ' || TO_CHAR(get_sum_multiples (m, sn)(n))
  );
END;
/
Result:

Sum of the first 5 multiples of 3 is 45

在PostgreSQL plpgsql函數中對應的用法:
PostgreSQL中不需要指定數組長度,可以存儲任意個元素。
但是不能使用字符串下標。

postgres=# create table t1(id int,info text);
CREATE TABLE

postgres=# do language plpgsql $$
declare
  v _t1; -- _t1表示t1表的數組類型
  v1 t1; 
begin
  v1.id := 10; 
  v1.info := 'abc'; 
  v[1] := v1;
  v[2] := '(11,"hello")';
  v1.id := 100;
  v1.info := 'i am digoal';
  v[3] := v1;
  foreach v1 in array v loop
    raise notice '%, %, %', v1, v1.id, v1.info;
  end loop;
end;
$$;
NOTICE:  00000: (10,abc), 10, abc
LOCATION:  exec_stmt_raise, pl_exec.c:3074
NOTICE:  00000: (11,hello), 11, hello
LOCATION:  exec_stmt_raise, pl_exec.c:3074
NOTICE:  00000: (100,"i am digoal"), 100, i am digoal
LOCATION:  exec_stmt_raise, pl_exec.c:3074
DO

如果要存儲非結構化數據,可以使用jsonb或者hstore和數組的組合。
不過目前在plpgsql中只能對非結構化數據一次性賦值,不能部分賦值。例如:

postgres=# do language plpgsql $$
declare
  v1 hstore := '';
  ky text;
begin
  v1 := v1 || '"a"=>1'::hstore; 
  v1 := v1 || hstore('b', '2'); -- 另一種hstore value寫法
v1 := v1 || '"b"=>100'::hstore; -- 覆蓋或修改b的值
  foreach ky in array akeys(v1) loop
    raise notice '%, %', ky, v1->ky; -- hstore->key 獲取指定key的value
  end loop;
end;
$$;
NOTICE: 00000: a, 1
LOCATION: exec_stmt_raise, pl_exec.c:3074
NOTICE: 00000: b, 100
LOCATION: exec_stmt_raise, pl_exec.c:3074
DO


[參考]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章