视图中缺少PostgreSQL数据

时间:2016-11-10 15:53:58

标签: database postgresql stored-procedures view dynamic-columns

因为 PostgreSQL 不支持动态计算的表列,所以克服此限制的一种可能方法是使用在this问题的答案中指出的视图。我尝试以下列方式实现此类视图:

CREATE VIEW user_info_view AS
  SELECT *,
         calculate_bonus_points_for_period(user_info.id) AS bonus_points_period,
         calculate_user_level(user_info.id) AS level
  FROM user_info;

user_info表如下:

CREATE TABLE user_info
(
  id                  serial     PRIMARY KEY,
  card_id             text       NOT NULL UNIQUE,
  name                text       NOT NULL,
  address             text       NOT NULL,
  phone               text       NOT NULL,
  bank_credit         bigint     NOT NULL,
  deposit             bigint     NOT NULL,
  bonus_points        bigint     NOT NULL
);

用于计算视图列的2个函数如下:

CREATE TYPE user_level AS ENUM ('bronze', 'gold', 'platinum');

----------------------------------------------------------------------

CREATE FUNCTION calculate_bonus_points_for_period(user_id integer)
  RETURNS bigint AS
$BODY$
  DECLARE
    bonus_period smallint;
    result       bigint;
  BEGIN
    SELECT settings.bonus_period INTO bonus_period FROM settings;

    SELECT sum(bonus_points_earned) INTO result FROM game_pledges
    WHERE game_pledges.user_id = calculate_bonus_points_for_period.user_id AND
          ts > current_date - interval '1 day' * bonus_period;

    RETURN COALESCE(result, 0);
  END;
$BODY$
  LANGUAGE plpgsql;

----------------------------------------------------------------------

CREATE FUNCTION calculate_user_level(user_id integer)
  RETURNS user_level AS
$BODY$
  DECLARE
    bonus_points_period    bigint;
    bronze_gold_boundery   bigint;
    gold_platinum_boundery bigint;
  BEGIN
    SELECT user_info_view.bonus_points_period
    INTO   bonus_points_period
    FROM   user_info_view
    WHERE  user_id = id;

    SELECT settings.bronze_gold_boundery   INTO bronze_gold_boundery   FROM settings;
    SELECT settings.gold_platinum_boundery INTO gold_platinum_boundery FROM settings;

    IF    bonus_points_period >= gold_platinum_boundery THEN
      RETURN 'platinum';
    ELSIF bonus_points_period >= bronze_gold_boundery   THEN
      RETURN 'gold';
    ELSE
      RETURN 'bronze';
    END IF;
  END;
$BODY$
  LANGUAGE plpgsql;

我在user_info表中有数据,但是当我用pgAdmin打开它时,视图为空。一开始,我在game_pledges表格中有数据,我希望sum0。有人可以解释为什么视图是空的吗?我期望与user_info表中的行数相同。

后记:

当我执行SELECT count(*) FROM user_info_view;时,我发现我的功能有些含糊不清。我纠正了上面的代码并解决了歧义问题,但现在又出现了另一个错误:

ERROR:  stack depth limit exceeded
HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
CONTEXT:  SQL statement "SELECT sum(bonus_points_earned)             FROM game_pledges
    WHERE game_pledges.user_id = calculate_bonus_points_for_period.user_id AND
          ts > current_date - interval '1 day' * bonus_period"

0 个答案:

没有答案