欢迎投稿

今日深度:

Teradata到GBase 8a迁移总结,在无文档参考的情况下

Teradata到GBase 8a迁移总结,在无文档参考的情况下


Teradata到GBase 8a迁移总结

目录

1 DDL语法相关

1.1 字段类型

1.2 建表语句

1.2.1 表类型

1.2.2 表选项

1.2.3 列选项

1.2.4 约束

1.2.5 分布键

1.2.6 导出表(Derived Table)

1.3 复制表结构与数据

2 DML语法相关

2.1 简写

2.2 关联update

3 函数的使用

3.1 同名且用法相同的函数

3.1.1 ORDER BY

3.1.2 CASE WHEN

3.1.3 COALESCE函数

3.1.4 TRIM函数

3.1.5 EXTRACT函数

3.1.6 ADD_MONTHS函数

3.1.7 ROW_NUMBER开窗函数

3.1.8 ABS函数

3.1.9 EXP函数

3.1.10 LN函数

3.1.11 SQRT函数

3.1.12 SUBSTRING函数

3.1.13 SUBSTR函数

3.2 同名用法不同的函数

3.2.1 CAST对各种类型的转换

3.2.2 RANK函数

3.3 不同名函数的等价改法

3.3.1 求幂运算

3.3.2 TD中的LOG函数

3.3.3 TD中ZEROIFNULL函数

3.3.4 TD中NULLIFZERO函数

3.3.5 TD中的DATE和TIME函数

3.3.6 TD中的INDEX函数

3.3.7 TD中FORMAT短语

4 空串处理

4.1 数值、时间类型字段插入空串

4.1.1 int类型插空串

4.1.2 decimal类型插空串

4.1.3 time类型插空串

4.1.4 timestamp 类型插空串

4.1.5 date类型插空串

4.2 字符类型空串、空格的区别

5 不同类型字段的数据交换和关联

5.1 int和date字段的交互和关联

5.2 int/decimal和varchar字段的关联

6 超范围数据的处理

6.1 decimal类型插入超范围数据

6.2 字符类型插入超范围数据

7 SQL语法上的使用差异

7.1 字符型的列等于数值时的强转

7.2 别名依赖

7.3 TD中sql语句以’;'开始的含义

7.4 TD中的WITH RECURSIVE…递归语法

7.5 TD中的QUALIFY语句

8 开窗函数

9 UDF

1 DDL语法相关
本章节主要描述Teradata建表涉及到的相关内容与GBase 8a的差异;Teradata建表语句中包含较多的表选项和列选项,且支持通用的约束,而GBase 8a在这方面要相对简约些。在无文档参考的情况下,一般都是将GBase 8a不支持的全部去掉即可。

1.1 字段类型
Teradata中字段类型与GBase 8a的字段类型对照表如下,供迁移时参考。

数据类型

Teradata

GBase 8a

数值型

DECIMAL(n,m)/DEC(n,m)

DECIMAL(n,m)

NUMERIC(n,m)

NUMERIC(n,m)

BYTEINT范围(-128~127)

TINYINT范围(-127~127)

SMALLINT范围(-32768~32767)

SMALLINT范围(-32767~32767)

INTEGER/INT范围(-2147483648~2147483647)

INTEGER/INT范围(-2147483647~2147483647)

BIGINT范围(-9233372036854775808~9233372036854775807)

BIGINT范围(-9223372036854

775806~9223372036854775806)

REAL

REAL

FLOAT

FLOAT

DOUBLE PRECISION

DOUBLE/DOUBLE PRECISION

字符型

CHAR(n)/CHARACTER(n) 范围(1~64000)

CHAR(n) 范围(1~255)

VARCHAR(n)/CHAR VARYING(n) 范围(1~64000)

VARCHAR(n) 范围(1~10922)

LONG VARCHAR

VARCHAR(10922)/LONGTEXT

GRAPHIC(n) 范围(1~64000)

CHAR(n) 范围(1~255)

VARGRAPHIC(n) 范围(1~64000)

VARCHAR(n) 范围(1~10922)

LONG VARGRAPHIC

VARCHAR(10922)/LONGTEXT

CLOB

VARCHAR(10922)/LONGTEXT

二进制

BYTE(n)

BLOB/LONG BLOB

VARBYTE(n)

BLOB/LONG BLOB

BLOB

BLOB/LONG BLOB

日期时间型

DATE

DATE

TIME

TIME

TIMESTAMP

DATETIME

1.2 建表语句
1.2.1 表类型
Teradata中的表类型与GBase 8a的表类型对照表如下,供迁移时参考。

Teradata

Teradata描述

GBase 8a

GBase 8a描述

CREATE SET TABLE

普通表,不允许重复记录

CREATE TABLE

普通表,允许重复记录

CREATE MULTISET TABLE

普通表,允许重复记录

CREATE TABLE

普通表,允许重复记录

CREATE GLOBAL TEMPORARY TABLE

全局临时表,特点:

①可以被多个用户共享;

②每个用户会话只能看到自己的数据;

③会话(session)结束时,表的数据被丢掉;

④在数据字典中创建并保持表的定义。

CREATE TABLE

普通表,允许重复记录

CREATE VOLATILE TABLE

可变临时表,特点:

①会话级的表,存在于整个会话期间,会话结束表自动删除;

②不使用数据字典;

③一个会话中,最多有64个可变临时表;

④每个可变临时表必须有唯一的名称。

CREATE TEMPORARY TABLE

临时表,特点:

①会话级的表,存在于整个会话期间,会话结束表自动删除;

1.2.2 表选项
Teradata的表选项是GBase 8a所不支持的,迁移时直接去掉即可;对照表如下,供迁移时参考。

Teradata

Teradata描述

GBase 8a

GBase 8a描述

FALLBACK/NO FALLBACK

是否使用FALLBACK保护机制

JOURNAL/NO JOURNAL

有无流水日志

BEFORE JOURNAL /NO BEFORE JOURNAL

有无前项流水日志,数据变化前

AFTER JOURNAL/NO AFTER JOURNAL

有无后项流水日志,数据变化后

CHECKSUM = DEFAULT

CHECKSUM 是用来校验数据是否损坏的。DEFAULT是缺省项,可以再DBS程序中设置。不过,一般情况下DEFAULT为NONE选项,NONE选项不进行CHECKSUM计算,所以对性能没有任何印象

FREESPACE = 10 PERCENT

FREESPACE用来定义在每个磁盘柱面上保留的空间(0-75%)

DATABLOCKSIZE = 16384 BYTES

DATABLOCKSIZE用来指定数据块大小,最小的数据块为6144字节,最大的数据块是32256字节

DEFAULT MERGEBLOCKRATIO

默认合并块比

1.2.3 列选项
Teradata建表时的列选项与GBase 8a的列选项对照表如下,供迁移时参考。

Teradata

Teradata描述

GBase 8a

GBase 8a描述

DEFAULT

当字段无数据时用默认值来替代NULL

DEFAULT

当字段无数据时用默认值来替代NULL

WITH DEFAULT

用字段的系统默认值替换NULL

FORMAT

缺省的显示格式

TITLE

缺省的列标题

COMMENT

缺省的列标题

NOT NULL

不允许空值

NOT NULL

不允许空值

CASESPECIFIC

字母大小写敏感

UPPERCASE

字母大小写不敏感,内部用大写字母存储

COMPRESS

压缩值为NULL的字段存储空间为0

COMPRESS NULL

压缩值为NULL的字段存储空间为0

COMPRESS

压缩值为NULL和指定值的字段存储空间为0

CHARACTER SET LATIN

指定字段存储字符集

1.2.4 约束
Teradata建表时的约束项与GBase 8a的约束项对照表如下,供迁移时参考。

Teradata

Teradata描述

GBase 8a

GBase 8a描述

CONSTRAINT

约束名称

PRIMARY KEY

主键,非空,无重复值

PRIMARY KEY

主键,只兼容语法,无真实约束

UNIQUE

唯一

CHECK <条件>

指定合法值的范围

REFERENCES

外键

1.2.5 分布键
Teradata影响数据分布的为主索引,与GBase 8a在语法和约束存在一定的差异性,具体差异点如下:

语法:

TD:

UNIQUE PRIMARY INDEX <index_name> (col1,col2) #唯一

PRIMARY INDEX <index_name> (col1,col2) #非唯一

8a:

DISTRIBUTED BY (‘col1’,’col2’) #GBase字段名需要用引号括起来

差异

Teradata

GBase 8a

唯一性约束

支持

不支持

数据可发生变化

支持

不支持

指定时间类型作为分布键

支持

不支持

指定分布键名称

支持

不支持

1.2.6 导出表(Derived Table)
Teradata导出表特点如下:

1、对查询是本地的 - 存在于整个查询期间,查询结束后,表被丢掉;

2、并入SQL查询的语法;

3、查询完成后,Spool缓冲区的记录被丢掉;

4、不使用数据字典。

GBase 8a中没有导出表的概念,在sql中直接嵌套查询使用即可。

例:

TD中的导出表见如下标红部分:

SELECT last_name,

salary_amount,

department_number,

avgsal

FROM (SELECT AVG(salary_amount),

department_number

  FROM employee

GROUP BY department_number) my_temp(avgsal, deptno),

  employee ee

WHERE salary_amount > avgsal

AND department_number = deptno

ORDER BY 2 DESC;

8a中使用如下方式即可:

SELECT last_name,

salary_amount,

department_number,

avgsal

FROM (SELECT AVG(salary_amount) as avgsal,

department_number as deptno

   FROM employee

   GROUP BY department_number) my_temp,

employee ee

WHERE salary_amount > avgsal

AND department_number = deptno

ORDER BY 2 DESC;

1.3 复制表结构与数据
Teradata中建相同表结构的语法为:create multiset/set table tb1 as tb2 with no data/with data;

GBase 8a中对应写法为create table tb1 like tb2;/create table tb1 as select * from tb2;

注意:

1)在TD中建表时有关键字multiset和set,这两个关键字有不同含义,set表示该表不允许有重复记录,数据入表时会自动去重,而multiset是允许有重复记录的表。在迁移表结构带set关键字的表时,8a中只能通过sql来将去重后的数据插入表中,或者允许插入重复数据但是在使用该表时去重;

2)在8a中,create table … like…不能连带数据且不能指定字符集,create table … as …,如果连带分布键时需要指定分布键。

2 DML语法相关
2.1 简写
在Teradata中可使用SEL、INS、DEL来代替SELECT、INSERT、DELETE关键字,GBase 8a 不支持对上述关键字的简写,这个在迁移时可以进行批量替换。

2.2 关联update
Teradata和GBase 8a在关联update时,存在语法上的差异,主要体现在:①GBase 8a需在set字段前加上表的别名,Teradata不需要;② Teradata要比GBase 8a多一个from关键字。

例:

TD:update t1 from t2 set a=t2.a where a is not null;

8a:update t1,t2 set t1.a=t2.a where t1.a is not null;

3 函数的使用
本章节主要列举了Teradata中函数的使用与GBase 8a的异同。

3.1 同名且用法相同的函数
3.1.1 ORDER BY
Teradata和GBase 8a默认都是升序asc,区别在于空值的位置。

1)desc: TD空排在最后面,8a空排在最前面(迁移时要加nulls last)

2)asc: TD空排在最前面,8a空排在最后面(迁移时要加nulls first)

3.1.2 CASE WHEN
case when 的作用基本相同,但是在对字符类型做判断的时,TD和8a还是存在差异的:在TD中根据建表时字段是否指定敏感有关,如果指定了敏感,那么case when大小写是敏感的,反之不敏感;而在8a大小写是不敏感的。这里需要格外注意,会影响查询结果。

3.1.3 COALESCE函数
COALESCE函数在TD中的含义和用法与8a相同,其含义为返回值为列表当中的第一个非NULL 值,在全部为NULL 值的情况下返回值为NULL。

3.1.4 TRIM函数
TRIM函数用于去除字符数据中前头或后端的空格,TD和8a用法基本一致,TRIM函数的使用方法如下:

语法

意义

TRIM ()

去除字符数据中前后端的空格

TRIM (BOTH FROM )

同上

TRIM (TRAILING FROM )

去除后端的空格

TRIM (LEADING FROM )

去除前端的空格

3.1.5 EXTRACT函数
EXTRACT函数用于选取日期和时间中任意字段或任意间隔的值,TD中该函数用法和8a中用法相同,常用的一些用法如下表格:

用法

含义

EXTRACT(YEAR FROM DATE)

返回年份

EXTRACT(MONTH FROM DATE)

返回月份

EXTRACT(DAY FROM DATE)

返回日数

SELECT EXTRACT(HOUR FROM TIME)

返回小时数

SELECT EXTRACT(SECOND FROM TIME)

返回分钟数

3.1.6 ADD_MONTHS函数
ADD_MONTHS(date, number)函数是在一个日期上加上指定的月份数,在TD中的用法和8a中的用法相同。

3.1.7 ROW_NUMBER开窗函数
TD中row_number() over(partition by…order by…)的分析函数在8a中同样支持,用法和含义相同,但是需要注意是空值的排序问题:

1)TD和8a默认都是升序asc;

2)desc: TD空排在最后面,8a空排在最前面,迁移时要加desc nulls last;

3)asc: TD空排在最前面,8a空排在最后面,迁移时要加asc nulls first。

3.1.8 ABS函数
TD和8a的ABS函数用法相同,均为求数值的绝对值。

如:abs(-2)=abs(2)=2。

3.1.9 EXP函数
TD和8a的EXP函数用法相同,均为求e的幂数。

如:exp(2)=e2=7.39

3.1.10 LN函数
TD和8a中的LN函数用法相同,均为求自然对数。

如:ln(2)=0.69

3.1.11 SQRT函数
TD和8a的STRQ函数用法相同,均为求平方根。

如sqrt(9)=3。

3.1.12 SUBSTRING函数
TD中的使用格式为SUBSTRING(col1 FROM 1 FOR 1)。8a中对应的用法为SUBSTRING(col1 FROM 1 FOR 1)或SUBSTRING(col1,1,1)。

需要注意的是,TD和8a在某些场景下稍有不同,如下:

1)pos为负值,td是从-1位开始取数,8a是从倒数第一位开始取数

select substring(‘asdas’,-1,1);

td结果集:‘’

8a结果集:‘s’

2)pos为0,td是从0位开始取数,8a是从第一位开始取数

select substring(‘asdas’,0,1);

td结果集:‘’

8a结果集:‘a’

3)len缺省,pos前不带from,td不支持,8a支持

select substring(‘asdas’,-1);

td结果集:报错

8a结果集:‘s’

4)len缺省,pos前带from,td是从-1位开始取数,8a是从倒数第一位开始取数

select substring(‘asdas’ from -1);

td结果集:‘asdas’

8a结果集:‘s’

3.1.13 SUBSTR函数
substr函数在TD和8a中用法相同,均是对字符串进行截取,如substr(‘abc’,2,2)=‘bc’。

需要注意的是,TD和8a在某些场景下稍有不同,如下:

1)pos为负值,td是从-1位开始取数,8a是从倒数第一位开始取数

select substr(‘asdas’,-1,1);

td结果集:‘’

8a结果集:‘s’

2)pos为0,td是从0位开始取数,8a是从第一位开始取数

select substr(‘asdas’,0,1);

td结果集:‘’

8a结果集:‘a’

3)len缺省,pos前不带from,td是从-1位开始取数,,8a支持

select substr(‘asdas’,-1);

td结果集:‘asdas’

8a结果集:‘s’

4)len缺省,pos前带from,td不支持from,8a是从倒数第一位开始取数

select substr(‘asdas’ from -1);

td结果集:报错

8a结果集:‘s’

3.2 同名用法不同的函数
3.2.1 CAST对各种类型的转换
GBase 8a和Teradata都可以使用cast函数对时间、数值、符等类型进字行转换,但是在用法上略有不同,具体使用对照关系如下表:

类型

Teradata用法

GBase 8a用法

时间

CAST(col1 AS TIMESTAMP(0))

CAST(col1 AS datetime )

数值

CAST(col2 AS INTEGER)

CAST(col2 AS INTEGER)

字符

CAST(col2 AS VARCHAR(20) )

CAST(col2 AS VARCHAR(20) )

注意:Teradata中将数据转为integer后会在前面补全空格,补到11位,插入到char中会从前往后截取后再插入,所以会插入空格。GBase 8a插入的只有该值。

例如:Teradata中cast(‘2’ as integer)=’ 2’,会在前面补空格直到11位,当将此值插入到char(5)的列中时,进去的是空格而不是’2’。在GBase 8a中则是2。

3.2.2 RANK函数
Teradata中的rank(col1)函数,在GBase 8a中需要改写成rank() over(order by col1 desc nulls last),需要注意的是Teradata中的这种简写排序默认是降序,而GBase 8a是升序,改写时需要加上desc nulls last关键字。

另外需要注意,Teradata中的rank函数可带qualify字句限制排队输出的最终结果,其用法类似having,如:

SELECT storeid, prodid, sales, rank(sales)

FROM salestbl

GROUP BY storeid

QUALIFY rank(sales) <= 3;

在上面的sql中,GROUP BY子句不是做聚合,它实际上是改变查询的范围,也引起排序,排序是在组内。

GBase 8a中不直接支持这种写法,可进行如下改写:

SELECT *

FROM (SELECT storeid,

    prodid,

    sales,

rank() over(partition by storeid order by sales desc nulls last) ran_row

 FROM salestbl )t

WHERE ran_row <= 3;

3.2.3 CHAR函数
TD和8a的CHAR函数用法完全不同,TD是求长度,对应的是8a的length函数。

3.2.4 CHARACTER函数
TD和8a的CHARACTER函数用法完全不同,TD是求长度,对应的是8a的length函数。

3.3 不同名函数的等价改法
3.3.1 求幂运算
TD中幂的求法为2**3=8

8a中对应改法为pow(2,3)=8

3.3.2 TD中的LOG函数
TD中log函数返回某数值以10为底的对数,如log(10)=1。需要注意的是,8a中也有log函数,但是默认不是以10为底,而是等价于ln函数,log(2)=ln(2)=0.69。8a中需要使用log10对应TD中log函数。

例:

TD:log(10)

8a:log10(10)

3.3.3 TD中ZEROIFNULL函数
TD中的zeroifnull函数含义是在对数据做处理时,将空值作零处理,8a中使用ifnull函数来进行替换。如TD中zeroifnull(col1)等价于8a中ifnull(col1,0)。

3.3.4 TD中NULLIFZERO函数
TD中:nullifzero函数是将零值作空值处理,使用方法:zeroifnull(col1)。

8a中:可使用nullif(col1,0)函数进行处理,含义为当col1的值为0时返回null。

3.3.5 TD中的DATE和TIME函数
TD中DATE返回当前日期(yyyy/mm/dd),TIME返回当前时间(hh24:mi:ss),如select date,time;返回的是两个字段分别为当前日期和时间,8a中对应的写法分别为current_date和current_time。

3.3.6 TD中的INDEX函数
TD中index函数用来在一个字符串中定位一个子串的开始位置;在8a中可以替代的函数为instr函数。需要注意的是大小写敏感问题:TD是根据建表时字段是否指定敏感有关,8a大小写不敏感。

例:

insert into t3 values(‘AaBbCc’);select instr(a,‘c’) from t3;

td:根据建表时字段是否指定敏感有关,如果指定了敏感,返回6,没有指定返回5

8a:返回5

3.3.7 TD中FORMAT短语
TD中的FORMAT短语用于数据在输出时的格式化处理,但它并不影响数据的内部存储格式。FORMAT短语中常用的格式化字符主要如下:

1) $ 美元标识符

2) 9 数字位

3) Z 将数字中的前缀零去除

4) , 在指定位置插入逗号

5) . 指定小数点位置

6) - 在指定位置插入连字号

7) / 在指定位置插入斜线

8) % 在指定位置插入百分号

9) X 字符数据,每个X代表一个字符

10)G 图形数据.一个G代表一个逻辑字符(双字节)

11)B 在指定位置插入空格

FORMAT常用的日期显示格式列举如下,其中的B表示空格,如下:

1)YYYY/MM/DD

2)YYYY-MM-DD

3)YYYY.DDD

4)DBMMMBYYYY

5)MMBDD,BYYYY

6)YYYYBMMMBDD

7)YY/MM/DD

8)D-MM-YY

9)YBDDD

10)MM’

FORMAT比较常见的用法是对数字的补0和去0操作以及对日期的格式化,例如:

TD中01111(FORMAT’999999’)等价于01111(FORMAT’9(6)'),意思为将该值补0补齐六位,对应GBase的写法为lpad(01111,6,0)。

对一个日期的格式化TD中使用FORMAT ‘YYYY/MM/DD’,8a中使用TO_CHAR(col,‘yyyy/mm/dd’)。

FORMAT的用法在TD中比较广泛,迁移到8a时需要根据具体的不同用法进行对应修改,8a中的to_char函数基本可应对format短语的迁移,有时需要使用lpad来实现。

8a中to_char(number,[FORMAT])函数对数字格式化参数及含义如下表所示:

格式化参数

含义

一般作为分组符号使用,将number参数格式化为数位格式字符串输出,例如千位一分组,也可以按百位、十位一分组。通常与0、9、‚.‛配合使用。

示例:99,999。

.

将number参数格式化为小数形式的字符串输出。只能出现一次。通常与0、9、‚,‛配合使用。

示例:999.99。

$

转换为美元货币含义的字符串,只能出现在最前或最后。

示例:$999。

0

占位符,格式化number,如果参数number的位数少于格式化的位数,则显示0补足位。注意:0的优先级高于9。

示例:000。

9

占位符,格式化number,一旦参数number的位数,少于格式化的位数,则用空格补足位。

示例:999。

B、b

如果number的值为0,则替换为空格,可以出现在任意位置。

示例:B9.99

EEEE、eeee

按照科学计数法输出。

示例:9.99EEEE。

FM、fm

删除数字开头和结尾处的空格。

示例:FM909.9。

TME

按照科学计数法返回number。

X、x

转换为16进制。每个X代表16进制的一位。

例如:XX,代表两位16进制数。

如果number,转换成16进制数大于X的个数,则输出‚#‛。

注意:数值必须是大于等于0的整数。前面只能和0或者FM组合使用。

8a中to_char函数也可对日期进行格式化TO_CHAR(datetime,[FORMAT]),可对应TD中format对日期的格式化。具体如下表:

格式化参数

含义

, . ; :

除了左面标准的几个,还允许用文字作为分隔符号。例如年月日日期分隔符。用于格式化输出日期。

AD

即拉丁文 Anno Domini 的简写,表示公元,会根据 nls 的不同转换为公元或者AD 等。

如果是公元后的日期,显示 AD。

如果是公元前的日期,显示 BC。

AM

上午的简写,同 PM(下午),中文环境输出为上午。

如果是上午,返回 AM。

如果是下午,返回 PM。

BC

即拉丁文 Before Christ 的简写,表示公元前,会根据 nls 的不同转换为公元或者 BC 等。

如果是公元后的日期,显示 AD。

如果是公元前的日期,显示 BC。

CC

返回世纪,以阿拉伯数字表示。

D

一周之中的第几天,返回的是序号(1~7)。

DAY

返回日期中的 DAY 部分。返回的是英文全拼形式,首字母大写。

DD

同 DAY,但是返回的是数字形式(01~31)。

DDD

日期中的日是一年当中的第几天,返回的是序号 001~366。

DY

同 DAY,但是返回的是英文形式,返回前三个字母。首字母大写。

FF[n]

就是毫秒,如果不加数字就是用默认的精度,默认 6 位精度。1 ≤ n ≤ 9。只能用于 timestamp 类型的。

FM

删除日期开头和结尾处的空格。

FX

固定模式全局选项。

HH[12 | 24]

表示小时,默认 12 小时制。

HH12,12 小时制。返回(01~12)。

HH24,24 小时制。返回(00~23)。

IW

ISO 标准的一年中的第几周(1~52,或者 1~53)。

MI

返回分钟数(00~59)。

MM

返回月份,返回阿拉伯数字。

MON

返回月份,返回的是英文简写,三个英文字母,首字母大写。

MONTH

返回月份,返回的是英文全拼。首字母大写。

PM

下午的简写,中文环境输出为下午。

Q

返回季度,取值为 1~4。

RM

用罗马数字表示的月份。罗马数字全部大写。

RR或RRRR

返回 2 位或者 4 位年。

SCC

返回数字形式表示的世纪。

SS

返回秒(0~59)。

SSSSS

一天从午夜开始的累积秒数(0~86399)。

TS

返回带有 AM 或者 PM 的时分秒形式的时间。

W

一个月中的第几周,其算法局限在 datetime 参数所属于的月份之内而已。

WW

同 IW。

4 空串处理
本章主要讲述TD和8a在处理空串时的差别。

4.1 数值、时间类型字段插入空串
TD数据库中会将空串转化为系统的默认值,而8a默认情况下,对数据控制比较严格,大部分情况下会将空串认作为非法数据,SQL会报错;8a可通过开启非严格模式避免一些差异,但是不能完全避免( set sql_mode=PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH)。

4.1.1 int类型插空串
以下为int类型字段插入空串的几种场景,TD和8a互有差异:

建表语句:create table t1(a int);

1)insert into t1 values(‘’);

td:int插入空串,转化为0做插入

8a:在严格模式下,认为空串对于int是不合规的,sql报错;在非严格模式下,此sql将空串转化为0做插入

2)insert into t1 select ‘’ from t1;

td:int插入空串,转化为0做插入

8a:在严格模式下,认为空串对于int是不合规的,sql报错;在非严格模式下,此sql将空串转化为-2147483647做插入。(建议:如果在POC测试中要求核对数据,迁移时最好将int改成decimal default 0)

3)select a from t1 where a <> ‘’;

td:结果集非空非零

8a:在严格模式和非严格下,都认为空串对于int是不合规的,但结果集永为空

4.1.2 decimal类型插空串
以下为decimal类型字段插入空串的几种场景,TD和8a互有差异:

建表语句:create table t1(a decimal);

1)insert into t1 values(‘’);

td:decimal插入空串,转化为0做插入

8a:在严格模式下,认为空串对于decimal是不合规的,sql报错;在非严格模式下,空串转化为0做插入

2)insert into t1 select ‘’ from t1;

td:decimal插入空串,转化为0做插入

8a:在严格模式下,认为空串对于decimal是不合规的,sql报错;在非严格模式下,空串转化为0做插入

3)select a from t1 where a <> ‘’;

td:结果集非空非零

8a:在严格模式和非严格下,都认为空串对于decimal是不合规的,但结果集永为空

4.1.3 time类型插空串
以下为time类型字段插入空串的几种场景,TD和8a互有差异:

建表语句:create table t1(a time);

1)insert into t1 values(‘’);

td:time插入空串,转化为00:00:00做插入

8a:在严格模式下,认为空串对于time是不合规的,sql报错;在非严格模式下,空串转化为00:00:00做插入

2)insert into t1 select ‘’ from t1;

td:time插入空串,转化为00:00:00做插入

8a:在严格模式下,认为空串对于time是不合规的,sql报错;在非严格模式下,空串转化为00:00:00做插入

3)select a from t1 where a <> ‘’;

td:非空非’00:00:00’

8a:在严格模式和非严格下,都认为空串对于time是不合规的,但结果集永为空

4.1.4 timestamp 类型插空串
以下为timestamp类型字段插入空串的几种场景,TD和8a互有差异:

建表语句:create table t1(a timestamp);

1)insert into t1 values(‘’);

td:timestamp插入空串,认为空串对于timestamp是不合规的,sql报错;

8a: 在严格模式下,认为空串对于datetime是不合规的,sql报错;在非严格模式下,空串转化为0000-00-00 00:00:00做插入

2)insert into t1 select ‘’ from t1;

td:timestamp插入空串,认为空串对于timestamp是不合规的,sql报错;

8a: 在严格模式下,认为空串对于datetime是不合规的,sql报错;在非严格模式下,空串转化为0000-00-00 00:00:00做插入

3)select a from t1 where a <> ‘’;

td:认为空串对于timestamp是不合规的,sql报错

8a:在严格模式和非严格下,结果集都非空非’0000-00-00 00:00:00’

4)insert into t9 values(‘0000-00-00 00:00:00’);

td:认为数据不合规的,sql报错

8a:在严格模式下,认为数据不合规的,sql报错;在非严格模式下,可以做插入

4.1.5 date类型插空串
以下为date类型字段插入空串的几种场景,,TD和8a互有差异:

建表语句:create table t1(a date);

1)insert into t1 values(‘’);

td:认为空串对于date是不合规的,sql报错

8a:在严格模式下,认为空串对于date是不合规的,sql报错;在非严格模式下,空串转化为0000-00-00做插入

2)insert into t1 select ‘’ from t1;

td:认为空串对于date是不合规的,sql报错

8a:在严格模式下,认为空串对于date是不合规的,sql报错;在非严格模式下,空串转化为0000-00-00做插入

3)select a from t1 where a <> ‘’;

td:认为空串对于date是不合规的,sql报错

8a:在严格模式和非严格下,非空非’0000-00-00’

4)insert into t9 values(‘0000-00-00’);

td:认为数据不合规的,sql报错

8a:在严格模式下,认为数据不合规的,sql报错;在非严格模式下,可以做插入

4.2 字符类型空串、空格的区别
在TD中空串、一个空格、多个空格都是等价的,在8a中三者是不等价的。当数据中有字符和空格混合的情况下,TD中字段数据右边的空串、一个空格、多个空格都是等价的,左边是非等价的。

例:

1)等值:select a,chars(b) from t4 where b=‘’;

td结果集:b = 空串、单个空格、多个空格

8a结果集:b = 空串

2)不等值:select a,chars(b) from t4 where b<>‘’;

td结果集:b <> 空串、单个空格、多个空格、NULL

8a结果集:b <> 空串、NULL

3)关联(右空格):insert into t4 values(1,‘A’); insert into t5 values(2,'A ');select a.,b. from t4 a inner join t5 b on b.b=a.b;

td结果集:可关联

8a结果集:不可关联

4)关联(左空格):insert into t4 values(1,‘A’); insert into t5 values(2,’ A ');select a.,b. from t4 a inner join t5 b on b.b=a.b;

td结果集:不可关联

8a结果集:不可关联

5 不同类型字段的数据交换和关联
5.1 int和date字段的交互和关联
在TD中date类型数据实际上就是数值型,二者之间是可以直接转化和关联的;而在8a中只有在数据交互的时候可以转化,关联时没有隐式转换,且TD的转化需要作-19000000的运算,8a不需要;详情参考以下三个场景:

例:

建表语句:create table t1(a date); create table t2(a int);

1)数值插入date: insert into t1 values(19921010);

td:t1存入3892/10/10,如果插入1992/10/10,insert语句应为insert into t1 values(19921010-19000000);

8a:在严格模式和非严格下,t1都存入1992-10-10

2)int插入date: insert into t1 select a from t2 where a=19921010;

td: t1存入3892/10/10,如果插入1992/10/10,insert语句应为insert into t1 select a-19000000 from t2 where a=19921010

8a:在严格模式和非严格下,t1都存入1992-10-10

3)int和date关联:select a.,b. from t1 a left join t2 b on a.a=b.a;

td:可以关联

8a:在严格模式和非严格下,都认为数据类型不匹配,sql报错;

5.2 int/decimal和varchar字段的关联
TD和8a都能实现数值型和字符型的关联,主要区别在于1和001,以下从三个例子来讲述TD和8a的区别。

例:

建表语句:create table t1(a int); create table t2(a varchar(23));

插入数据:insert into t1 values(1);insert into t2 values(‘1’);insert into t2 values(‘001’);

1)select a.,b. from t1 a inner join t2 b on a.a=b.a;

td:可以关联,1和001都被查出

8a:可以关联,1和001都被查出

2)select * from t2 where a=1;

td:1和001都被查出

8a:1被查出

3)select * from t2 where a=‘1’;

td:1被查出

8a:1被查出

6 超范围数据的处理
6.1 decimal类型插入超范围数据
在TD中对于精度舍入的规则为四舍六入五成双(奇进偶不进),在8a中为四舍五入。

例:

1)create table t1(a decimal(5,3));insert into t1 values(23.3365);

td结果集:23.336

8a结果集:23.337

2)create table t1(a decimal(5,3));insert into t1 values(23.3375);

td结果集:23.338

8a结果集:23.338

6.2 字符类型插入超范围数据
在TD中,字符串类型插入超范围数据,直接作截断处理,而8a中只在非严格模式下,才会做截断处理。

例:

create table t1(a varchar(3));insert into t1 values(‘dasadasd’);

td结果集:插入’das’

8a结果集:严格模式:超长报错;非严格模式:插入’das’

7 SQL语法上的使用差异
7.1 字符型的列等于数值时的强转
TD中字符型的列在sql条件中可以直接等于一个数值,如某条记录的col1的值为’001234’,而sql中写的条件为col1=1234是成立的可以找到该条记录。

8a中这样是找不到该条记录的,需要写成to_number(col1)=1234方可。

7.2 别名依赖
TD中支持投影列中表达式的别名作为列名参与后续运算,如别名可以直接在投影列中、在where条件中、在关联条件中等使用。目前,8a也已经兼容这项功能,需要保证参数:_t_gcluster_support_alias_dependent=1,默认是开启的;但是olap函数中,别名依赖是不生效的,如下:

SELECT substring(storeid,1,6) as sroid ,sales

FROM salestbl

QUALIFY row_number() over(partition by sroid order by sales desc) =1 ;

这种在8a中是不支持的,需要手动进行修改为:

SELECT substring(storeid,1,6) as sroid ,sales

FROM salestbl

QUALIFY row_number() over(partition by substring(storeid,1,6) order by sales desc nulls last) =1 ;

7.3 TD中sql语句以’;‘开始的含义
在TD中一个文本中多条sql语句时,如果有sql是以’;'开始,则该sql和其前面的sql是同时执行的,例如:

select … from …

;select … from …

;

则在执行这个文本里的内容时这两个sql是并行同时执行的。

7.4 TD中的WITH RECURSIVE…递归语法
TD中可以根据用户自己的需要定义任意的递归循环语法,例如:

WITH RECURSIVE

table1…AS…

(

select…from… – sql1

union all

select … From table1 … – sql2

)

select * from table1;

该类型的sql含义为根据sql1为基准产生的临时数据放入table1中,为递归的第一次循环,再根据sql2从table1中的数据来进行递归,每次递归的数据都是根据前一次递归产生的数据,直到最终循环的内容没有数据为止。

这种递归语法8a中不能直接支持,需要通过存储过程来修改替代,替代的大概步骤如下:

create table table1 … as select … from …; – 第一步生成临时表table1,同TD中的sql1

set row_count=1;

while row_count>0 do – 开始循环

set i=i+1;

insert into PEEL_MAP_TABLE

SELECT …

FROM table1

WHERE ... and row_num=i-1;    -- 每次递归的数据都是根据前一次递归产生的数据

set row_count=row_count();

end while;

7.5 TD中的QUALIFY语句
在TD中,有一种特有的语法qualify,用于olap函数的刷选,它类似于where、having,所处的位置为:where>having>qualify。目前,8a也已经支持qualify语句,但须要注意以下情况。

例:

SELECT storeid, prodid, sales, rank(sales)

FROM salestbl

GROUP BY storeid

QUALIFY rank(sales) <= 3;

在上面的sql中,GROUP BY子句不是做聚合,它实际上是改变查询的范围,也引起排序,排序是在组内。8a中不直接支持这种写法,可进行如下改写:

SELECT storeid,

   prodid,

   sales,

rank() over(partition by storeid order by sales desc nulls last)

FROM salestbl

QUALIFY rank() over(partition by storeid order by sales desc nulls last) <= 3;

8 开窗函数
TD中有部分开窗函数功能,是8a所不具备的,只能通过创建存储过程或者建临时表等进行实现的,是个较为复杂的改写过程。以下为改写方案,具体迁移案例见附件。

函数名

含义

改写方案

CSUM

开窗累计和

存储过程改写 或者 自关联不等值join改写

MAVG

开窗移动平均值

LAG+case when改写 或者 自关联不等值join改写

MDIFF

开窗移动差值

LAG函数改写

MLINREG

开窗线性回归预测值

暂无改写方案

MSUM

开窗移动求和

同MAVG

QUANTILE

开窗分位数

CEIL(rn / @countn * 100)方式改写

QUALIFY

相当于OLAP中的having子句

嵌套子查询+where条件改写

PERCEDING/FOLLOWING

开窗函数关键字

GBase 8a不支持只能用LEAD和LAG尝试进行改写

9 UDF
TD中的部分8a不支持或不同名的函数,可通过UDF的形式实现迁移,目前已经完成的UDF如下表:详细请见附件。

TD

8a

months_between

无对应函数,使用UDF

nullifzero

对应函数为nullif,使用UDF可减少迁移量

zeroifnull

对应函数为ifnull,使用UDF可减少迁移量

random

无对应函数,使用UDF

nvl2

无对应函数,使用UDF

width_bucket

无对应函数,使用UDF

substring

当pos为负值时,使用UDF,否则结果集会有问题,除此之外可使用8a自身的substring

www.htsjk.Com true http://www.htsjk.com/teradata/45712.html NewsArticle Teradata到GBase 8a迁移总结,在无文档参考的情况下 Teradata到GBase 8a迁移总结 目录 1 DDL语法相关 1.1 字段类型 1.2 建表语句 1.2.1 表类型 1.2.2 表选项 1.2.3 列选项 1.2.4 约束 1.2.5 分布键 1.2.6 导...
评论暂时关闭