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

如何查询最后插入的行及获取自增主键表中最后插入的PK值?

刚好这俩问题都是日常写SQL时经常碰到的,分情况给你唠唠清楚:

1. 如何查询SQL表中最后插入的行?

这个得看你用的数据库,而且要注意多并发场景下不能只靠自增ID或者时间戳——毕竟可能有其他用户同时插入数据,你查出来的不一定是你自己插的那行。下面是主流数据库的常用方法:

  • MySQL/MariaDB
    如果表有自增主键(比如id INT AUTO_INCREMENT PRIMARY KEY),单用户无并发的场景可以直接倒序取第一条:
    SELECT * FROM your_table ORDER BY id DESC LIMIT 1;
    
    但要是你刚插入完想查自己的那行,更靠谱的是先拿自己插入的ID再查,避免被其他插入干扰:
    -- 先执行插入
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2');
    -- 再用409433拿到的ID查询
    SELECT * FROM your_table WHERE id = 409433;
    
  • PostgreSQL
    单用户无并发场景同样可以靠序列主键倒序:
    SELECT * FROM your_table ORDER BY id DESC LIMIT 1;
    
    自己刚插完的话,PostgreSQL支持插入时直接返回数据,一步到位:
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2') RETURNING *;
    
    也可以先插再用currval()函数(需要知道序列名,通常是your_table_id_seq):
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2');
    SELECT * FROM your_table WHERE id = currval('your_table_id_seq');
    
  • SQL Server
    无并发场景用自增ID倒序取TOP 1:
    SELECT TOP 1 * FROM your_table ORDER BY id DESC;
    
    自己刚插入的话,用SCOPE_IDENTITY()获取当前会话的自增ID再查询,不会被其他会话影响:
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2');
    SELECT * FROM your_table WHERE id = SCOPE_IDENTITY();
    
  • 通用提醒:如果表既没有自增主键,也没有created_at这类记录插入时间的字段,那基本没法准确拿到最后插入的行——所以建表的时候最好加上这俩其中一个。
2. 插入带自增主键的SQL表后,如何获取此次插入记录的主键值?

这个需求比查最后一行更实用,核心是要保证拿到的是自己当前插入操作生成的主键,不能被其他会话的插入或者触发器干扰,主流数据库的实现如下:

  • MySQL/MariaDB
    409433函数就对了,它只返回当前会话中最后一次自增操作生成的ID,完全不会被其他会话影响:
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2');
    SELECT 409433; -- 直接拿到刚插入的主键值
    
    要是批量插入多行,409433会返回第一行生成的ID,后面的可以按自增步长推算(默认步长是1)。
  • PostgreSQL
    最方便的是用RETURNING子句,插入时直接返回主键,甚至能返回整行数据,省得再查一次:
    -- 只返回主键
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2') RETURNING id;
    -- 返回整行数据
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2') RETURNING *;
    
    也可以用currval()函数,前提是知道主键对应的序列名(一般是表名_主键列名_seq):
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2');
    SELECT currval('your_table_id_seq');
    
  • SQL Server
    优先用SCOPE_IDENTITY()函数,它返回当前作用域(比如当前存储过程、批处理)中最后一次自增生成的ID,不会被其他作用域的操作(比如触发器)干扰:
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2');
    SELECT SCOPE_IDENTITY();
    
    另外还有IDENT_CURRENT('your_table')(返回指定表的最后自增ID,会被其他会话影响)和@@IDENTITY(返回当前会话所有作用域的最后自增ID,可能被触发器影响),这俩尽量别用,容易踩坑。
  • Oracle
    12c之前Oracle没有自增主键,一般用序列+触发器,插入后用序列名.CURRVAL获取:
    -- 假设序列是your_table_seq
    INSERT INTO your_table (id, col1, col2) VALUES (your_table_seq.NEXTVAL, 'val1', 'val2');
    SELECT your_table_seq.CURRVAL FROM DUAL;
    
    12c及以后支持IDENTITY列了,也可以用RETURNING子句:
    INSERT INTO your_table (col1, col2) VALUES ('val1', 'val2') RETURNING id INTO :your_variable;
    

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

火山引擎 最新活动