• sqlserver CTE定位点类型和递归部分的类型不匹配


    【1】字符串类型递归报错

    在CTE递归测试,遇到了小问题:

      

    登时就迷糊了:不都是取的是Unit表中的同一个列,相加之后类型就变了么?

    难道是因为,系统知道这是在进行递归运算,但又不确定递归的层次,以及字符串连接后的长度,于是把这个字符串的长度预设为很大很大的。

    例子1:

    ;with t1(id ,num1 ) as (
    select 1 ,1
    union all 
    select id+1,id+id*10 from t1
    where id<=10
    )
      

    但是上面例子中的 num 1也进行了运算,为什么就不需要显示转换类型?

    【2】错误情况

      、 

      

    【2】基本分析与验证

    这是因为递归也不是无限递归的,也是有层次限制的:

    【在测试递归查询的结果时,可以通过在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中使用 MAXRECURSION 提示和 0 到 32,767 之间的值,来限制特定语句允许的递归级数。】

    而int 足够了:(目测是int类型,因为直接写一个数字, 默认的类型就是int)

    Int从 -2^31 (-2,147,483,648) 到 2^31 - 1 (2,147,483,647) 的整型数据(所有数字)。存储大小为 4 个字节

      

    Int类型猜测正确, 但为什么错误提示是:溢出,而不是更多字节的bigint?

    前面不是说了么:数值的默认类型是int,一旦确定就不会再改变。(而且这个环境还没有智能到,根据所赋的值的大小,或者要进行的加减乘除的运算,自动匹配到最合适的类型。)

    于是乎,我茅塞顿开:字符串进行运算的时候,也是有默认类型的(字符串运算,默认就会把字符串转换成 varchar(8000) )下面就是做图验证

            

    所以这个问题就是CTE递归时,Union运算要求同结构,同类型;

    而运算后的默认类型和自定义的类型不一致, 显示转换下就OK了, 选择哪种转换方式, 看具体需求。

    【3】核心问题所在

    但其实只要上下字符串类型一致即可;

    【3.1】报错

     注意,把字符串转换到下面也不行:

    如下图,我们其实的 aa其实并不是 varchar(8000),那为什么【2】中我们把 上面的 cast('aa' varchar(8000))  这样一改就可以了呢?

    因为union all 下面递归,经过计算/拼接的字符串,它是一个可变的长度,无法确定它的长度,但字符串默认最多是8000,所以 union all 上半部只要定义为 varchar(8000),那么就可以解决这个问题。

         

    【3.2】解决:上下类型一致

      

       

    参考:

    http://bbs.csdn.net/topics/290079093

    http://technet.microsoft.com/zh-cn/library/ms186243(v=sql.105).aspx

    https://www.cnblogs.com/ccding13/p/3515393.html

  • 相关阅读:
    简单的总结
    /bin/bash: sshpass: command not found
    ubuntu 16.04 忘记root密码
    ubuntu下QtCreator启动无响应问题解决
    TX1 文字界面启动与root用户自动登录设置
    qt线程睡眠
    TX2 默认root用户启动
    linux下使用文件IO监听GPIO中断
    Linux下指定线程的名字
    [Error] ISO C++ forbids comparison between pointer and integer
  • 原文地址:https://www.cnblogs.com/gered/p/13804408.html
Copyright © 2020-2023  润新知