1

在 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 函数。

4

3 回答 3

0

我建议使用MERGE INTO带有错误表的 SQL 中的操作来捕获无法应用的记录。这将允许您加载数据并对无法应用的错误表中的记录进行后处理。

您还可以从 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;
于 2012-04-18T16:50:12.583 回答
0

您可以使用 FastExport 从旧表中写出数据,然后使用 FastLoad 将其加载到新表中。任何解析为 decimal(4, 0) 的记录都将被加载到新表中,而其余记录将被写出到错误表中。确保设置一个足够高的值ERRLIMIT,以确保作业不会在少数错误后终止。

于 2012-04-18T23:26:43.957 回答
-1

最后在同事的帮助下,我找到了可行的解决方案。它有一些限制(不考虑符号,不考虑小数部分),但对于 ID,它工作得很好。

  1. 从字符串的开头和结尾修剪空格
  2. 从字符串中修剪前导零
  3. 测试最大允许长度
  4. 用零填充字符串到四个字符(将四个零添加到字符串的开头并从字符串中获取最后四个字符)
  5. 在允许的字符集上测试字符串中的每个位置

所以SRC_TABLE不能转换成的记录DECIMAL(4)可以通过select来获取:

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
于 2012-04-19T10:40:29.543 回答