SQL,限制可以添加内容的时间

时间:2019-11-21 13:01:41

标签: sql postgresql

我已经使用Postgresql建立了图书馆管理系统,我想限制学生/员工可以借阅的书籍数量。如果某人想添加一个新的元组,而学生/员工已经借了一本书,而该特定用户已经借了例如7本书,则该表格将不接受其他添加。

3 个答案:

答案 0 :(得分:1)

根据我的说法,您需要从业务逻辑的角度进行处理,即在插入之前检索特定学生的数据,然后采取行动

从基于规则的角度看

  1. 不要等待应用程序插入任何其他行,而是不断观察表中的计数,一旦达到计数,db就会通知应用程序。
  2. 您可以根据以下内容调用/触发存储过程: 如果count_num_books> 7,则特定用户拍摄的图书数量 然后,应用程序将对其进行处理。

请查看他们的文档中提到的ON CONFLICT

http://www.postgresqltutorial.com/postgresql-upsert/

您可以创建一个存储过程,并在发生冲突时插入,并采取相应的措施。

INSERT INTO table_name(column_list) VALUES(value_list)
ON CONFLICT target action;

答案 1 :(得分:0)

通常,SQL并不容易做到这一点。典型的解决方案是这样的:

  • 保持一张桌子,每借一本书和一个学生一行。
  • students表中保留大量优秀图书。
  • 使用触发器维护此计数。
  • 在计数上添加检查约束。

Postgres确实有更方便的方法。一种方法是将借用书的列表存储为数组或JSON结构。 ,,这不是关系格式。而且,它不允许声明外键约束。

也就是说,它确实允许在check列上使用简单的books_borrowed约束-例如使用cardinality()。而且,验证数组中没有重复项并不容易。另外,INSERTUPDATEDELETE s更加复杂。

对于您的特定问题,我建议采用第一种方法。

答案 2 :(得分:0)

如上所述,这是进行APPLICATION检查的最佳位置。但是,否则,在这种情况下,最简单的方法什么都不做-即不要尝试保持运行中的活动签出总数。由于Postgres不会从触发器表中选择触发器来触发触发器,因此只需导出已签出的未完成的书即可。以下假设存在一个签出表,如下所示:

create table checkouts    
     ( checkout_id          serial
     , student_employee_id  integer not null
     , book_id              integer not null
     , out_date             date    not null
     , return_date          date    default null
     ) ; 

然后在此表上创建一个插入行触发器,并调用以下命令:

 create or replace function limit_checkouts()
   returns trigger 
   language plpgsql
 as $$
 declare
    checkout_count integer; 
 begin
    select count(*)
      into checkout_count
      from checkouts c
     where c.student_employee_id = new.student_employee_id
       and returned_date is null ;

    if checkout_count > 7
    then 
        raise exception 'Checkout limit exceeded';
    end if;

    return new;
end; 
$$;