创建程序以仅在学生有足够余额的情况下才允许学生注册课程[关闭]

Posted

技术标签:

【中文标题】创建程序以仅在学生有足够余额的情况下才允许学生注册课程[关闭]【英文标题】:Create procedure to allow students to register for a course only if they have enough balance [closed] 【发布时间】:2018-12-22 11:36:11 【问题描述】:

如何创建一个程序,让学生只有在有足够余额的情况下才能注册课程。

带有学生 ID 和课程 ID 参数的过程。 根据学生余额检查他们是否可以注册。

如果我们有这样的表格:

courses

c_id    c_cost  c_name  c_hours
1       30          C#    3
2       50         Java   3
3       40          DB    3

students

sid  S_blance   S_name
1     300       john
2     100       sam
3     20         kim

register table

sid S_name  C_cost  C_name
1   john    30      DB
3   sam     30      DB
1   john    50      Java

【问题讨论】:

欢迎来到 Stack Overflow!这是一个您可以就您编写的软件遇到的问题提出问题并获得答案的网站,但它不是“为我做作业”或“为我做我的工作” “ 地点。当您提出问题时,您应该包含您编写的代码、您遇到的具体错误或您的程序产生的结果以及您预期的结果的解释。没有这些,我们真的无能为力帮助您。请编辑您的问题以显示您所做的事情并告诉我们代码存在哪些问题。再次,欢迎来到 Stack Overflow! 【参考方案1】:

这是一个检查学生余额与课程费用的程序;如果他们的帐户中有足够的资金,则会为该学生注册课程,否则会引发异常。

create or replace procedure register_for_course (
     p_S_id in students.s_id%type
     , p_C_id in courses.c_id%type
     )
is
    l_course courses%rowtype;
    l_student students%rowtype;
begin
    select * into l_course
    from courses c
    where c.c_id = p_c_id;

    select * into l_student
    from students s
    where s.s_id = p_s_id
    for update of s_balance;

    if l_course.c_cost > l_student.s_balance then
        raise_application_error(-20000, 
            'student cannot afford to register for this course');
    end if;

    insert into register 
    values (p_s_id, l_student.s_name, l_course.c_cost, l_course.c_name);

    update  students s  
    set s.s_balance = s.s_balance - l_course.c_cost
    where s.s_id = p_s_id;

    commit;

end;
/

如果您想要一个只进行检查的例程,您可能需要一个返回标志的函数。 Oracle SQL - 与大多数其他 RDBMS 一样 - 不支持 Boolean 数据类型,因此如果您想在 SQL 中使用该函数,它必须返回一个字符串。

create or replace function can_register_for_course (
     p_S_id in students.s_id%type
     , p_C_id in courses.c_id%type
     ) return varchar2
is
    l_course courses%rowtype;
    l_student students%rowtype;
    rv varchar2(1);
begin
    select * into l_course
    from courses c
    where c.c_id = p_c_id;

    select * into l_student
    from students s
    where s.s_id = p_s_id
    for update of s_balance;

    if l_course.c_cost > l_student.s_balance then
        rv := 'N';
    else
        rv := 'Y';
    end if;

    return rv;

end;
/

像这样在单独的函数中检查预订的效率会很低,因为在插入register 表时需要再次查询studentscourses。这是因为该表是非规范化的,具有冗余列。更好的数据模型是register 表,其投影类似于(s_id, c_id),可以巧妙地作为复合主键以及父表的外键强制执行。

【讨论】:

【参考方案2】:

在下面创建存储过程,如果学生可以注册课程,则返回 1,否则返回 0

CREATE PROCEDURE YourProedure (@sid int, @c_id int)
AS
BEGIN
  IF ((SELECT
      S_balance
    FROM students
    WHERE sid = @sid)
    >= (SELECT
      c_cost
    FROM COURSES
    WHERE c_id = @c_id)
    )
    SELECT
      1 Result
  ELSE
    SELECT
      0 Result
END

【讨论】:

这不是 Oracle 语法。 最初的问题是 sql-server 标签。

以上是关于创建程序以仅在学生有足够余额的情况下才允许学生注册课程[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥学生认证后无法使用azure

仅在“-Dorg.apache.sqoop.splitter.allow_text_splitter=true”属性作为参数传递的情况下才允许为文本索引列生成拆分

使用 Python 的 Tkinter,我如何保存数据以仅在该应用程序上使用?

验证以仅在后跟字母时允许空格字符

解析 JWT 令牌以仅在 C# 或 Blazor 中没有外部库的情况下获取有效负载内容

我的查询一直允许我注册现有帐户