CREATE TEMPORARY TABLES 权限必须显式按数据库粒度授予,不能用 ON .,且需配合源表 SELECT 权限;临时表无元数据、不可授权/重命名,推荐优先使用 CTE 或派生表。

CREATE TEMPORARY TABLES 权限必须显式授予数据库级范围
MySQL 不会默认给用户 CREATE TEMPORARY TABLES 权限,哪怕用户有 SELECT 或 CREATE 权限也不行。这个权限是独立的、必须显式授予,且只能按数据库粒度授权(不能只写 ON *.*,尤其在 MySQL 5.7 及更早版本会直接报错)。
常见错误现象:用户执行 CREATE TEMPORARY TABLE tmp AS SELECT ... 时抛出 ERROR 1142 (42000): CREATE TEMPORARY TABLES command denied to user。
- 正确写法:
GRANT CREATE TEMPORARY TABLES ON app_db.* TO 'reporter'@'%'; - 错误写法:
GRANT CREATE TEMPORARY TABLES ON *.* TO 'reporter'@'%';(兼容性差,生产环境应避免) - 若需多库支持,必须逐个授权:
GRANT CREATE TEMPORARY TABLES ON db_a.* TO 'reporter'@'%'; GRANT CREATE TEMPORARY TABLES ON db_b.* TO 'reporter'@'%'; - 授权后无需
FLUSH PRIVILEGES;(GRANT语句自动生效)
临时表数据可见性由源表权限决定,不是临时表本身
授予 CREATE TEMPORARY TABLES 权限 ≠ 允许任意捞数据建临时表。真正卡住的是 SELECT 源表的权限 —— 临时表只是“容器”,里面填什么,取决于你能否从基表读出来。
例如:CREATE TEMPORARY TABLE tmp_log AS SELECT * FROM audit_logs; 失败,大概率不是因为没临时表权限,而是用户根本没对 audit_logs 表的 SELECT 权限。
- 必须同步授予对应库/表的
SELECT权限,且作用域要匹配(比如SELECT和CREATE TEMPORARY TABLES都得在app_db下) - 跨库引用会失败:
CREATE TEMPORARY TABLE t AS SELECT * FROM sys.config;要求用户同时拥有sys库的SELECT权限,哪怕临时表建在app_db - 临时表不继承权限:即使你用
DEFINER存储过程创建临时表,执行时仍校验调用者(而非定义者)对源表的访问权
临时表无法被 GRANT 授权,也不能重命名或跨会话访问
临时表没有元数据记录在 information_schema.tables 中,MySQL 权限系统压根“看不见”它,因此所有试图对临时表名做 GRANT 的操作都会失败,比如 GRANT SELECT ON app_db.tmp_user TO 'u1'@'%' 直接报 ERROR 1146 (42S02): Table 'app_db.tmp_user' doesn't exist。
-
RENAME TABLE tmp TO new_tmp;会报错 —— MySQL 不支持重命名临时表 -
DROP TEMPORARY TABLE是可选的,会话断开时自动清理;但DROP TABLE(无 TEMPORARY)会误删永久表,务必核对语法 - 误写
CREATE TABLE tmp_xxx ...(漏掉TEMPORARY)将创建永久表,它会进权限系统、占磁盘、残留数据,且可能被其他有权限用户读取 - 检查是否真建了临时表:
SHOW FULL TABLES WHERE Table_type = 'TEMPORARY';永远返回空(这是正常行为),更靠谱的方式是建完后立刻执行SHOW CREATE TABLE tmp_xxx;看输出里是否含TEMPORARY关键字
替代方案:CTE 或派生表更适合轻量级场景
如果只是为了中间结果复用、又不想操心权限和生命周期,优先考虑 WITH 子句(MySQL 8.0.1+)或派生表(subquery in FROM),它们不需要额外权限,也不产生元数据。
例如:WITH sales_by_region AS (SELECT region, SUM(amount) s FROM orders GROUP BY region) SELECT * FROM sales_by_region WHERE s > 10000; —— 整个逻辑在单条语句内完成,无临时表、无权限依赖、无残留风险。
- CTE 不可跨语句复用,每次都要重新定义;临时表可以多次
SELECT、JOIN、UPDATE - 派生表(如
SELECT * FROM (SELECT ... ) AS t)更轻量,但嵌套过深会影响可读性 - CTE / 派生表无法索引,大数据量下性能不如带索引的临时表;此时才值得走授权 +
CREATE TEMPORARY TABLE流程
临时表权限控制的关键不在“表”,而在“谁允许你从哪读、在哪建”。容易被忽略的是:授权必须精确到库、源表权限另算、临时表名根本进不了权限系统——这些点没对齐,光给 CREATE TEMPORARY TABLES 就是白给。


















