Syntax
------

GRANT
  priv_type [(column_list)]
   [, priv_type [(column_list)]] ...
  ON [object_type] priv_level
  TO user_specification [ user_options ...]

user_specification:
 username [authentication_option]
 | PUBLIC
authentication_option:
 IDENTIFIED BY 'password'
 | IDENTIFIED BY PASSWORD 'password_hash'
 | IDENTIFIED {VIA|WITH} authentication_rule [OR authentication_rule  ...]

authentication_rule:
  authentication_plugin
 | authentication_plugin {USING|AS} 'authentication_string'
 | authentication_plugin {USING|AS} PASSWORD('password')

GRANT PROXY ON username
  TO user_specification [, user_specification ...]
  [WITH GRANT OPTION]

GRANT rolename TO grantee [, grantee ...]
  [WITH ADMIN OPTION]

grantee:
  rolename
  username [authentication_option]

user_options:
  [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
  [WITH with_option [with_option] ...]

object_type:
  TABLE
 | FUNCTION
 | PROCEDURE
 | PACKAGE

priv_level:
  *
 | *.*
 | db_name.*
 | db_name.tbl_name
 | tbl_name
 | db_name.routine_name

with_option:
  GRANT OPTION
 | resource_option

resource_option:
 MAX_QUERIES_PER_HOUR count
 | MAX_UPDATES_PER_HOUR count
 | MAX_CONNECTIONS_PER_HOUR count
 | MAX_USER_CONNECTIONS count
 | MAX_STATEMENT_TIME time

tls_option:
 SSL
 | X509
 | CIPHER 'cipher'
 | ISSUER 'issuer'
 | SUBJECT 'subject'

Description
-----------

The GRANT statement allows you to grant privileges or roles to accounts. To
use GRANT, you must have the GRANT OPTION privilege, and you must have the
privileges that you are granting.

Use the REVOKE statement to revoke privileges granted with the GRANT statement.

Use the SHOW GRANTS statement to determine what privileges an account has.

Account Names
-------------

For GRANT statements, account names are specified as the username argument in
the same way as they are for CREATE USER statements. See account names from
the CREATE USER page for details on how account names are specified.

Implicit Account Creation
-------------------------

The GRANT statement also allows you to implicitly create accounts in some
cases.

If the account does not yet exist, then GRANT can implicitly create it. To
implicitly create an account with GRANT, a user is required to have the same
privileges that would be required to explicitly create the account with the
CREATE USER statement.

If the NO_AUTO_CREATE_USER SQL_MODE is set, then accounts can only be created
if authentication information is specified, or with a CREATE USER statement.
If no authentication information is provided, GRANT will produce an error when
the specified account does not exist, for example:

show variables like '%sql_mode%' ;
+---------------+--------------------------------------------+
| Variable_name | Value                                      |
+---------------+--------------------------------------------+
| sql_mode      | NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+--------------------------------------------+

GRANT USAGE ON *.* TO 'user123'@'%' IDENTIFIED BY '';
ERROR 1133 (28000): Can't find any matching row in the user table

GRANT USAGE ON *.* TO 'user123'@'%' 
 IDENTIFIED VIA PAM using 'mariadb' require ssl ;
Query OK, 0 rows affected (0.00 sec)

select host, user from mysql.user where user='user123' ;

+------+----------+
| host | user     |
+------+----------+
| %    | user123 |
+------+----------+

Privilege Levels
----------------

Privileges can be set globally, for an entire database, for a table or
routine, or for individual columns in a table. Certain privileges can only be
set at certain levels.

* Global privileges priv_type are granted using *.* for
priv_level. Global privileges include privileges to administer the database
and manage user accounts, as well as privileges for all tables, functions, and
procedures. Global privileges are stored in the mysql.user table prior to
MariaDB 10.4, and in  mysql.global_priv table afterwards.
* Database privileges priv_type are granted using db_name.*
for priv_level, or using just * to use default database. Database
privileges include privileges to create tables and functions, as well as
privileges for all tables, functions, and procedures in the database. Database
privileges are stored in the mysql.db table.
* Table privileges priv_type are granted using db_name.tbl_name
for priv_level, or using just tbl_name to specify a table in the default
database. The TABLE keyword is optional. Table privileges include the
ability to select and change data in the table. Certain table privileges can
be granted for individual columns.
* Column privileges priv_type are granted by specifying a table for
priv_level and providing a column list after the privilege type. They allow
you to control exactly which columns in a table users can select and change.
* Function privileges priv_type are granted using FUNCTION db_name.routine_name
for priv_level, or using just  FUNCTION routine_name to specify a function
in the default database.
* Procedure privileges priv_type are granted using PROCEDURE
db_name.routine_name
for priv_level, or using just PROCEDURE routine_name to specify a procedure
in the default database.

The USAGE Privilege
-------------------

The USAGE privilege grants no real privileges. The SHOW GRANTS statement will
show a global USAGE privilege for a newly-created user. You can use USAGE with