在Teradata DB中我有源表
create set table SRC_TABLE (
Some_Id varchar(2O) not null
);
此表加载了来自外部系统的数据。我有目标表
create set table DST_TABLE (
Some_Id decimal(4,0) not null
);
我需要安全地将行从SRC_TABLE复制到DST_TABLE。有一个合同,外部系统将只提供可转换为DECIMAL(4)的值。但是,有没有安全的方法如何在SRC_TABLE中选择不符合合同的行并可能导致类型转换失败?
更新:由于我正在处理的环境限制,我无法使用UDF功能。
答案 0 :(得分:0)
我建议在SQL中使用错误表中的MERGE INTO
操作来捕获无法应用的记录。这将允许您加载数据并对无法应用的错误表中的记录进行后处理。
您还可以从Teradata Developer Exchange下载相应的UDF库,并使用IsNumeric()
等效项对SRC_TABLE
的每一行执行条件检查,以避免将非数字数据插入表中。此条件检查可以丢弃整个记录,将记录加载到日志表,或将值设置为无效数据的约定默认值。
CREATE ERROR TABLE MyDB.TGT_TABLE_ERR FOR MyDB.TGT_TABLE; -- Creates Error Table for MERGE INTO operation
MERGE INTO MyDB.TGT_TABLE T1
USING MyDB.SRC_TABLE T2
ON T1.{primary index} = T2.{primary index}
WHEN MATCHED THEN
UPDATE SET Some_ID = CAST(T2.Some_ID AS DECIMAL(4,0))
WHEN NOT MATCHED THEN
INSERT VALUES (T2.{column list})
LOGGING ALL ERRORS WITH NO LIMIT;
答案 1 :(得分:0)
您可以使用FastExport从旧表中写出数据,然后使用FastLoad将其加载到新表中。任何解析为十进制(4,0)的记录都将加载到新表中,而其余记录将写入错误表。确保设置足够高的ERRLIMIT
以确保在发生一些错误后作业不会死亡。
答案 2 :(得分:-1)
最后在同事的帮助下,我找到了可行的解决方案。它有一些限制(不考虑符号,不考虑小数部分),但对于ID它可以正常工作。
因此,可以通过选择获取SRC_TABLE
中无法转换为DECIMAL(4)
的记录:
select
Some_Id
from
SRC_TABLE
where
characters(trim(leading '0' from trim(both ' ' from Some_Id))) > 4
or substring(substring('0000' || trim(leading '0' from trim(both ' ' from Some_Id)) FROM characters('0000' || trim(leading '0' from trim(both ' ' from Some_Id))) - 3) FROM 1 FOR 1) NOT IN ('0','1','2','3','4','5','6','7','8','9')
or substring(substring('0000' || trim(leading '0' from trim(both ' ' from Some_Id)) FROM characters('0000' || trim(leading '0' from trim(both ' ' from Some_Id))) - 3) FROM 2 FOR 1) NOT IN ('0','1','2','3','4','5','6','7','8','9')
or substring(substring('0000' || trim(leading '0' from trim(both ' ' from Some_Id)) FROM characters('0000' || trim(leading '0' from trim(both ' ' from Some_Id))) - 3) FROM 3 FOR 1) NOT IN ('0','1','2','3','4','5','6','7','8','9')
or substring(substring('0000' || trim(leading '0' from trim(both ' ' from Some_Id)) FROM characters('0000' || trim(leading '0' from trim(both ' ' from Some_Id))) - 3) FROM 4 FOR 1) NOT IN ('0','1','2','3','4','5','6','7','8','9');
编辑: 更方便的是dnoeth在回答Convert char to int TeraData Sql时提出的方法,这也适用于TD 13.10:
-- TO_NUMBER returns NULL when failing
CAST(TO_NUMBER(UTENTE_CD) AS INTEGER)
-- check if there are only digits
CASE WHEN UTENTE_CD = '' -- all spaces
THEN NULL
WHEN LTRIM(UTENTE_CD, '0123456789') = '' -- only digits
THEN CAST(UTENTE_CD AS INTEGER)
ELSE NULL
END