MySQL中 ORDINAL_POSITION的使用小结

 更新时间:2026年07月29日 10:02:22   作者:宁小法先森︿( ̄︶ ̄)︿  
ORDINAL_POSITION是MySQL系统表information_schema.columns中的一个重要字段,用于表示列在表中的定义顺序,本文就来详细的介绍一下ORDINAL_POSITION的使用,感兴趣的可以了解一下

ORDINAL_POSITION是 MySQL 系统表 information_schema.columns中的一个关键字段,它表示列在表中的定义顺序。

一、基本定义

1. 官方定义

  • 字段名:ORDINAL_POSITION
  • 数据类型:int
  • 含义:列在表中的位置序号(从1开始)
  • 值域:正整数,从1到表中的总列数

2. 示例说明

-- 创建示例表
CREATE TABLE employees (
    id INT PRIMARY KEY,           -- ORDINAL_POSITION = 1
    first_name VARCHAR(50),       -- ORDINAL_POSITION = 2
    last_name VARCHAR(50),        -- ORDINAL_POSITION = 3
    email VARCHAR(100),           -- ORDINAL_POSITION = 4
    hire_date DATE               -- ORDINAL_POSITION = 5
);

-- 查看列顺序
SELECT 
    COLUMN_NAME,
    ORDINAL_POSITION,
    DATA_TYPE
FROM information_schema.columns
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = 'employees'
ORDER BY ORDINAL_POSITION;

输出结果

COLUMN_NAME

ORDINAL_POSITION

DATA_TYPE

id

1

int

first_name

2

varchar

last_name

3

varchar

email

4

varchar

hire_date

5

date

二、ORDINAL_POSITION 的重要性

1. 反映表定义顺序

-- 表定义决定了ORDINAL_POSITION
CREATE TABLE test_order (
    col3 VARCHAR(10),  -- 位置1
    col1 INT,          -- 位置2
    col2 DATE          -- 位置3
);

-- 查询结果
SELECT COLUMN_NAME, ORDINAL_POSITION
FROM information_schema.columns
WHERE TABLE_NAME = 'test_order';
-- 结果:col3(1), col1(2), col2(3)

2. 影响 SELECT * 的输出顺序

-- SELECT * 按ORDINAL_POSITION顺序返回列
SELECT * FROM employees;
-- 返回顺序:id, first_name, last_name, email, hire_date

3. 影响 DESCRIBE/SHOW COLUMNS

-- DESCRIBE 也按此顺序显示
DESCRIBE employees;
-- 显示顺序与ORDINAL_POSITION一致

三、如何修改 ORDINAL_POSITION

重要ORDINAL_POSITION本身是只读的系统字段,不能直接修改。必须通过以下 DDL 操作间接修改:

1. 通过 ALTER TABLE 修改列顺序

-- 将email列移到first_name之后
ALTER TABLE employees
MODIFY COLUMN email VARCHAR(100)
AFTER first_name;

-- 查询修改后的顺序
SELECT COLUMN_NAME, ORDINAL_POSITION
FROM information_schema.columns
WHERE TABLE_NAME = 'employees';
-- 新顺序:id(1), first_name(2), email(3), last_name(4), hire_date(5)

2. 批量重新排列列顺序

-- 重新定义列顺序
ALTER TABLE employees
    MODIFY id INT FIRST,
    MODIFY hire_date DATE AFTER last_name,
    MODIFY email VARCHAR(100) AFTER first_name;

3. 重建表修改顺序

-- 方法1:通过CREATE TABLE ... AS
CREATE TABLE employees_new AS
SELECT id, first_name, email, last_name, hire_date
FROM employees;

DROP TABLE employees;
RENAME TABLE employees_new TO employees;

-- 方法2:通过ALTER TABLE ... RENAME
ALTER TABLE employees RENAME TO employees_old;

CREATE TABLE employees (
    -- 按新顺序定义列
    id INT PRIMARY KEY,
    first_name VARCHAR(50),
    email VARCHAR(100),
    last_name VARCHAR(50),
    hire_date DATE
);

INSERT INTO employees SELECT * FROM employees_old;
DROP TABLE employees_old;

四、ORDINAL_POSITION 的特殊规则

1. 虚拟列/生成列的位置

CREATE TABLE virtual_test (
    id INT,
    amount DECIMAL(10,2),
    tax DECIMAL(10,2) GENERATED ALWAYS AS (amount * 0.1) VIRTUAL,
    total DECIMAL(10,2) GENERATED ALWAYS AS (amount + tax) VIRTUAL
);

-- 虚拟列的ORDINAL_POSITION
SELECT COLUMN_NAME, ORDINAL_POSITION, EXTRA
FROM information_schema.columns
WHERE TABLE_NAME = 'virtual_test';
-- 结果:id(1), amount(2), tax(3), total(4)

2. 添加/删除列的影响

-- 原始表
CREATE TABLE demo (a INT, b INT, c INT);  -- 顺序:a(1), b(2), c(3)

-- 删除中间列
ALTER TABLE demo DROP COLUMN b;
-- 新顺序:a(1), c(2)

-- 添加新列
ALTER TABLE demo ADD COLUMN d INT AFTER a;
-- 新顺序:a(1), d(2), c(3)

3. 分区键列的位置

CREATE TABLE partitioned (
    id INT,
    region VARCHAR(20),
    sale_date DATE,
    amount DECIMAL(10,2)
)
PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025)
);

-- 分区键不影响ORDINAL_POSITION
SELECT COLUMN_NAME, ORDINAL_POSITION
FROM information_schema.columns
WHERE TABLE_NAME = 'partitioned';
-- 顺序仍为:id(1), region(2), sale_date(3), amount(4)

五、实际应用场景

1. 生成表结构文档

-- 生成规范的字段列表
SELECT 
    CONCAT(
        LPAD(ORDINAL_POSITION, 3, '0'), '. ',
        COLUMN_NAME, ' (', 
        COLUMN_TYPE, 
        IF(IS_NULLABLE = 'YES', ', 可空', ', 非空'),
        IF(COLUMN_KEY = 'PRI', ', 主键', ''),
        ')'
    ) AS field_description
FROM information_schema.columns
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = 'employees'
ORDER BY ORDINAL_POSITION;

2. 检测表结构变更

-- 记录列顺序快照
CREATE TABLE column_snapshot (
    snapshot_date DATE,
    table_name VARCHAR(64),
    column_name VARCHAR(64),
    ordinal_position INT,
    data_type VARCHAR(64)
);

-- 插入快照
INSERT INTO column_snapshot
SELECT 
    CURDATE(),
    TABLE_NAME,
    COLUMN_NAME,
    ORDINAL_POSITION,
    DATA_TYPE
FROM information_schema.columns
WHERE TABLE_SCHEMA = DATABASE();

-- 检测变化
SELECT 
    cs1.column_name,
    cs1.ordinal_position as old_position,
    cs2.ordinal_position as new_position
FROM column_snapshot cs1
JOIN information_schema.columns cs2 
    ON cs1.table_name = cs2.TABLE_NAME 
    AND cs1.column_name = cs2.COLUMN_NAME
WHERE cs1.snapshot_date = '2024-01-01'
  AND cs1.ordinal_position != cs2.ORDINAL_POSITION;

六、与其他系统视图的关系

1. 与 information_schema.statistics 的关系

-- 查看索引中列的顺序(与ORDINAL_POSITION不同)
SELECT 
    TABLE_NAME,
    INDEX_NAME,
    COLUMN_NAME,
    SEQ_IN_INDEX,  -- 在索引中的顺序
    c.ORDINAL_POSITION  -- 在表中的顺序
FROM information_schema.statistics s
JOIN information_schema.columns c
    ON s.TABLE_SCHEMA = c.TABLE_SCHEMA
    AND s.TABLE_NAME = c.TABLE_NAME
    AND s.COLUMN_NAME = c.COLUMN_NAME
WHERE s.TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;

2. 与 performance_schema 的关系

-- 查询列统计信息
SELECT 
    TABLE_NAME,
    COLUMN_NAME,
    ORDINAL_POSITION,
    COUNT_STAR
FROM performance_schema.table_io_waits_summary_by_table
ORDER BY ORDINAL_POSITION;

七、注意事项与限制

1. ORDINAL_POSITION 的限制

  • 只读属性:不能直接UPDATE修改
  • 依赖表结构:随ALTER TABLE操作自动更新
  • 事务性:DDL操作立即生效
  • 视图中的顺序:对于视图,反映创建视图时SELECT子句中的列顺序

2. 对应用程序的影响

-- 应用代码应注意列顺序
-- 不推荐的写法(依赖列顺序)
ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
String firstName = rs.getString(2);  -- 依赖first_name在第2位

-- 推荐的写法(明确指定列)
ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM employees");
String firstName = rs.getString("first_name");

八、最佳实践

1. 规范化列顺序约定

-- 建议的列顺序标准
1. 主键列 (id, uuid)
2. 业务键列 (code, sn)
3. 外键引用列 (xxx_id)
4. 状态标志列 (status, type, flag)
5. 核心业务数据列
6. 时间戳列 (created_at, updated_at)
7. 审计/版本列 (created_by, version)
8. 软删除标志 (deleted_at)
9. 扩展字段

2. 维护脚本示例

-- 检查列顺序一致性的脚本
SELECT 
    TABLE_NAME,
    GROUP_CONCAT(
        CONCAT(ORDINAL_POSITION, '.', COLUMN_NAME) 
        ORDER BY ORDINAL_POSITION
    ) AS column_sequence
FROM information_schema.columns
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME IN ('table1', 'table2', 'table3')
GROUP BY TABLE_NAME
ORDER BY TABLE_NAME;

总结

ORDINAL_POSITION是 MySQL 中一个重要的元数据字段,它:

  • 定义列在表中的物理顺序
  • 从1开始计数,按表定义顺序递增
  • 只读属性,必须通过 DDL 操作间接修改
  • 影响SELECT *DESCRIBE等操作的输出顺序
  • 应该保持一致性以便于维护和理解

理解并合理利用 ORDINAL_POSITION可以帮助您更好地管理数据库表结构,提高代码的可维护性。

到此这篇关于MySQL中 ORDINAL_POSITION的使用小结的文章就介绍到这了,更多相关MySQL ORDINAL_POSITION内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL自增锁(Auto-Increment Lock) 的原理使用

    MySQL自增锁(Auto-Increment Lock) 的原理使用

    MySQL的自增锁用于确保自增值在并发插入时唯一且递增,本文主要介绍了MySQL自增锁的原理使用,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • Mysql的慢SQL优化思路和规范详解

    Mysql的慢SQL优化思路和规范详解

    这篇文章主要介绍了Mysql的慢SQL优化思路和规范详解,官方介绍索引是帮助MySQL高效获取数据的数据结构。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度,需要的朋友可以参考下
    2023-05-05
  • mysql双向加密解密方式用法详解

    mysql双向加密解密方式用法详解

    这篇文章主要介绍了mysql双向加密解密方式用法,需要的朋友可以参考下
    2014-04-04
  • mysql报错Duplicate entry ‘xxx‘ for key ‘字段名‘的解决

    mysql报错Duplicate entry ‘xxx‘ for key&nbs

    有时候对表进行操作,例如加唯一键,或者插入数据,会报错,本文就来介绍一下mysql报错Duplicate entry ‘xxx‘ for key ‘字段名‘的解决方法,感兴趣的可以了解一下
    2023-10-10
  • MySQL中使用SQL语句对字段进行重命名

    MySQL中使用SQL语句对字段进行重命名

    MySQL中,如何使用SQL语句来对表中某一个字段进行重命名呢?我们将使用alter table 这一SQL语句,需要的朋友可以参考下
    2016-04-04
  • win10 下安装 mysql 5.7.14 详细图文教程

    win10 下安装 mysql 5.7.14 详细图文教程

    本文通过文字和图片相结合的形式给大家介绍了win10 下安装 mysql 5.7.14的教程的,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • MySQL互为主从(双向同步)部署超详细教程

    MySQL互为主从(双向同步)部署超详细教程

    MySQL互为主从是一种特殊的复制架构,其中两个MySQL服务器互为主从,彼此之间互相同步数据,这篇文章主要介绍了MySQL互为主从(双向同步)部署的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • 详细深入聊一聊Mysql中的int(1)和int(11)

    详细深入聊一聊Mysql中的int(1)和int(11)

    mysql数据库作为当前常用的关系型数据库,肯定会遇到设计表的需求,下面对设计表时int类型的设置进行分析,下面这篇文章主要给大家介绍了关于Mysql中int(1)和int(11)的相关资料,需要的朋友可以参考下
    2022-08-08
  • MySQL锁等待与死锁根治的全攻略

    MySQL锁等待与死锁根治的全攻略

    本文详细分析了MySQL中的锁等待和死锁问题,解释了InnoDB锁的基本概念、分类以及它们之间的兼容性,并提供了排查这些锁相关问题的方法,重点关注了锁等待的常见原因及对应的解决策略,需要的朋友可以参考下
    2026-04-04
  • Mysql中的用户管理实践

    Mysql中的用户管理实践

    这篇文章主要介绍了Mysql中的用户管理实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-05-05

最新评论