为什么这个CASE表达式:
SELECT CASE column
WHEN 'a' THEN '1'
WHEN 'b' THEN '2'
... c -> i
WHEN 'j' THEN '10'
WHEN 'k' THEN '11'
END [col]
FROM LinkedServer.database.dbo.table产生这个结果?
错误信息: Msg 8180,16级,状态1,第1行语句(S)无法准备。 Msg 125、级别15、状态4、第1行大小写表达式只能嵌套到级别10。
显然,这里没有嵌套的CASE表达式,尽管有10多个分支。
另一个怪事。这个内联表值函数会产生相同的错误:
ALTER FUNCTION [dbo].[fn_MyFunction]
(
@var varchar(20)
)
RETURNS TABLE
AS
RETURN
(
SELECT CASE column
WHEN 'a' THEN '1'
WHEN 'b' THEN '2'
... c -> i
WHEN 'j' THEN '10'
WHEN 'k' THEN '11'
END [col]
FROM LinkedServer.database.dbo.table
)但是,类似的多语句TVF工作得很好:
ALTER FUNCTION [dbo].[fn_MyFunction]
(
@var varchar(20)
)
RETURNS @result TABLE
(
value varchar(max)
)
AS
BEGIN
INSERT INTO @result
SELECT CASE column
WHEN 'a' THEN '1'
WHEN 'b' THEN '2'
... c -> i
WHEN 'j' THEN '10'
WHEN 'k' THEN '11'
END [col]
FROM LinkedServer.database.dbo.table
RETURN;
END发布于 2013-05-22 22:44:44
显然,这里没有嵌套的
CASE表达式。
不是在查询文本中,不是。但是,解析器总是将CASE表达式扩展到嵌套形式:
SELECT CASE SUBSTRING(p.Name, 1, 1)
WHEN 'a' THEN '1'
WHEN 'b' THEN '2'
WHEN 'c' THEN '3'
WHEN 'd' THEN '4'
WHEN 'e' THEN '5'
WHEN 'f' THEN '6'
WHEN 'g' THEN '7'
WHEN 'h' THEN '8'
WHEN 'i' THEN '9'
WHEN 'j' THEN '10'
WHEN 'k' THEN '11'
END
FROM AdventureWorks2012.Production.Product AS p
该查询是本地的(没有链接服务器),Compute Scalar定义了以下表达式:

在本地执行时,这很好,因为解析器没有看到嵌套的CASE语句在10层以上的深度(尽管它确实将一条语句传递到本地查询编译的后期阶段)。
但是,通过链接服务器,可以将生成的文本发送到远程服务器进行编译。如果是这样的话,远程解析器会看到一个嵌套的CASE语句的深度超过10层,您将得到错误8180。
另一个怪事。这个内联表值函数会产生相同的错误。
内联函数被扩展到原始查询文本中,因此与链接服务器的错误结果相同并不奇怪。
但是类似的多语句TVF工作得很好。
相似,但不一样。msTVF涉及到对varchar(max)的隐式转换,这恰好阻止将CASE表达式发送到远程服务器。因为CASE是在本地计算的,所以解析器从未看到过嵌套的CASE,也没有错误。如果您将表定义从varchar(max)更改为CASE结果的隐式类型-- varchar(2) --该表达式被msTVF远程处理,您将得到一个错误。
最终,当过度嵌套的CASE由远程服务器计算时,就会发生错误.如果在远程查询迭代器中没有计算CASE,则没有错误结果。例如,以下内容包括一个未远程处理的CONVERT,因此即使使用了链接服务器,也不会发生错误:
SELECT CASE CONVERT(varchar(max), SUBSTRING(p.Name, 1, 1))
WHEN 'a' THEN '1'
WHEN 'b' THEN '2'
WHEN 'c' THEN '3'
WHEN 'd' THEN '4'
WHEN 'e' THEN '5'
WHEN 'f' THEN '6'
WHEN 'g' THEN '7'
WHEN 'h' THEN '8'
WHEN 'i' THEN '9'
WHEN 'j' THEN '10'
WHEN 'k' THEN '11'
END
FROM SQL2K8R2.AdventureWorks.Production.Product AS p
发布于 2014-02-12 13:07:39
你可以绕开这里
SELECT COALESCE(
CASE SUBSTRING(p.Name, 1, 1)
WHEN 'a' THEN '1'
WHEN 'b' THEN '2'
WHEN 'c' THEN '3'
WHEN 'd' THEN '4'
WHEN 'e' THEN '5'
WHEN 'f' THEN '6'
WHEN 'g' THEN '7'
WHEN 'h' THEN '8'
WHEN 'i' THEN '9'
ELSE NULL
END,
CASE SUBSTRING(p.Name, 1, 1)
WHEN 'j' THEN '10'
WHEN 'k' THEN '11'
END)
FROM SQL2K8R2.AdventureWorks.Production.Product AS p发布于 2016-06-24 07:35:14
解决此问题的另一个解决方法是使用基于集合的逻辑,将CASE表达式替换为对引用表(以下代码中的ref)的左联接(或外部应用),该表可以是永久的、临时的,也可以是派生的表/ CTE。如果在多个查询和过程中需要这一点,我希望将其作为永久表:
SELECT ref.result_column AS [col]
FROM LinkedServer.database.dbo.table AS t
LEFT JOIN
( VALUES ('a', '1'),
('b', '2'),
('c', '3'),
---
('j', '10'),
('k', '11')
) AS ref (check_col, result_column)
ON ref.check_col = t.column ;https://dba.stackexchange.com/questions/42837
复制相似问题