3

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

create table test_seq(
    seq_id integer
);

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

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表格?

4

1 回答 1

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;

解释“从 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;
于 2013-08-05T09:43:25.223 回答