使用触发器/过程基于实体的值评估参数

时间:2011-01-28 04:24:32

标签: sql oracle triggers procedure

我有以下问题。在我的应用程序中,用户使用SPECIAL系统(强度,感知等,使用1到10的值)创建游戏角色。在保存或之后(通过调用程序)我需要在SPECIAL参数值的基础上计算字符统计。我怎样才能做到这一点 ?这是关系计划:

enter image description here

这里是SQL代码:

create table Player (
  id_player numeric,
  player_name varchar2(50) not null,
  age decimal not null,
  strength decimal not null,
  perception decimal not null,
  endurance decimal not null,
  charisma decimal not null,
  inteligence decimal not null,
  agility decimal not null,
  luck decimal not null,
  caps decimal not null,
  statistics numeric,
  CONSTRAINT chk_s check (strength <= 10),
  CONSTRAINT chk_p check (perception <= 10),
  CONSTRAINT chk_e check (endurance <= 10),
  CONSTRAINT chk_c check (charisma <= 10),
  CONSTRAINT chk_i check (inteligence <= 10),
  CONSTRAINT chk_a check (agility <= 10),
  CONSTRAINT chk_l check (luck <= 10),
  CONSTRAINT unique_name UNIQUE (player_name),

  CONSTRAINT PLAYER_PK primary key (id_player)
);

create table Player_derived_statistics(
  id_statistics numeric,
  carry_weight decimal,
  hit_points decimal,
  radiation_resistance decimal,

  CONSTRAINT DERIVED_STATISTICS_PK primary key (id_statistics)
);

alter table Player add constraint PLAYER_DERIVED_STATISTICS_FK1 foreign key (statistics) references Player_derived_statistics (id_statistics);

并查询返回所有参数:

SELECT p.strength, p.perception, p.endurance, p.charisma, p.inteligence, p.agility, p.luck
from player p inner join player_derived_statistics s on s.id_statistics = p.statistics;

所以最后我希望能够为每个玩家计算carry_weight,hit_points和radiation_resistance。假设所有公式都是(player_parameter * 10) + 150。什么是更好的使用:触发器或程序?


修改

我正在尝试使用回答中的代码,但我收到错误Encountered the symbol "INNER" when expecting one of the following: ( ...

CREATE OR REPLACE PACKAGE pkg_player_stats AS
  FUNCTION get_derived_stats( p_id_player IN player.id_player%TYPE )
    RETURN derived_stats_rec
  IS
    l_stats_rec derived_stats_rec;
  BEGIN
    SELECT (p.strength*10)+150,
           (p.endurance*20)+150,
           ((p.endurance-1)*2)/100
      INTO l_stats_rec.carry_weight,
           l_stats_rec.hit_points,
           l_stats_rec.radiation_resistance
      FROM (
        SELECT p.strength,  
               p.endurance
          from player p inner join player_derived_statistics s on s.id_statistics = p.statistics);
    RETURN l_stats_rec;
  END get_derived_stats;
END;

2 个答案:

答案 0 :(得分:0)

我绝对不会使用触发器来做这类事情。听起来你想要一个接受ID_PLAYER参数并返回值或值记录的函数。这样的事情(请注意,我不确定我是否理解你所描述的公式所以我猜了一下

CREATE OR REPLACE PACKAGE pkg_player_stats
AS
  TYPE derived_stats_rec IS RECORD (
    carry_weight NUMBER,
    hit_points   NUMBER,
    radiation_resistance NUMBER );

  FUNCTION get_derived_stats( p_id_player IN player.id_player%TYPE )
    RETURN derived_stats_rec;
END;

CREATE OR REPLACE PACKAGE pkg_player_stats
AS
  FUNCTION get_derived_stats( p_id_player IN player.id_player%TYPE )
    RETURN derived_stats_rec
  IS
    l_stats_rec derived_stats_rec;
  BEGIN
    SELECT carry_weight         * multiplier + 150,
           hit_points           * multiplier + 150,
           radiation_resistance * multiplier + 150
      INTO l_stats_rec.carry_weight,
           l_stats_rec.hit_points,
           l_stats_rec.radiation_resistance
      FROM (
        SELECT p.strength + 
               p.perception + 
               p.endurance +
               p.charisma + 
               p.inteligence +
               p.agility +
               p.luck multiplier,
               s.carry_weight,
               s.hit_points,
               s.radiation_resistance
          from player p 
               inner join player_derived_statistics s on s.id_statistics = p.statistics);
    RETURN l_stats_rec;
  END get_derived_stats;
END;

答案 1 :(得分:0)

为什么你需要两张桌子?我会选择

  • 仅包含所有S.P.E.C.I.A.L统计信息的单个表以及计算派生统计信息的视图(在您的应用程序中,您将查询该视图):

    CREATE VIEW player_v AS 
    SELECT p.strength, ..., /* all attributes */
           p.strength * 10 + 150 as carry_weight,
           p.endurance * 20 + 150 as hit_points,
           (p.endurance - 1) * 2 / 100 as radiation_resistance
      FROM player p
    
  • 使用触发器更新的包含派生列的单个表:

    CREATE OR REPLACE TRIGGER player_ins_up_trg 
       BEFORE UPDATE OR INSERT ON player
       FOR EACH ROW
    BEGIN
       :new.carry_weight := :new.strength * 10 + 150;
       :new.hit_points := :new.endurance * 20 + 150;
       :new.radiation_resistance := (:new.endurance - 1) * 2 / 100;
    END;
    
  • 如果您使用的是Oracle 11,还可以使用virtual column

      

    虚拟列未存储在磁盘上。相反,数据库通过计算一组表达式或函数来按需派生虚拟列中的值。

    例如:

    ALTER TABLE player ADD (carry_weight AS (strength * 10 + 150));