2013-08-05 3 views
3

저는 teradata를 처음 사용합니다. 나는 아래와 같이 테이블 test_seq에 1부터 1000까지의 숫자를 삽입하고 싶습니다.재귀 쿼리의 숫자 오버플로 : Teradata

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은 다음과 같이 만들어지며 하나의 값만 포함합니다. (오라클의 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 테이블을 없앨 수 있도록 쿼리를 작성하는 방법이 있습니까?

답변

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을 선택합니다;" 조금 어리 석다. 그래서 진짜 테이블이 더 좋을지도 모른다.

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/단일 행)가 정의되어야합니다 다음 이 경우와 같이 데이터가 단일 AMP에 상주하는 경우에도 "단계"를 수행 할 수 있습니다.

는 (숫자의 알려진 순서 또는 다른 테이블) 미만 73,414 값 (2백1년) 더 나은 사용 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; 
+0

우수. 고맙습니다. – Noel

+0

BYTEINT 것은 정말 유익한 데, 정말 고마워요. 재귀 sql은 항상 from 절을 주장합니다. 나는 왜 teradata가 이중과 같은 것이 아닌지 궁금합니다. –

+2

@etl_devs :'select 1;'이 Teradata에서 유효하기 때문에 이중 테이블이 필요 없습니다. 그러나 UNION과 같은 집합 연산을 추가 할 때 그들은 표준 SQL 호환 규칙을 사용하기 시작했습니다.이 규칙에는'FROM'이 필요합니다. . 더미 (dummy)를 만들 수 있습니다. 예약어이므로'DUAL '로 이름을 지우지 말고,''DUAL''으로 작성해야합니다 :'DAYAL AS SELECT 'X'AS 'DUMMY; – dnoeth