无需循环或游标,向临时表插入日期范围内所有年份的方法
无需循环/游标插入日期范围内所有年份的方法
当然可以!完全不用依赖WHILE循环或者游标,用基于集合的查询就能轻松搞定,给你分享几个实用的方案:
方法1:递归CTE(通用表表达式)
这是SQL Server里很常用的生成序列的方式,逻辑清晰易理解:
-- 先创建目标临时表 CREATE TABLE #YearList (YearValue INT); -- 定义你的起止年份 DECLARE @StartYear INT = 2010, @EndYear INT = 2018; -- 用递归CTE生成年份序列并插入临时表 WITH YearCTE AS ( -- 初始化:起始年份 SELECT @StartYear AS YearNum UNION ALL -- 递归:每次年份+1,直到达到结束年份 SELECT YearNum + 1 FROM YearCTE WHERE YearNum < @EndYear ) INSERT INTO #YearList (YearValue) SELECT YearNum FROM YearCTE; -- 验证结果 SELECT * FROM #YearList;
递归CTE会先生成起始年份,然后不断自增直到等于结束年份,全程是集合操作,比循环高效得多。
方法2:利用系统表生成序列
如果不想用递归,可以借助SQL Server自带的系统表master.dbo.spt_values来生成数字序列,进而得到年份:
CREATE TABLE #YearList (YearValue INT); DECLARE @StartYear INT = 2010, @EndYear INT = 2018; INSERT INTO #YearList (YearValue) SELECT @StartYear + number FROM master.dbo.spt_values WHERE type = 'P' -- 筛选正数序列 AND number <= (@EndYear - @StartYear); -- 控制生成的数量 SELECT * FROM #YearList;
注意:spt_values的number默认范围是0到2047,如果你需要的年份跨度超过2047,这个方法就不适用了,得换其他方案。
方法3:SQL Server 2022+/Azure SQL专属:GENERATE_SERIES函数
如果你的数据库是SQL Server 2022及以上版本,或者用的是Azure SQL,可以直接用官方提供的GENERATE_SERIES函数,代码更简洁:
CREATE TABLE #YearList (YearValue INT); DECLARE @StartYear INT = 2010, @EndYear INT = 2018; INSERT INTO #YearList (YearValue) SELECT value FROM GENERATE_SERIES(@StartYear, @EndYear, 1); SELECT * FROM #YearList;
这个函数可以直接指定起始值、结束值和步长,一步生成你需要的年份序列,非常直观。
以上几种方法都是基于集合的操作,比循环/游标性能更好,也更符合SQL的设计理念。
内容的提问来源于stack exchange,提问作者Pankaj Saha
相关产品推荐
相关产品推荐

