【问题标题】:Numeric Overflow in Recursive Query : Teradata递归查询中的数值溢出:Teradata
【发布时间】:2013-08-05 08:23:21
【问题描述】:

我是 teradata 的新手。我想将数字 1 到 1000 插入到表 test_seq 中,该表创建如下。

create table test_seq(
    seq_id integer
);

在这个网站上搜索后,我想出了 recusive 查询来插入数字。

insert into test_seq(seq_id)
with recursive cte(id) as (
    select 1 from test_dual
    union all
    select id + 1 from cte
    where id + 1 <= 1000
    )
select id from cte;

test_dual 创建如下,它只包含一个值。 (类似于 Oracle 中的 DUAL)

create table test_dual(
    test_dummy varchar(1)
);

insert into test_dual values ('X');

但是,当我运行插入语句时,我得到了错误,Failure 2616 Numeric overflow occurred during computation.

我在这里做错了什么? integer 数据类型不足以容纳数值 1000 吗? 另外,有没有办法编写查询,以便我可以取消 test_dual 表?

【问题讨论】:

    标签: sql teradata recursive-cte


    【解决方案1】:

    当您简单地写入 1 时,解析器会为其分配最匹配的数据类型,即 BYTEINT。 BYTEINT 的有效值范围是 -128 到 127,因此只需将类型转换添加到 INT :-)

    通常您不需要 Teradata 中的虚拟 DUAL 表“SELECT 1;”是有效的,但在某些情况下,解析器仍然坚持使用 FROM(不要问我为什么)。这个技巧应该有效:

    SEL * FROM (SELECT 1 AS x) AS dt;
    

    您可以在此创建视图:

    REPLACE VIEW oDUAL AS SELECT * FROM (SELECT 'X' AS dummy) AS dt;
    

    解释“从 oDUAL 中选择 1;”有点愚蠢,所以一张真正的桌子可能会更好。但是为了获得有效的访问(= 单个 AMP/单行),它必须定义如下:

    CREATE TABLE dual_tbl(
        dummy VARCHAR(1) CHECK ( dummy = 'X') 
    ) UNIQUE PRIMARY INDEX(dummy); -- i remember having fun when you inserted another row in Oracle's DUAL :_)
    
    INSERT INTO dual_tbl VALUES ('X'); 
    
    REPLACE VIEW oDUAL AS SELECT dummy FROM dual_tbl WHERE dummy = 'X';
    
    insert into test_seq(seq_id)
    with recursive cte(id) as (
        select cast(1 as int) from oDUAL
        union all
        select id + 1 from cte
        where id + 1 <= 1000
        )
    select id from cte;
    

    但递归并不是获取一系列数字的合适方法,因为它是连续的,并且始终是“全 AMP 步骤”,即使数据驻留在单个 AMP 上,就像在这种情况下一样。

    如果小于 73414 个值(201 年),最好使用 sys_calendar.calendar(或任何其他具有已知数字序列的表):

    SELECT day_of_calendar 
    FROM sys_calendar.CALENDAR
    WHERE day_of_calendar BETWEEN 1 AND 1000;
    

    否则使用 CROSS 连接,例如获取从 1 到 1,000,000 的数字:

    WITH cte (i) AS 
     ( SELECT day_of_calendar
       FROM sys_calendar.CALENDAR
       WHERE day_of_calendar BETWEEN 1 AND 1000
     ) 
    SELECT 
      (t2.i - 1) * 1000 + t1.i
    FROM cte AS t1 CROSS JOIN cte AS t2;
    

    【讨论】:

    • 优秀。非常感谢。
    • 那个 BYTEINT 东西是真正有用的,非常感谢。递归 sql 总是坚持使用 from 子句,我想知道为什么 teradata 与 dual 完全不同。
    • @etl_devs:由于select 1; 在 Teradata 中有效,因此不需要双表。但是当他们添加像UNION 这样的集合操作时,他们开始使用需要FROM 的标准SQL 兼容规则。您可以创建一个虚拟对象,但不要将其命名为 DUAL,因为它是保留关键字,必须写为 "DUAL":REPLACE VIEW oDual AS SELECT 'X' AS DUMMY;
    猜你喜欢
    • 1970-01-01
    • 2016-11-20
    • 2012-07-26
    • 1970-01-01
    • 2018-03-03
    • 2019-06-08
    • 2017-10-20
    • 1970-01-01
    相关资源
    最近更新 更多