Sorry for the long answer, which is actually a comment, but I do not understand it. The third-line GRANT command works well for me. Here are two cases that should work. It would be great if you could post some test commands that reproduce the error. At least I could learn from this :)
Case No. 1, the user does not exist:
mysql> SHOW GRANTS FOR my_user@ "%"; ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'
OK, the user does not exist.
mysql> create database my_database; Query OK, 1 row affected (0.00 sec) mysql> GRANT SELECT ON my_database.* TO my_user@ "%" IDENTIFIED BY 'my_password'; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR my_user@ "%"; +-----------------------------------------------------------------------+ | Grants for my_user@ % | +-----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' | | GRANT SELECT ON `my_database`.* TO 'my_user'@'%' | +-----------------------------------------------------------------------+ 2 rows in set (0.00 sec)
OK, he has SELECT permission.
Case No. 2, the user exists and has the right to other_database
and my_database
too:
mysql> SHOW GRANTS FOR my_user@ "%"; ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'
OK, the user does not exist.
mysql> create database my_database; Query OK, 1 row affected (0.00 sec) mysql> create database other_database; Query OK, 1 row affected (0.01 sec) mysql> GRANT SELECT ON my_database.* TO my_user@ "%" IDENTIFIED BY 'my_password'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT SELECT ON other_database.* TO my_user@ "%" IDENTIFIED BY 'my_password'; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR my_user@ "%"; +-----------------------------------------------------------------------+ | Grants for my_user@ % | +-----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' | | GRANT SELECT ON `other_database`.* TO 'my_user'@'%' | | GRANT SELECT ON `my_database`.* TO 'my_user'@'%' | +-----------------------------------------------------------------------+ 3 rows in set (0.00 sec)
The above test equipment, and now we give the user a new UPDATE
permission:
mysql> GRANT UPDATE ON my_database.* TO my_user@ "%" IDENTIFIED BY 'my_password'; Query OK, 0 rows affected (0.00 sec) mysql> SHOW GRANTS FOR my_user@ "%"; +-----------------------------------------------------------------------+ | Grants for my_user@ % | +-----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' | | GRANT SELECT ON `other_database`.* TO 'my_user'@'%' | | GRANT SELECT, UPDATE ON `my_database`.* TO 'my_user'@'%' | +-----------------------------------------------------------------------+ 3 rows in set (0.00 sec)
His permission did not change to other_database
, and he received a new UPDATE
permission on my_database
and in the previous SELECT
.
Based on the comments, it should only be UPDATE
without SELECT
.
Unfortunately, with current versions of MySQL this cannot be done with just one command. GRANT
does not have a REMOVE EXISTING
.
I think the best solution is @eswald GRANT USAGE ON ...
, but there are 3 more teams. Another solution is
DELETE FROM mysql.db WHERE user = 'my_user' AND host ='%' AND db = 'my_database'
but he needs FLUSH PRIVILEGES
, so he also has 3 teams.
A workaround could be a bash script that generates three commands that are in question:
#!/bin/bash function grant { USER=$1 PASSWORD=$2 DB=$3 PERMISSIONS=$4 echo "GRANT USAGE ON $DB TO $USER IDENTIFIED BY '$PASSWORD';" echo "REVOKE ALL PRIVILEGES ON $DB FROM $USER;" echo "GRANT $PERMISSIONS ON $DB TO $USER IDENTIFIED BY '$PASSWORD';" } grant " my_user@ '%'" "my_password" "my_database.*" "SELECT, UPDATE"
He prints:
GRANT USAGE ON my_database.* TO my_user@ '%' IDENTIFIED BY 'my_password'; REVOKE ALL PRIVILEGES ON my_database.* FROM my_user@ '%'; GRANT SELECT, UPDATE ON my_database.* TO my_user@ '%' IDENTIFIED BY 'my_password';
(I changed the first GRANT SELECT
to USAGE
.)