检查mySQL中的多个表

时间:2012-04-25 08:54:59

标签: mysql

问题:

我是mySQL的新手,我甚至不知道从哪里开始。我想知道如何编写一个简单的函数,它根据分布在许多表中的值返回true或false。

详细说明:

以下是我的表的相关部分(所有引擎都是innodb)。在您阅读时,您将看到数据库只是为这些用户/组存储用户,组,文件以及这些文件的权限。

USER表

CREATE TABLE IF NOT EXISTS USER
(
   ID                 INT NOT NULL auto_increment,

   PRIMARY KEY(ID)
)

GROUP表:

CREATE TABLE IF NOT EXISTS GROUP
(
   ID           INT NOT NULL AUTO_INCREMENT,

   PRIMARY KEY(ID)
)

GROUP MEMBERSHIP表:

CREATE TABLE IF NOT EXISTS GROUPMEMBERSHIP
(
   ID           INT NOT NULL AUTO_INCREMENT,
   USERID       INT NOT NULL,
   GROUPID      INT NOT NULL,

   UNIQUE ( USERID, GROUPID ),
   PRIMARY KEY(ID),
   FOREIGN KEY (USERID) REFERENCES USER(ID),
   FOREIGN KEY (GROUPID) REFERENCES GROUP(ID)
)

文件表:(R,W,X,适用于other

CREATE TABLE IF NOT EXISTS FILE
(
   ID                 INT NOT NULL AUTO_INCREMENT,
   READ               BOOLEAN DEFAULT FALSE,
   WRITE              BOOLEAN DEFAULT FALSE,
   EXECUTE            BOOLEAN DEFAULT FALSE,

   PRIMARY KEY(ID)
)

FILE USER PERMISSIONS表:

CREATE TABLE IF NOT EXISTS FILEUSERPERMISSIONS
(
   ID           INT NOT NULL AUTO_INCREMENT,
   FILEID       INT NOT NULL,
   USERID       INT NOT NULL,
   READ         BOOLEAN DEFAULT FALSE,
   WRITE        BOOLEAN DEFAULT FALSE,
   EXECUTE      BOOLEAN DEFAULT FALSE,

   UNIQUE (FILEID, USERID),
   PRIMARY KEY(ID),
   FOREIGN KEY (FILEID) REFERENCES FILE(ID),
   FOREIGN KEY (USERID) REFERENCES USER(ID)
)

文件组权限表:

CREATE TABLE IF NOT EXISTS FILEGROUPPERMISSIONS
(
   ID           INT NOT NULL AUTO_INCREMENT,
   FILEID       INT NOT NULL,
   GROUPID      INT NOT NULL,
   READ         BOOLEAN DEFAULT FALSE,
   WRITE        BOOLEAN DEFAULT FALSE,
   EXECUTE      BOOLEAN DEFAULT FALSE,

   UNIQUE (FILEID, GROUPID),
   PRIMARY KEY(ID),
   FOREIGN KEY (FILEID) REFERENCES FILE(ID),
   FOREIGN KEY (GROUPID) REFERENCES GROUP(ID)
)

hasPermission功能:

DELIMITER $$
DROP FUNCTION IF EXISTS hasPermission$$
CREATE FUNCTION hasPermission(fileID INT, userID INT)
RETURNS BOOLEAN
BEGIN
   ???
END$$
DELIMITER ;

我将如何进行,或者至少在哪里开始编写hasPermission函数,以便在查询时如此:

SELECT hasPermission( 123, 456)

执行以下内容:

  1. 检查other
  2. 是否可以读取文件123
  3. 检查用户456是否具有文件123的读取权限
  4. 检查用户456是否在某个具有文件123读取权限的组中
  5. 第一个是非常琐碎的三者中最微不足道的。第二个让我难过。第三个对我来说是一个概念障碍。除此之外,我显然必须检查用户和/或文件是否存在。

    请善待,因为我是MySQL的新手。

    先谢谢你

3 个答案:

答案 0 :(得分:2)

  1. 检查文件123是否可由other

    阅读

    你说这是微不足道的,但为了完整性:

    SELECT READ
    FROM FILE
    WHERE ID = 123;
    
  2. 检查用户456是否具有文件123的读取权限

    您可以使用FILEUSERPERMISSIONS表中的类似查找来执行此操作:

    SELECT READ
    FROM FILEUSERPERMISSIONS
    WHERE FILEID = 123 AND USERID = 456;
    
  3. 检查用户456是否在某个具有文件123读取权限的组中

    要完成此操作,您需要JOIN GROUP MEMBERSHIPFILE GROUP PERMISSIONS表:

    SELECT READ
    FROM FILEGROUPPERMISSIONS JOIN GROUPMEMBERSHIP USING (GROUPID)
    WHERE FILEID = 123 AND USERID = 456;
    

  4. 要将这些组合在一起,您可以这样做:

    SELECT
       (SELECT READ FROM FILE WHERE ID = 123)
    OR (SELECT READ FROM FILEUSERPERMISSIONS WHERE FILEID = 123 AND USERID = 456)
    OR (SELECT READ FROM FILEGROUPPERMISSIONS JOIN GROUPMEMBERSHIP USING (GROUPID)
        WHERE FILEID = 123 AND USERID = 456);
    

答案 1 :(得分:2)

检查文件的权限。我可能会这样做:

SELECT
    (
        CASE WHEN EXISTS
            (
                SELECT
                    NULL
                FROM
                    FILE
                WHERE EXISTS
                    (
                        SELECT
                            NULL
                        FROM
                            USER
                            JOIN GROUPMEMBERSHIP
                                ON GROUPMEMBERSHIP.USERID=USER.ID
                            JOIN FILEUSERPERMISSIONS
                                ON FILEUSERPERMISSIONS.USERID=GROUPMEMBERSHIP.USERID
                            JOIN FILEGROUPPERMISSIONS
                                ON FILEGROUPPERMISSIONS.GROUPID=GROUPMEMBERSHIP.GROUPID
                        WHERE 
                            FILEUSERPERMISSIONS.FILEID=FILE.ID
                            AND FILEGROUPPERMISSIONS.FILEID=FILE.ID
                            AND FILEUSERPERMISSIONS.READ=FILE.READ
                            AND FILEGROUPPERMISSIONS.READ=FILE.READ
                            AND USER.ID=userID
                    )
                WHERE
                    FILE.READ=1
                    AND FILE.ID=fileID
            )
        THEN CAST(1 AS BIT)
        ELSE CAST(0 AS BIT)
        END
    ) AS hasRights

但如果你真的想要重视你的功能。我建议使用表函数,只提供userid。这样您就可以获得用户有权访问的所有文件。这看起来像这样:

SELECT
    ID
FROM
    FILE
WHERE EXISTS
    (
        SELECT
            NULL
        FROM
            USER
            JOIN GROUPMEMBERSHIP
                ON GROUPMEMBERSHIP.USERID=USER.ID
            JOIN FILEUSERPERMISSIONS
                ON FILEUSERPERMISSIONS.USERID=GROUPMEMBERSHIP.USERID
            JOIN FILEGROUPPERMISSIONS
                ON FILEGROUPPERMISSIONS.GROUPID=GROUPMEMBERSHIP.GROUPID
        WHERE 
            FILEUSERPERMISSIONS.FILEID=FILE.ID
            AND FILEGROUPPERMISSIONS.FILEID=FILE.ID
            AND FILEUSERPERMISSIONS.READ=FILE.READ
            AND FILEGROUPPERMISSIONS.READ=FILE.READ
            AND USER.ID=userID
    )
WHERE
    FILE.READ=1

顺便说一下。问题是大坝好。这应该是如何提问的一个例子

答案 2 :(得分:0)

为了完整性,我也发布了解决方案,解决了这个问题。我最初的动机是创建一个函数来查看一个linux用户(即。user1)是否可以访问另一个linux用户(即。user2)主文件夹(即user1是否有读取/home/user2的权限。然后我会在使用VIEW函数为每个mysql用户构造user()时使用此函数(假设mysql用户名和linux用户名是一对一的)。感谢Arion的建议,我现在正在创建一个使用连接的视图。

注意,出于本示例的目的,主文件夹存储在FILE表中。

USER_VIEW视图:

CREATE VIEW USER_VIEW
AS
SELECT 
   U.ID
FROM 
   USERS AS U
   LEFT JOIN FILES AS F
      ON U.ID = F.USER_ID
   LEFT JOIN FILE_USER_PERMISSIONS AS P
      ON F.ID = P.FILE_ID
   LEFT JOIN USERS AS S
      ON P.USER_ID = S.ID
WHERE
(
   U.USERNAME = SUBSTR( USER(), 1, POSITION( '@' IN USER() ) - 1 )
)
OR
(
   F.R = TRUE
)
OR
(
   U.HOME = F.PATH AND P.R = TRUE AND S.USERNAME = SUBSTR( USER(), 1, POSITION( '@' IN USER() ) - 1 )
)
UNION
SELECT 
   U.ID
FROM 
   USERS AS U
   LEFT JOIN FILES AS F
      ON U.ID = F.USER_ID
   LEFT JOIN FILE_GROUP_PERMISSIONS AS P
      ON F.ID = P.FILE_ID
   LEFT JOIN GROUP_MEMBERSHIP AS G
      ON P.GROUP_ID = G.ID
   LEFT JOIN USERS AS S
      ON G.USER_ID = S.ID
WHERE
(
   U.HOME = F.PATH AND P.R = TRUE AND S.USERNAME = SUBSTR( USER(), 1, POSITION( '@' IN USER() ) - 1 )
)

编辑:我相信而不是发出像

这样的命令
CREATE VIEW USER_VIEW
AS
SELECT 
   U.ID
FROM 
    ...

我可以做到

CREATE VIEW USER_VIEW
AS
SELECT 
   U.*
FROM 
    ...

如果你想要复制10+列

,这会派上用场