MySQL向数据库授予除一个表之外的所有权限

MySQL向数据库授予除一个表之外的所有权限,mysql,privileges,grant,user-permissions,Mysql,Privileges,Grant,User Permissions,我无法找到合理的解决方案来实现以下目标: 我希望有一个用户对数据库(或具有相同架构的一系列数据库)拥有所有权限,除了对一个表具有选择权限的 本质上,我希望用户可以自由支配数据库,但不能更新特定的表 到目前为止,我已经尝试过,但没有成功: 授予该数据库(db_name.*)上的所有权限,然后专门授予所需表上的select权限(希望它会覆盖“all”,我知道这很愚蠢) 授予该数据库的所有权限(db_name.*),然后撤消插入、更新和删除。但这产生了一个错误,称db_name.table_name

我无法找到合理的解决方案来实现以下目标:

我希望有一个用户对数据库(或具有相同架构的一系列数据库)拥有所有权限,除了对一个表具有选择权限的

本质上,我希望用户可以自由支配数据库,但不能更新特定的表

到目前为止,我已经尝试过,但没有成功:

  • 授予该数据库(db_name.*)上的所有权限,然后专门授予所需表上的select权限(希望它会覆盖“all”,我知道这很愚蠢)

  • 授予该数据库的所有权限(db_name.*),然后撤消插入、更新和删除。但这产生了一个错误,称db_name.table_name没有授予规则

根据我收集到的信息,我必须单独授予数据库中每个表的所有特权,只读表除外

请有人告诉我有一个更简单的方法


注意:我正在运行MySQL 5.1。最新版本可在Ubuntu 10.04上获得。

AFAIK,是的,您需要为每个表单独授予权限。但是,嘿,你有一台电脑。计算机非常擅长为您自动化重复性任务,因此为什么不编写一个脚本来执行以下操作:

  • 获取数据库中所有表的列表(
    显示表;
  • 对于列表中的每个项目,授予所有权限
  • 撤消对特殊表的权限
  • 或者,或者: 2.对于清单上的每一项,检查是否为特殊表格;如果不是,则授予所有权限


    我不给出代码的原因是,它可以在任何带有MySQL功能的脚本语言中完成,甚至是shell脚本;使用你最喜欢使用的东西。

    我知道这是一篇老文章,但我想我应该在@tdammers问题上添加一个内容,让其他人看看。您还可以对information_schema.tables执行SELECT CONCAT来创建grant命令,而不必编写单独的脚本

    首先从该数据库中撤消所有权限:

    REVOKE ALL PRIVILEGES ON db.* FROM user@localhost;  
    
    然后创建您的授权声明:

    SELECT CONCAT("GRANT UPDATE ON db.", table_name, " TO user@localhost;")
    FROM information_schema.TABLES
    WHERE table_schema = "YourDB" AND table_name <> "table_to_skip";
    
    选择CONCAT(“在数据库上授予更新”,表名称”,以user@localhost;")
    来自信息\u schema.TABLES
    其中table_schema=“YourDB”和table_name“table_to_skip”;
    

    将结果复制并粘贴到MySQL客户端,然后全部运行。

    下面是我用来授予MariaDB角色的草稿。 也许设置一个活动会让它更酷:-)


    不幸的是,MySQL中有内置的自然方式来执行选择性/特殊任务

    您可以使用下面的脚本(linux控制台bash脚本)

    如果您有windows控制台,则可以使用以下.bat文件:

    @ECHO OFF
    %= Define the database and root authorization details =% 
    set db_host=192.168.70.138
    set db_name=adhoctuts
    set db_user=adhoctuts
    set db_pass=Adhoctuts2018#
    
    mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "select concat(table_schema,'.',table_name) from information_schema.tables where table_schema='%db_name%' and table_name not like 'tbl1' AND table_name not like '\_\_%%';" %db_name% > tbls
    
    setlocal EnableDelayedExpansion
    set user_cnt=2
    set user[1]='Adhoctuts1'@'192.168.%%.%%'
    set pass[1]=Adhoctuts1_2018#
    set user[2]='Adhoctuts2'@'192.168.%%.%%'
    set pass[2]=Adhoctuts2_2018#
    
    set i=1
    :loop
        set user=!user[%i%]!
        set pass=!pass[%i%]!
        mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "drop user if exists %user% ; create user %user%  identified by '%pass%';"
        mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "revoke all privileges, grant option from %user%;" %db_name%      
        for /F "usebackq delims=" %%a in ("tbls") do (
            mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "grant select on %%a TO %user%;" %db_name%
        )
        if %i% equ %user_cnt% goto :end_loop
        set /a i=%i%+1
    goto loop
    
    :end_loop
    del /f tbls
    
    首先编写查询以获取所需表的列表,然后定义要授予访问权限的用户列表。每次数据库结构更改时,都需要执行脚本。我为MySQL选择性/特殊任务创建了单独的简短教程


    对不起,我应该说明这一点,现在是5.11。使用两个数据库怎么样?我的意思是你们可以在第二个数据库中存储特殊的表。2.我问过版本,因为在MySQL 5.5中,这可以通过准备好的语句来完成。目前它们在两个数据库中。事实上,“只读”是来自另一台服务器上的另一个数据库的文件,一切正常。我希望将该表复制到本地数据库中(还没有检查这是否可行)。由于表将是主从复制中的从机,因此我要确保在没有任何情况下,它会被写入。我可以创建一个新用户,该用户只对该表具有读取权限。但是,如果我可以有一个用户,我可以有一个连接并执行连接查询(这是真正的目标),而这个解决方案现在可以工作,如果您向数据库添加表,则必须为每个用户添加新表的权限。似乎没有办法只在*上添加权限,但在特定表上具有反权限。除了这种方式之外,真的没有办法吗?这似乎不对。我最好还是从mysql开始。我也需要这样做。使用角色可以避免“新用户”问题。为适当的角色分配详细的表级权限。向用户授予和撤销角色。现在,表级授权只需要在架构发生更改时更新(当您仍要重新访问权限时)。要使用
    通配符
    异常,而不是使用
    和table_name
    使用
    和table_name,而不是“%\u something”
    这非常方便。:)在这个问题被问到将近11年后,这仍然像一个魅力。
    #!/bin/bash
    
    # Define the database and root authorization details
    db_host='localhost'
    db_name='adhoctuts'
    db_user='root'
    db_pass='Adhoctuts2018#'
    
    # Define the query to get the needed tables
    table_list=$(mysql -h $db_host -u $db_user -p"$db_pass" -se "select concat(table_schema,'.',table_name) from information_schema.tables where table_schema='$db_name' and table_name not like 'tbl1' AND table_name not like '\_\_%';" $db_name | cut -f1)
    
    # Convert the query result into the array
    table_arr=(${table_list//,/ })
    
    # Declare the associative array of the users as username=>password pair
    # e.g: declare -A user_list=(["'user1'"]="pass1" ["'user2'"]="pass2")
    # In our case there is a single user
    declare -A user_list=(["'aht_r'@'localhost'"]="Adhoctuts2018#")
    for user in "${!user_list[@]}"
    do
        pass=${user_list[$user]}
        # Recreate user
        mysql -h $db_host -u $db_user -p"$db_pass" -se "drop user if exists $user; create user $user identified by '$pass';"
    
        # Provide SELECT privilege
        mysql -h $db_host -u $db_user -p"$db_pass" -se "revoke all privileges, grant option from $user;" $db_name
        mysql -h $db_host -u $db_user -p"$db_pass" -se "grant usage on $db_name.* TO $user;" $db_name
        for tbl in "${table_arr[@]}"; do
            echo "grant select on $tbl TO $user"
            mysql -h $db_host -u $db_user -p"$db_pass" -se "grant select on $tbl TO $user;" $db_name    
        done
    done
    
    @ECHO OFF
    %= Define the database and root authorization details =% 
    set db_host=192.168.70.138
    set db_name=adhoctuts
    set db_user=adhoctuts
    set db_pass=Adhoctuts2018#
    
    mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "select concat(table_schema,'.',table_name) from information_schema.tables where table_schema='%db_name%' and table_name not like 'tbl1' AND table_name not like '\_\_%%';" %db_name% > tbls
    
    setlocal EnableDelayedExpansion
    set user_cnt=2
    set user[1]='Adhoctuts1'@'192.168.%%.%%'
    set pass[1]=Adhoctuts1_2018#
    set user[2]='Adhoctuts2'@'192.168.%%.%%'
    set pass[2]=Adhoctuts2_2018#
    
    set i=1
    :loop
        set user=!user[%i%]!
        set pass=!pass[%i%]!
        mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "drop user if exists %user% ; create user %user%  identified by '%pass%';"
        mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "revoke all privileges, grant option from %user%;" %db_name%      
        for /F "usebackq delims=" %%a in ("tbls") do (
            mysql -h %db_host% -u %db_user% -p"%db_pass%" -se "grant select on %%a TO %user%;" %db_name%
        )
        if %i% equ %user_cnt% goto :end_loop
        set /a i=%i%+1
    goto loop
    
    :end_loop
    del /f tbls