【问题标题】:How to insert values in one column with respect to the value of other column of a table如何相对于表的另一列的值在一列中插入值
【发布时间】:2016-07-23 20:12:35
【问题描述】:

我有下表result

roll integer 
c_id varchar(20)
marks number(6,2)
grade varchar(6)
gpa number(3,2)
cgpa number(3,2)
year varchar(10)
term varchar(10)

还有coursesstudent 表。我已经在result表中输入了课程的分数,并想在成绩栏中分配相应的成绩。我想在成绩栏中插入 A+ 表示大于或等于 240 的分数,A 表示大于等于 210 且小于 240 的分数。

我该怎么做?

这里是 DDL:

drop table result;
drop table courses;
drop table student;
create table student(
roll number(10),
fname varchar(30),
lname varchar(30),
department varchar(50)
);
ALTER TABLE student ADD PRIMARY KEY (roll)

create table courses(
c_id varchar(30) NOT NULL,
c_name varchar(30), 
credit integer CHECK(credit>0 and credit<5)
);    
ALTER TABLE COURSES ADD PRIMARY KEY (c_id)
ALTER TABLE COURSES ADD UNIQUE KEY (c_id)
create table result(
roll number(10),
c_id varchar(30),
marks number (6,2),
year varchar (10),
term varchar (10),
gpa number(3,2),
cgpa number(3,2),
grade varchar (4)
);
ALTER TABLE result ADD FOREIGN KEY (roll) REFERENCES student(roll)
ALTER TABLE result ADD FOREIGN KEY (c_id) REFERENCES courses(c_id)

这是结果数据:

insert into result (roll,c_id,marks,year,term) values (1307019,'cse 3103',200,'2nd','1st');
insert into result (roll,c_id,marks,year,term) values (1307019,'cse 3105',210,'2nd','1st');
insert into result (roll,c_id,marks,year,term) values (1307019,'cse 3107',190,'2nd','1st');

【问题讨论】:

  • 为什么要在同一张表的同一列上同时添加主键和唯一键?您应该(可能)在results 上添加一个复合主键,来自roll, c_id, year, term。那么 - 为什么将“gpa”保留在保存个别课程成绩的同一张表中?应该计算“gpa”,而不是存储。

标签: database oracle


【解决方案1】:

您可以使用带有条件表达式的update 语句来更改现有数据并填充grade 列。

这应该可行:

update result 
set grade = 
  case 
    when marks >= 240 then 'A+'
    when marks >= 210 and marks < 240 then 'A'
    -- continue adding more clauses below
    -- else 'B' -- maybe a default value?
  end;

【讨论】:

  • @ashik 我不知道。您收到任何错误消息吗?
  • @ashik 也许是个愚蠢的问题,但您是否在选择之前执行更新?
【解决方案2】:

试试这个数据库复合触发器

这里我给你数据库触发器,当你插入或更新记录时,它会在表上触发,这可以在特定条件下完成

CREATE OR REPLACE TRIGGER trg_result
  FOR INSERT OR UPDATE ON result
  COMPOUND TRIGGER
  BEFORE EACH ROW IS
  BEGIN
    CASE

      WHEN INSERTING OR UPDATING THEN
        :NEW.GRADE := (CASE
                        WHEN :NEW.marks >= 240 THEN
                         'A+'
                        WHEN :NEW.marks >= 210 and :NEW.marks < 240 THEN
                         'A'
                        ELSE
                         'B'
                      END);

    END CASE;
  END BEFORE EACH ROW;

END trg_result;

触发器的主要好处是我们可以在您的示例中插入和更新时自动更新分数,这取决于标记。

创建触发器后再次触发您的插入语句并查看结果。您的成绩列作为指定条件插入。

复合触发器的完整描述在这里

https://oracle-base.com/articles/11g/trigger-enhancements-11gr1

我希望这会有所帮助。

【讨论】:

  • 如果我们使用更新,那么它必须在数据更改时再次触发。
【解决方案3】:

有两种自然的方法可以做到这一点。为了说明我简化了问题(在原始问题的 cmets 中,我指出了一些应该在设置中更改的事情)。

虚拟列方法:

create table results (
roll number,
c_id number,
mark number(6,2),                      -- why "marks"? it should be "mark"
grade varchar(6) as (                  -- oversimplified, change as needed
     case when mark >= 240 then 'A+'
          when mark >= 210 then 'A'
          else                  'F--'
          end
   )
);

在这种安排中,您只插入 roll, c_id, s_id, mark 的值 - 如果您尝试同时输入 grade 的值,您将收到一条错误消息。像这样使用:

SQL> insert into results (roll, c_id, mark) values (322245, 316, 235);

1 row created.

SQL> insert into results (roll, c_id, mark) values (322673, 316, 190);

1 row created.


SQL> select * from results;

      ROLL       C_ID       MARK GRADE
---------- ---------- ---------- ------
    322245        316        235 A
    322673        316        190 F--

2 rows selected.

这种方法的最大缺点是不同字母等级的断点直接硬编码在表定义中。

更好的方法是:

查看

使用c_id, year, term 和每个字母等级的最低要求分数创建一个单独的表。这是与results 表分开维护的。

然后创建一个 VIEW 连接 results 表和这个辅助表来计算标记的字母等级,连接 c_id, year, term 和一个更复杂的条件 mark

不确定 OP 想走那么远;如果需要,我可以发布此方法的简单实现。

【讨论】:

    猜你喜欢
    • 2021-12-22
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 2021-05-11
    相关资源
    最近更新 更多