CHOOSE是SQL Server 2012+的索引查表函数,索引从1开始,越界或空索引返回NULL;所有参数预先求值,类型需兼容;不能用于对象名,性能敏感时应改用短路求值的CASE WHEN。

CHOOSE函数在SQL Server中怎么用?
CHOOSE只在SQL Server 2012+ 和 Azure SQL Database 中可用,MySQL、PostgreSQL、Oracle 都不支持这个函数。它本质是“索引查表”:给一个整数索引和若干选项值,返回对应位置的值(索引从1开始,不是0)。CHOOSE 不是标准SQL,别在跨数据库项目里硬套。
索引超出范围时返回NULL而不是报错
这是最容易忽略的行为——CHOOSE(5, 'a', 'b') 不会抛异常,而是安静地返回 NULL。如果你依赖返回值做后续逻辑(比如 WHERE CHOOSE(...) = 'x'),结果可能意外过滤掉整行。实际使用时建议加校验:
- 用
CASE WHEN @idx BETWEEN 1 AND N THEN CHOOSE(@idx, ...)包一层 - 或提前用
ISNULL(CHOOSE(...), 'default')设默认值 - 注意:空值传入索引位(如
CHOOSE(NULL, 'x', 'y'))也返回NULL
CHOOSE vs CASE WHEN:什么时候该换用CASE?
CHOOSE 看似简洁,但有硬伤:所有选项值会在执行前全部求值。比如 CHOOSE(@i, GETDATE(), GETUTCDATE(), SYSDATETIME()),不管@i是1还是3,三个时间函数全执行一遍。而 CASE WHEN 是短路求值。性能敏感场景(尤其含子查询、UDF、IO操作时)必须用 CASE 替代。
另外,选项值类型必须能隐式转换为同一类型。例如 CHOOSE(1, 123, 'abc') 会尝试把 'abc' 转成 int,失败就报错:Conversion failed when converting the varchar value 'abc' to data type int.
常见误用:把CHOOSE当动态列名或表名用
CHOOSE 返回的是标量值,不能用于生成列名、表名、ORDER BY 表达式等需要编译期确定结构的地方。比如下面写法非法:
SELECT CHOOSE(2, col1, col2) FROM t -- ✅ 可以(返回值参与计算)<br>SELECT * FROM CHOOSE(1, 't1', 't2') -- ❌ 报错:FROM后必须是对象名,不是字符串值
想实现类似效果,得用动态SQL拼接,但那是另一层复杂度了——CHOOSE 压根不碰对象解析,只管“选值”。

















