CREATE TEMPORARY TABLES权限独立于CREATE权限,需显式授予且必须与SELECT权限作用域一致(如均限定在app_db.*),否则执行CREATE TEMPORARY TABLE ... AS SELECT会报错ERROR 1142。

只给 CREATE TEMPORARY TABLES 权限,不给 CREATE
核心就是权限分离:MySQL 把建临时表和建普通表拆成两个独立权限。只要不授 CREATE,用户就无法执行 CREATE TABLE;但只要给了 CREATE TEMPORARY TABLES,就能建临时表。
常见错误是误以为“只读用户默认不能建临时表”,其实恰恰相反——很多新用户没显式禁用 CREATE,结果意外获得了建物理表的能力。
- 必须显式授予
CREATE TEMPORARY TABLES,它不会随SELECT自动附带 - 绝对不要授
CREATE权限(哪怕只在某个库),否则用户可建真实表 - 如果用户已有
ALL PRIVILEGES或GRANT OPTION,得先DROP USER重建,或用REVOKE CREATE ON ...清理
GRANT 语句必须限定到具体数据库
权限作用域错配是报错 ERROR 1142 (42000): CREATE TEMPORARY TABLES command denied to user 的最常见原因。MySQL 要求 CREATE TEMPORARY TABLES 和 SELECT 必须在同一作用域(比如都写 `app_db`.*)才能配合使用 CREATE TEMPORARY TABLE t AS SELECT ...。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- ✅ 正确:
GRANT SELECT ON `app_db`.* TO 'tmp_user'@'%'; GRANT CREATE TEMPORARY TABLES ON `app_db`.* TO 'tmp_user'@'%'; - ❌ 错误:
GRANT CREATE TEMPORARY TABLES ON *.* TO ...—— 这会让用户能在information_schema等系统库建临时表,有潜在风险 - ⚠️ 注意:
GRANT ... ON `app_db`.*不等于USE app_db;如果应用连接后执行跨库查询(如SELECT * FROM app_db.orders JOIN log_db.events),临时表语句仍需在app_db范围内才有效
用户 host 匹配和认证插件要对得上
权限配置完连不上、或者 SHOW GRANTS 显示权限缺失,大概率是账号匹配失败,不是权限本身写错了。
- 检查实际登录用的 host:用
127.0.0.1连 ≠localhost,MySQL 把它们当两个不同账号处理 - MySQL 8.0+ 默认用
caching_sha2_password插件,老客户端(如某些 Python MySQL 驱动)可能握手失败,报错像authentication plugin cannot be loaded;建用户时加IDENTIFIED WITH mysql_native_password BY 'xxx'更稳妥 - 验证当前会话真正匹配的账号:
SELECT CURRENT_USER();,再查它的权限:SHOW GRANTS FOR CURRENT_USER;
临时表能做什么、不能做什么要心里有数
临时表不是绕过只读限制的后门,它能力明确受限:
- ✅ 允许:
CREATE TEMPORARY TABLE tmp AS SELECT ...、ALTER TABLE tmp ADD COLUMN(改结构不影响原表) - ❌ 禁止:
INSERT INTO real_table SELECT * FROM tmp(无INSERT权限)、DROP TABLE real_table、RENAME TABLE tmp TO other_tmp(MySQL 不支持重命名临时表) - ⚠️ 特别注意:
CREATE TEMPORARY TABLE ... AS SELECT如果源查询含重复主键值,而你又显式定义了PRIMARY KEY,MySQL 8.0+ 会直接报错——这不是权限问题,是数据约束冲突
真正容易被忽略的是权限作用域和 host 匹配这两层,它们不出现在 SQL 语法里,却决定授权是否生效。写完 GRANT 别急着测试逻辑,先跑一遍 CURRENT_USER() 和 SHOW GRANTS 确认权限真落到目标账号上。

















