首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么链接服务器在一个案例表达式中有10个分支的限制?

为什么链接服务器在一个案例表达式中有10个分支的限制?
EN

Database Administration用户
提问于 2013-05-22 20:19:20
回答 4查看 23.2K关注 0票数 19

为什么这个CASE表达式:

代码语言:javascript
复制
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多个分支。

另一个怪事。这个内联表值函数会产生相同的错误:

代码语言:javascript
复制
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工作得很好:

代码语言:javascript
复制
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
EN

回答 4

Database Administration用户

回答已采纳

发布于 2013-05-22 22:44:44

显然,这里没有嵌套的CASE表达式。

不是在查询文本中,不是。但是,解析器总是将CASE表达式扩展到嵌套形式:

代码语言:javascript
复制
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,因此即使使用了链接服务器,也不会发生错误:

代码语言:javascript
复制
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
票数 25
EN

Database Administration用户

发布于 2014-02-12 13:07:39

你可以绕开这里

代码语言:javascript
复制
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
票数 5
EN

Database Administration用户

发布于 2016-06-24 07:35:14

解决此问题的另一个解决方法是使用基于集合的逻辑,将CASE表达式替换为对引用表(以下代码中的ref)的左联接(或外部应用),该表可以是永久的、临时的,也可以是派生的表/ CTE。如果在多个查询和过程中需要这一点,我希望将其作为永久表:

代码语言:javascript
复制
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 ;
票数 3
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/42837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档