- Error number
- 1142
- SQLSTATE
42000- Symbol
ER_TABLEACCESS_DENIED_ERROR- Product
- MySQL Server
- Versions
- MySQL 5.7, 8.0 and 8.4 (8.0.46 names the table without its database)
- Category
- Access & Privileges
- Last reviewed
- 24 October 2026
On this page
What it means
Error 1142 means the account is logged in but does not have the privilege this statement needs on that table, so MySQL refused the statement.
After a login succeeds, MySQL checks every statement against the privileges of the account that matched the login (CURRENT_USER(), which can differ from the name you typed). Privileges can be granted globally (ON *.*), per database (ON shop.*), per table or per column, and through roles. When none of these gives the needed privilege for the table, the statement fails with 1142. The message tells you three things: the statement type that was denied (SELECT, INSERT, UPDATE, DELETE, DROP, ALTER and so on), the account as user@host, and the table. In MySQL 8.0.46 the table is named without its database, so check which database the statement used.
SQLSTATE 42000 is shared with syntax errors, which is why PHP PDO labels it "Syntax error or access violation"; check the error number. Some system tables refuse certain statements to everyone: performance_schema tables such as processlist and global_status cannot be changed with DELETE or UPDATE even by an administrative account, and they raise 1142 too. Being refused a whole database, for example by USE or by the default database of a connection, gives error 1044 (Access denied for user to database) instead, and a missing global privilege such as PROCESS or SYSTEM_VARIABLES_ADMIN gives error 1227.
Common causes
- The application account was granted only some privileges (for example SELECT) and the code now writes, deletes or changes the schema.
- The grant is on another database or table than the one used: a test database, a renamed table, or a statement that names a table in a second database.
- The login matched another account than you think: grants were made to
'app'@'%'but the login matches'app'@'localhost', which has its own (smaller) privileges. - The privileges come from a role that is granted but not active in the session (roles are active only if they are default roles, activated with SET ROLE, or activate_all_roles_on_login is ON).
- The statement targets a system table that does not allow it, such as UPDATE or DELETE on a performance_schema table.
Diagnose it
Read-only These statements only read metadata (information_schema, performance_schema and SHOW statements) or your own data. They do not change data, privileges or configuration, so they are safe to run first.
Which account am I, and what can it do?
Run these in the session that got the error.
SELECT USER() AS sent_as, CURRENT_USER() AS checked_as;
SHOW GRANTS FOR CURRENT_USER(); CURRENT_USER() is the account whose privileges are checked. In SHOW GRANTS, look for a line that covers the statement type in the message on shop.*, on the table itself, or on *.*. If none does, the privilege is missing.
Are the roles I was given active?
SELECT CURRENT_ROLE();
SHOW VARIABLES LIKE 'activate_all_roles_on_login'; NONE means no role is active in this session, so privileges granted only through roles do not apply. activate_all_roles_on_login OFF (the default) means only default roles are activated at login.
As an administrator: privileges for the account on databases and tables
SELECT grantee, table_schema, privilege_type
FROM information_schema.schema_privileges
WHERE grantee LIKE '''app''@%'
ORDER BY table_schema, privilege_type;
SELECT grantee, table_schema, table_name, privilege_type
FROM information_schema.table_privileges
WHERE grantee LIKE '''app''@%'
ORDER BY table_schema, table_name, privilege_type; Each database-level and table-level privilege of every app account, per host. Compare the host in each grantee with the host in the error message: a privilege granted to another host part does not help this login.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Grant only the missing privilege on the right object
Changes permissionsGrant the statement type from the message on the table, or on the application's database if it needs it on every table, to exactly the account shown in the message.
Caution: Do not grant ALL PRIVILEGES ON *.* (or WITH GRANT OPTION) to an application account to make the error go away. Schema changes (CREATE, ALTER, DROP) belong to a separate migration account, not the account the application runs with.
GRANT INSERT, UPDATE ON shop.orders TO 'app'@'localhost';
-- or, for the whole application database:
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'localhost';
Activate the roles the account was given
Changes permissionsIf the privileges come from a role, make it a default role so it is active at every login, or activate it in the session with SET ROLE.
Caution: SET DEFAULT ROLE ALL activates every role granted to the account. If some roles are meant for occasional use only, name the roles to activate instead of ALL.
SET DEFAULT ROLE ALL TO 'app'@'localhost';
-- or, in the current session only:
SET ROLE ALL;
Use the right account and database
Client or network sideIf the grants exist for another host part or another database, fix the connection settings (host, user, default database) or the statement's qualified table name rather than adding privileges.
Read system tables instead of changing them
Read-onlyperformance_schema tables like processlist and global_status are views of server state: read them with SELECT. To end a session use KILL, and to reset statistics use the statements the manual provides for that table (some summary tables accept TRUNCATE TABLE), not DELETE or UPDATE.
Examples
An application account that can only read
Shown as documented in the MySQL server error message reference (ER_TABLEACCESS_DENIED_ERROR); not reproduced here, because it needs a restricted account and the lab may not create accounts. The table is named without its database, as MySQL 8.0.46 printed it in our tests on system tables.
-- The account was given read access only:
-- GRANT SELECT ON shop.* TO 'app'@'localhost';
-- Connected as app@localhost:
INSERT INTO orders (customer_id, total) VALUES (7, 19.99);
ERROR 1142 (42000): INSERT command denied to user 'app'@'localhost' for table 'orders'
How to prevent it
Write down what each account needs and grant exactly that: the application account gets SELECT, INSERT, UPDATE and DELETE on its own database, a separate migration account gets the schema privileges, and reporting accounts get SELECT only. Grant to the same host pattern the application logs in with, and set default roles when you use roles.
Run the application's tests with the same restricted account as production, so a new statement that needs another privilege fails in testing, not in front of users. Handle 1142 in code as a configuration error, not something to retry.
Common questions
How do I fix SELECT command denied to user for table?
Run SHOW GRANTS FOR CURRENT_USER() in the failing session to see what the account has. Then, as an administrator, grant SELECT on that table or database to exactly the user@host in the message, or connect as the account that already has it.
I granted the privilege, so why do I still get 1142?
Usually the grant went to another account: the same user name with another host part (app@% instead of app@localhost), or another database. Compare CURRENT_USER() with the grantee. If the privilege comes from a role, the role may not be active (SELECT CURRENT_ROLE() shows NONE).
Why does root get 1142 on performance_schema?
performance_schema tables expose server state and only allow the operations that make sense for each table. DELETE and UPDATE on tables such as processlist or global_status are refused to every account with 1142; read them with SELECT instead.
Learn more on CodeWithSQL
Official documentation
Last technically reviewed 24 October 2026; examples and diagnostics run on MySQL 8.0.46. Message templates checked against the server's error catalogue (perror) for that version.