递归查询中的数字溢出:Teradata

时间:2013-08-05 08:23:21

标签: sql teradata recursive-cte

我是teradata的新手。我想在表test_seq中插入数字1到1000,如下所示。

create table test_seq(
    seq_id integer
);

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

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');

但是,当我运行insert语句时,我收到错误Failure 2616 Numeric overflow occurred during computation.

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

1 个答案:

答案 0 :(得分:7)

当您只编写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;

解释“SELECT 1 FROM oDUAL”;有点愚蠢,所以真正的桌子可能会更好。但要获得高效访问(=单个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;