限制特定用户的行的最佳方法是什么?

时间:2016-11-01 04:39:26

标签: sql

我正在构建一个应用程序,其中用户(已在另一个表中)可以拥有一组他们可以邀请到该位置的访问者。限制每个用户的行数(在访问者表中)的最佳方法是什么?

感谢您的建议。

1 个答案:

答案 0 :(得分:0)

我建议 在数据库架构中处理此问题。相反,请在data model

中处理它

经验法则是 将业务规则强制执行到架构中;他们经常变化。相反,架构应该强制数据的完整性。例如,架构应确保每个邀请都与邀请用户,受邀用户和事件相关联。如果其中任何一个消失,邀请就会消失。这正在保护数据完整性。业务规则类似于“名称长度只能为20个字符”,鼓励过度使用name varchar(20)之类的内容。

相反,请在数据模型中强制执行规则,例如User.add_invitation。随着业务规则的变化,这将更容易修改,它将为尝试添加邀请失败的原因提供更好的错误消息,并且它将允许具有不同规则的不同应用程序使用相同的模式。

这假设更改数据库将通过一个模型。如果您有代码对数据库进行无可置疑的更改,那么在一个地方对业务规则进行编码可能是务实的:架构。

你没有说你正在使用什么数据库,所以我会为你做出一个很好的决定并假设它是Postgres。它具有很好的触发和约束功能。 (我看到你在MS SQL Server上,代码应该非常相似。)

如果您决定在架构中执行此操作,那么如果邀请太多,您可能需要before insert trigger raises an exception

假设您有一个包含用户,事件和邀请的架构。

create table users (
    id bigserial primary key,
    name text not null,
    ...whatever...
);

create table events (
    id bigserial primary key,
    ...whatever...
);

create table event_invitations (
    host     bigint references user(id),
    guest    bigint references user(id),
    event    bigint references events(id)
);

每个用户一次只能邀请10个人参加活动。为此,如果已有10个邀请,您将使用before insert触发器来阻止插入。我的pl/pgsql有点生疏,但它是这样的:

create function limit_event_invitations_to()
returns trigger as $$
declare
    invitations_count integer;
begin
    select count(*) into invitations_count
    from event_invitations
    where host = NEW.host and event = NEW.event;

    if invitations_count > TG_ARGV[0] then
        raise 'User %d has too many invitations to event %d', NEW.host, NEW.event
          using errcode = 'check_violation';
    end if;

    return NEW;
end;
$$ language plpgsql;

create trigger limit_event_invitations
before insert on event_invitations
for each row execute procedure limit_event_invitations_to(10);

基本上计算一个用户已经为一个事件发出了多少个邀请,如果它超过了限制,则会引发异常。这应该非常快,因为它只是索引外键查找。

我选择使用the check_violation error code因为它与你正在做的最接近。这使您可以检测特定类型的异常,而无需解析错误消息。