You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MySQL 8.0.22 information_schema查询回归问题咨询

问题分析与解决办法

这个问题并非操作有误,而是你的查询逻辑没考虑到MySQL 8.0中information_schema.KEY_COLUMN_USAGE表的行为变化,同时缺少对外键类型的过滤,导致结果不符合预期。

核心原因

在MySQL 5.7中,虽然KEY_COLUMN_USAGE也包含主键、唯一键、外键等所有键的记录,但可能由于查询优化器的行为差异,当同时查询多个表时,非外键的记录没有被关联到结果集中(或者你关注的外键信息刚好没被干扰);而MySQL 8.0的查询优化器逻辑更严谨,所有匹配JOIN条件的记录(包括主键、唯一键)都会被关联进来,这就出现了你看到的“异常”结果。

当你只查询Tbl2时看似结果正常,其实只是因为你可能只关注了外键列tbl1Id的信息,忽略了主键id对应的keyColumnName会被填充为id(这并不是你需要的外键信息)——单表情况下这种干扰不明显而已。

修正后的查询语句

要实现“获取所有列名,若列是FOREIGN KEY则返回关联表/列信息”的需求,你需要在JOIN KEY_COLUMN_USAGE过滤出仅属于外键的记录,同时补充关联表和列的字段:

SELECT 
    TABLES.TABLE_SCHEMA AS dbName,
    TABLES.TABLE_NAME AS tableName,
    COLUMNS.COLUMN_NAME AS columnName,
    -- 新增关联表和列的字段,匹配你的需求
    KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME AS referencedTableName,
    KEY_COLUMN_USAGE.REFERENCED_COLUMN_NAME AS referencedColumnName
FROM information_schema.TABLES
LEFT JOIN information_schema.COLUMNS 
    ON COLUMNS.TABLE_SCHEMA = TABLES.TABLE_SCHEMA 
    AND COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
LEFT JOIN information_schema.KEY_COLUMN_USAGE 
    ON KEY_COLUMN_USAGE.TABLE_SCHEMA = COLUMNS.TABLE_SCHEMA 
    AND KEY_COLUMN_USAGE.TABLE_NAME = COLUMNS.TABLE_NAME 
    AND KEY_COLUMN_USAGE.COLUMN_NAME = COLUMNS.COLUMN_NAME
    -- 关键过滤条件:仅保留外键记录
    AND KEY_COLUMN_USAGE.CONSTRAINT_TYPE = 'FOREIGN KEY'
    -- 确保是有实际关联的外键(避免特殊情况的空引用)
    AND KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME IS NOT NULL
WHERE 
    TABLES.TABLE_SCHEMA = 'dbg' 
    AND TABLES.TABLE_NAME IN ('Tbl1', 'Tbl2')

验证说明

修正后的查询在MySQL 5.7和8.0中都会得到一致的正确结果:

  • Tbl1id列:referencedTableNamereferencedColumnNameNULL(因为它是主键,不是外键)
  • Tbl2id列:同样两个关联字段为NULL
  • Tbl2tbl1Id列:会返回关联的Tbl1id

额外优化

如果想让结果更直观,可以用IFNULL格式化关联信息,比如:

SELECT 
    TABLES.TABLE_SCHEMA AS dbName,
    TABLES.TABLE_NAME AS tableName,
    COLUMNS.COLUMN_NAME AS columnName,
    IFNULL(CONCAT(KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME, '.', KEY_COLUMN_USAGE.REFERENCED_COLUMN_NAME), 'Not a Foreign Key') AS foreignKeyReference
FROM information_schema.TABLES
LEFT JOIN information_schema.COLUMNS 
    ON COLUMNS.TABLE_SCHEMA = TABLES.TABLE_SCHEMA 
    AND COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
LEFT JOIN information_schema.KEY_COLUMN_USAGE 
    ON KEY_COLUMN_USAGE.TABLE_SCHEMA = COLUMNS.TABLE_SCHEMA 
    AND KEY_COLUMN_USAGE.TABLE_NAME = COLUMNS.TABLE_NAME 
    AND KEY_COLUMN_USAGE.COLUMN_NAME = COLUMNS.COLUMN_NAME
    AND KEY_COLUMN_USAGE.CONSTRAINT_TYPE = 'FOREIGN KEY'
    AND KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME IS NOT NULL
WHERE 
    TABLES.TABLE_SCHEMA = 'dbg' 
    AND TABLES.TABLE_NAME IN ('Tbl1', 'Tbl2')

内容的提问来源于stack exchange,提问作者obe

火山引擎 最新活动