sql server中用sys.all_objects生成小范围数字序列最省事,只需select top(n) row_number() over(order by object_id) from sys.all_objects,无需递归或建对象,高效安全。

SQL Server里用sys.all_objects生成小范围数字序列最省事
只要需要几十到几千个连续整数,直接查系统表比写递归CTE快得多,也不用担心栈溢出。SQL Server的sys.all_objects通常有上万行,足够应付多数分页、补全、测试场景。
常见错误是直接SELECT ROW_NUMBER() OVER(ORDER BY object_id)却不加TOP限制——结果可能远超所需,还拖慢查询。实际用法要带明确上限:
SELECT TOP (100) ROW_NUMBER() OVER (ORDER BY object_id) AS n FROM sys.all_objects- 如果怕
sys.all_objects被删减(极少见),可加WHERE type = 'S'保底,但没必要过度防御 - 注意:这个方法只适用于SQL Server,其他数据库没这表
PostgreSQL用generate_series()函数一步到位
PostgreSQL原生支持generate_series(),从起始值到结束值、按步长生成整数或时间序列,语法直白,性能稳定。
容易踩的坑是混淆参数顺序或类型:第一个参数必须≤第二个,且三者类型要一致(比如都是integer);传float会报错,除非显式转换:
-
SELECT * FROM generate_series(1, 10, 1) AS n→ 正确 -
SELECT * FROM generate_series(10, 1, 1)→ 返回空集,不报错但结果意外 -
SELECT * FROM generate_series(1.5, 5.5, 1.0)→ 报错,得写成generate_series(1, 5, 1)再转类型
MySQL 8.0+用递归CTE生成序列,但必须设cte_max_recursion_depth
MySQL的递归CTE默认只允许100层递归,查不到101以上的数字就报错ERROR 3636 (HY000): Recursive query aborted after 100 iterations。
这不是语法问题,是服务端配置限制。临时解决要先改会话变量:
SET SESSION cte_max_recursion_depth = 1000;- 再执行递归:
WITH RECURSIVE seq(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM seq WHERE n - 注意:该变量不能超过全局
max_allowed_packet隐含限制,生成超大序列仍可能OOM
跨数据库可移植方案:建一个最小化数字表
如果项目要兼容多种数据库,或者频繁用到序列(比如日期维度、ID补位),硬编码递归或依赖系统表都不是长久之计。最稳的方式是建一张numbers表,只存1~10000的整数。
这张表体积小(约40KB)、查询极快、无版本/配置依赖。初始化一次后,所有环境都能用SELECT n FROM numbers WHERE n BETWEEN 1 AND 100取数:
- 建表语句只需
CREATE TABLE numbers (n INT PRIMARY KEY);,然后用任意方式INSERT初始数据 - 别用触发器或函数动态生成——那又绕回性能和兼容性老问题
- 真正麻烦的不是建表,而是团队是否愿意接受“预置静态表”这种反直觉但有效的做法










