【问题标题】:How to design a user/role schema in a SQL Server database?如何在 SQL Server 数据库中设计用户/角色架构?
【发布时间】:2012-06-08 09:33:57
【问题描述】:

我想设计一个用户/角色系统:

用户拥有名称和密码,然后用户可以拥有多个角色,例如Admin

为此,我创建了这样的架构:

用户:

CREATE TABLE [dbo].[Users]
(
    [id] [int] NOT NULL,
    [name] [nvarchar](50) NULL,
    [password] [nvarchar](50) NULL,

    CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ([id] ASC)
)

角色:

CREATE TABLE [dbo].[Roles]
(
    [id] [int] NOT NULL,
    [name] [nvarchar](50) NULL,

    CONSTRAINT [PK_Roles] PRIMARY KEY CLUSTERED ([id] ASC)
)

用户角色:

CREATE TABLE [dbo].[User_Roles]
(
    [id] [int] NOT NULL,
    [User_id] [int] NOT NULL,
    [Role_id] [int] NOT NULL,

    CONSTRAINT [PK_User_Roles] PRIMARY KEY CLUSTERED ([id] ASC)
)

我的问题是:我应该使用外键User_Roles.User_id -> User.Id

如果是,为什么?

【问题讨论】:

  • 是的! 当然你应该有外键。你为什么问?? FK 有助于确保数据一致性 - 如果没有 FK,您可以将任何类型的 id 存储到您的 user_roles 表中 - 无需检查它们是否引用有效的用户和/或角色 - 这不是您想要的去做(而不是你以后想清理的事情!)

标签: sql-server


【解决方案1】:

不太清楚你的意思,但是...

  • User_Roles 应该只有 2 列 User_idRole_id
    这两者都构成了主键
  • 您不需要额外的 id 列 User_Roles
  • User_idUsers.id 的外键
  • Role_idRoles.id 的外键

编辑:现在我明白了。是的,always use foreign keys

还有……

  • 如果passwordnvarchar(50),这意味着纯文本。 This is bad.
  • 如果您在Users 中有重复的name 值,您如何知道哪个用户是哪个?
    特别是如果他们有相同的密码(这会发生,因为我们肉袋是愚蠢的)

主键创建后评论后编辑...

CREATE TABLE [dbo].[User_Roles]
(
    [User_id] [int] NOT NULL,
    [Role_id] [int] NOT NULL,

    CONSTRAINT [PK_User_Roles] PRIMARY KEY CLUSTERED ([User_id], [Role_id]),
    CONSTRAINT [UQ_ReversePK] UNIQUE ([Role_id], [User_id])
)

【讨论】:

  • 密码和用户名仅用于演示,不是纯文本。我的重点是角色系统
  • user_roles中如何设置主键?
  • 为什么首先使用User_Roles association tableUsers.idRoles 表中存在作为外键还不够吗?
  • @Jens:用户可以有多个角色,角色可以有多个用户?您的建议意味着“每个角色只有一个用户”
【解决方案2】:

Spring Security 提出this 推荐:

create table users(
    username varchar_ignorecase(50) not null primary key,
    password varchar_ignorecase(50) not null,
    enabled boolean not null
);

create table authorities (
    username varchar_ignorecase(50) not null,
    authority varchar_ignorecase(50) not null,
    constraint fk_authorities_users foreign key(username) references users(username)
);
create unique index ix_auth_username on authorities (username,authority);

【讨论】:

    【解决方案3】:

    在数据建模关系时始终使用外键。在您的示例中,如果您不创建外键,则没有什么可以阻止您(或其他有权访问数据库的人)错误地(或故意)删除当前使用的角色。

    假设您有很多用户和几个角色。其中一个角色称为“管理员”,在您的应用程序中需要它才能执行某些任务。如果您没有设置外键,则数据库中没有任何内容可以阻止某人删除管理员角色,从而导致您的应用程序:

    • 可能会崩溃,因为它会寻找不再在数据库中的角色
    • 如果不是上述情况,那么至少没有用户将拥有“管理员”角色,从而关闭需要它的应用程序部分

    另一方面,如果您已经设置了外键,如果您尝试删除当前分配给某个用户的角色(通​​过 User_Roles 表),您将收到来自数据库的错误。

    【讨论】:

      【解决方案4】:

      与@GBN 略有不同的最佳方法之一是:

      我希望这对您或其他人有所帮助

      CREATE TABLE [dbo].[UserRoles](
          [roleId] [int] NOT NULL,
          [userId] [int] NOT NULL,
          [CreateDate] [datetime] NULL,
          [CreateUser] [nvarchar](30) NULL,
          [ModifyDate] [datetime] NULL,
          [ModifyUser] [nvarchar](30) NULL,
       CONSTRAINT [PK_User_Roles] PRIMARY KEY CLUSTERED 
      (
          [roleId] ASC,
          [userId] ASC
      )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
       CONSTRAINT [UQ_ReversePK] UNIQUE NONCLUSTERED 
      (
          [roleId] ASC,
          [userId] ASC
      )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
      ) ON [PRIMARY]
      GO
      
      ALTER TABLE [dbo].[UserRoles] ADD  CONSTRAINT [DF_UserRoles_ModifyDate]  DEFAULT (getdate()) FOR [ModifyDate]
      GO
      
      ALTER TABLE [dbo].[UserRoles]  WITH CHECK ADD  CONSTRAINT [FK_UserRoles_roleId] FOREIGN KEY([roleId])
      REFERENCES [dbo].[Roles] ([roleId])
      GO
      
      ALTER TABLE [dbo].[UserRoles] CHECK CONSTRAINT [FK_UserRoles_roleId]
      GO
      
      ALTER TABLE [dbo].[UserRoles]  WITH CHECK ADD  CONSTRAINT [FK_UserRoles_userId] FOREIGN KEY([userId])
      REFERENCES [dbo].[Users] ([uId])
      GO
      
      ALTER TABLE [dbo].[UserRoles] CHECK CONSTRAINT [FK_UserRoles_userId]
      GO
      

      【讨论】:

        【解决方案5】:

        users_roles 表应包含每个用户及其角色之间的映射。每个用户可以有多个角色,每个角色可以有多个用户:

        TABLE users
          id INTEGER NOT NULL PRIMARY KEY,
          userName VARCHAR(50) NOT NULL
        
        TABLE roles
          id INTEGER NOT NULL PRIMARY KEY,
          role VARCHAR(20) NOT NULL
        
        CREATE TABLE users_roles (
          userId INTEGER NOT NULL,
          roleId INTEGER NOT NULL,
          primary key (userId, roleId),
          foreign key (userId) references users(id),
          foreign key (roleId) references roles(id)
        );
        

        【讨论】:

          猜你喜欢
          • 2012-03-08
          • 2010-11-12
          • 2014-11-26
          • 2010-12-12
          • 2011-10-15
          • 2012-03-08
          • 2021-04-01
          • 2011-01-06
          • 1970-01-01
          相关资源
          最近更新 更多