技术开发 频道

专家点评:达梦6.0试用之数据类型

  【IT168 独家

  编者言:在4月份举办的2010中国数据库与商业智能技术大会上,国产数据库的代表厂商达梦高调亮相,给一向由国外厂商把持的企业商业数据库市场带来不小的波澜。人们开始纷纷将目光投向国产数据库软件市场,开始关注由中国人自己开发的数据库产品。

  国产数据库产品究竟能不能用?在功能和特性上够不够用?为了解开这些疑问,我们特邀请在数据库业界众多知名的技术专家亲身试用相关产品,并真实地写出自己的试用感受。这些专家大都是Oracle数据库的ACE,或者是对其它主流的商业数据库十分精通和了解,让他们站在这样的角度来客观写出自己对国产数据库的技术评测,是非常有说服力的。

  尽管各位专家的工作都十分繁忙,但他们还是都认为,将国产数据库软件在技术上的真实情况书写出來,给出自己中肯的评价,这是一件非常有意义的工作。 更令人欣慰的是,相比过去,今天像达梦这样的国产数据库产品已经显得非常自信,它们希望听到业界技术专家的建议甚至是批评,不断完善自己的产品和功能,这将是一个非常良性的循环,长此下去,我们相信,摆在国产数据库脚下的将是更为宽广的道路!

  作者简介:杨廷琨(网名Yangtingkun),现任海虹医药电子商务有限公司首席DBA, ITPUB论坛Oracle数据库管理版版主,知名社区技术专家。2004年曾参与编写《Oracle数据库性能优化》一书,2007年被Oracle公司授予Oracle ACE称号,喜欢研究Oracle相关的技术问题,他的技术博客上积累了1500多篇Oracle相关的原创技术文章。

  前几天ITPUB的熊主编和我联系,希望我能参加国产数据库达梦的试用活动,并写几篇使用感受。本来最近手头的事情比较多,本打算推辞的,不过熊主编再三邀请,而且强调并非是枪手文,只要写出真实使用感受即可。既然如此,我就本着支持国产数据库的原则,写几篇试用感受。

  由于本人唯一熟悉的数据库就是Oracle,因此所有的对比都是与Oracle数据库进行对比,在这个过程中,将尽可能避免将对Oracle数据库的喜爱之情带进来,争取站在一个比较公正的位置上来进行评价。

  这一篇简单介绍达梦数据库提供的数据类型。

  登陆达梦数据库:

C:\dmdbms\bin>isql
isql V6.
0.2.51-Build(2009.12.23)
SQL
>login
server name:localhost
user name:test
password:
port:
12345
dm_login time used:
190.370(ms)

  首先看一下字符类型CHAR和VARCHAR:

SQL>create table t_type
2   (id number, name varchar2(30));
create table t_type
(id
number, name varchar2(30));
time used:
436.197(ms) clock tick:729306570.
SQL
>create table t_char(col char(8000));
create table t_char(col char(8000));
列定义长度超长.error code
= -1334
SQL
>create table t_char(col char(4000));
create table t_char(col char(4000));
列定义长度超长.error code
= -1334
SQL
>create table t_char(col char(3000));
create table t_char(col char(3000));
time used:
20.943(ms) clock tick:35001630.

  达梦为了兼容Oracle的字符类型,因此VARCHAR2这种Oracle特殊的类型也是支持的。和Oracle不同的是,CHAR类型和VARCHAR类型的最大长度都是8188,但是这个值并不是固定的,当数据库页面大小不同的时候,这个最大值也是不固定的,比如32K页面大小,字符类型CHAR或VARCHAR的最大值是8188,而如果是16K页面大小,则字符类型最大值是8000,对于当前8K页面大小,字符类型最大值只有3900,而如果页面大小为4K,则字符类型最大长度只要1900。

  对于Oracle数据库而言,CHAR类型最大值是2000而VARCHAR2是4000,虽然达梦数据库绝大部分情况下,都比这个范围要大,不过个人并不认为这是一个很好的设计。不同数据库之前的迁移对于一个成熟系统而言是很常见的,而不同数据库的页面大小不同也是很平常的事情,达梦的这种设计虽然使得不同页面的最大值尽量扩大,但是却给不同页面间数据库的迁移埋下了问题。当数据库向页面更大的数据库迁移不会存在问题,但是反之可能造成表无法创建、数据丢失或数据被截断的情况。

  而且感觉达梦数据库在实现VARCHAR类型的时候还有一定的问题:

SQL>insert into t_type values (1, 'a ');
insert into t_type values (1, 'a ')
1 rows affected
time used:
0.464(ms) clock tick:765250.
SQL
>select id, name || 'a' from t_type;
select id, name || 'a' from t_type;
id
1       1       a a
1 rows got

 

  至此没有问题,VARCHAR类型中的空格被保留,但是对VARCHAR类型进行查询的时候:

SQL>select * from t_type where name = 'a ';
select * from t_type where name = 'a ';
id              name
1       1       a
1 rows got
time used:
29.588(ms) clock tick:49459510.
SQL
>select * from t_type where name = 'a';
select * from t_type where name = 'a';
id              name
1       1       a
1 rows got
time used:
0.314(ms) clock tick:517060.
SQL
>select * from t_type where name = 'a    ';
select * from t_type where name = 'a    ';
id              name
1       1       a
1 rows got
time used:
0.421(ms) clock tick:694830.

 

  显然在比较的时候,空格是没有被考虑在内的,这对于CHAR类型是没有问题的,但是VARCHAR类型似乎并不应该具有这样的特性:

SQL>insert into t_type values (2 ,'a');
insert into t_type values (2 ,'a')
1 rows affected
time used:
0.401(ms) clock tick:661320.
SQL
>select * from t_type
2   where name = 'a';
select * from t_type
where name = 'a';
id              name
1       1       a
2       2       a
2 rows got
time used:
0.397(ms) clock tick:653730.
SQL
>alter table t_type add primary key (name);
alter table t_type add primary key (name);
违反唯一性约束.error code
= -3100

 

  显然在达梦中即使VARCHAR类型的字段也认为’a’和’a_’(这里用下划线来标识空格)是相等的,这种情况会引发歧义,我们认为已经相等的数据在经过相同的处理后就会变得又不相等了:

SQL>select id, name || 'a' from t_type;
select id, name || 'a' from t_type;
id
1       1       a a
2       2       aa
2 rows got
time used:
36.391(ms) clock tick:60834180.

  下面看看数值类型:

SQL>create table t_num
2   (c1 number,
3   c2 number(4, 1),
4   c3 number(4, -1),
5   c4 number(2, 3));
第4行:
'-'附近有语法错误
SQL
>create table t_num
2   (c1 number,
3   c2 number(4, 1),
4   c4 number(2, 3));
create table t_num
(c1
number,
c2
number(4, 1),
c4
number(2, 3));
无效的数据类型.error code
= -2520
SQL
>create table t_num
2   (c1 number,
3   c2 number(4, 1));
create table t_num
(c1
number,
c2
number(4, 1));
time used:
42.803(ms) clock tick:71554500.

  虽然达梦支持数值类型NUMBER和Oracle的NUMBER类型十分相似,但是二者还是有区别的,显然达梦不支持标度小于0的情况,而且不支持精度小于标度的情况,而这些情况在Oracle中都是支持的,下面是Oracle中的情况:

SQL> create table t_num
  
2  (c1 number,
  
3  c2 number(4, 1),
  
4  c3 number(4, -1),
  
5  c4 number(2, 3));
表已创建。
SQL
> insert into t_num
  
2  values (1, 234.4, 3225, 0.023);
已创建
1 行。
SQL
> select * from t_num;
        C1         C2         C3         C4
---------- ---------- ---------- ----------
         1      234.4       3230       .023

  虽然NUMBER类型和Oracle的NUMBER类型并不完全一致,但是二者对于精度和标度的描述还是一致的。不过Oracle如果NUMBER不指定精度,则默认是38,而在达梦中,默认是20。

SQL>insert into t_num values
2   (1234567890123456789012, 123.1);
insert into t_num values
(
1234567890123456789012, 123.1)
数据溢出.error code
= -2502
SQL
>create table t_num2
2   (c1 number(*, 0));
第2行:
'*'附近有语法错误

  另外达梦中也不支持NUMBER(*, 0)的写法。

  达梦和SQLSERVER、SYBASE等数据库一样,对于表示整数的数据类型实现了自增列:

SQL>CREATE TABLE T_INC
2   (ID NUMBER(5, 0) IDENTITY (1, 2),
3   NAME VARCHAR);
CREATE TABLE T_INC
(ID
NUMBER(5, 0) IDENTITY (1, 2),
NAME
VARCHAR);
time used:
15.516(ms) clock tick:25924810.
SQL
>INSERT INTO T_INC (NAME)
2   VALUES ('A');
INSERT INTO T_INC (NAME)
VALUES ('A')
1 rows affected
time used:
36.438(ms) clock tick:60908390.
SQL
>INSERT INTO T_INC (NAME)
2   VALUES ('B');
INSERT INTO T_INC (NAME)
VALUES ('B')
1 rows affected
time used:
0.655(ms) clock tick:1082480.
SQL
>SELECT * FROM T_INC;
SELECT * FROM T_INC;
ID              NAME
1       1       A
2       3       B
2 rows got
time used:
1.769(ms) clock tick:2943530.

  接着看看达梦数据库的时间类型:

SQL>create table t_date
2   (day date, tim time, o_date datetime);
create table t_date
(
day date, tim time, o_date datetime);
time used:
60.083(ms) clock tick:100448590.
SQL
>insert into t_date
2   values ('2010-04-01', '16:22:57', to_date('2010-4-1 16:22:57', 'yyyy-mm-dd h
h24:mi:ss
'));
insert into t_date
values ('2010-04-01', '16:22:57', to_date('2010-4-1 16:22:57', 'yyyy-mm-dd hh24:
mi:ss
'))
1 rows affected
time used:
56.728(ms) clock tick:94839380.
SQL
>select * from t_date;
select * from t_date;
day             tim             o_date
1       2010-04-01      16:22:57.000000 2010-04-01 16:22:57.000000
1 rows got
time used:
0.501(ms) clock tick:828690.

  达梦数据库中的DATE和Oracle中的DATE有本质的区别,这一点似乎和SQLSERVER中的DATE类型比较相似。它把日期和时间分成了两个部分,对应两种不同的类型DATE和TIME,DATE的精度只到天,而TIME的精度到毫秒。达梦中也有即包括年月日也包括时分秒的数据类型DATETIME,也就是TIMESTAMP类型。不过这个类型和Oracle的DATE不同,它包含毫秒信息,相比较和Oracle的TIMESTAMP类型更相似一些,不过Oracle的TIMESTAMP不但支持到微秒,而且还可以包含时区的信息。

  还有一点也是达梦的时间类型所不支持的,公元前的日期:

SQL>insert into t_date
2   (day) values ('-235-4-1');
insert into t_date
(
day) values ('-235-4-1')
非法的时间日期类型数据.error code
= -2519
SQL
>insert into t_date
2   (o_date) values (to_date('-235-4-1', 'syyyy-mm-dd'));
insert into t_date
(o_date)
values (to_date('-235-4-1', 'syyyy-mm-dd'))
无效的时间格式掩码.error code
= -2528

  达梦支持多种INTERVAL类型的时间,虽然提供的类型比Oracle提供的要多很多,但是本质上并没有增加什么额外的新类型。有一点需要注意,两个Oracle日期类型相减后得到的是一个NUMBER类型的数值,表示的是两个日期相差的天数,而达梦中得到的是INTERVAL类型。

  下面简单介绍一下大字段类型,在达梦数据库中被称为多媒体类型:

SQL>create table t_text
2   (c1 text, c2 blob, c3 clob);
create table t_text
(c1
text, c2 blob, c3 clob);
time used:
139.863(ms) clock tick:233839160.

  TEXT类型类似Oracle中的LONG,不过没有LONG那么多的限制。TEXT、BLOB和CLOB的最大长度都是2G-1,相当于Oracle LONG字段的长度,比8i中的BLOB和CLOB长度小了一半。在达梦数据库中没有BFILE对应的数据类型。

  达梦还提供了Oracle在SQL类型中没有支持的BOOLEAN类型:

SQL>create table t_bool
2   (col boolean);
create table t_bool
(col boolean);
time used:
66.991(ms) clock tick:111995500.
SQL
>insert into t_bool values (true);
insert into t_bool values (true)
1 rows affected
time used:
0.538(ms) clock tick:889960.
SQL
>insert into t_bool values (0);
insert into t_bool values (0)
1 rows affected
time used:
0.393(ms) clock tick:647120.
SQL
>insert into t_bool values (null);
insert into t_bool values (null)
1 rows affected
time used:
0.337(ms) clock tick:555060.
SQL
>select * from t_bool;
select * from t_bool;
col
1       1
2       0
3       NULL
3 rows got
time used:
37.112(ms) clock tick:62038100.
SQL
>select * from t_bool where col & 0 = 0;
select * from t_bool where col & 0 = 0;
col
1       1
2       0
2 rows got
time used:
22.225(ms) clock tick:37149920.
SQL
>select * from t_bool where col | 1 = 1;
select * from t_bool where col | 1 = 1;
col
1       1
2       0
2 rows got
time used:
14.423(ms) clock tick:24106790.

  TEXT类型类似Oracle中的LONG,不过没有LONG那么多的限制。TEXT、BLOB和CLOB的最大长度都是2G-1,相当于Oracle LONG字段的长度,比8i中的BLOB和CLOB长度小了一半。在达梦数据库中没有BFILE对应的数据类型。

  达梦还提供了Oracle在SQL类型中没有支持的BOOLEAN类型:

  可以看到,达梦数据库对于NULL的布尔逻辑判断和Oracle中是不同的,在Oracle中,NULL & 0结果是FALSE,而NULL | 1结果是TRUE。在达梦中,NULL进行任何布尔运算的结果都仍然是NULL。

  此外达梦数据库对于位操作提供了很多方便的函数,比如按位与、按位或、异或等,在位操作方面确实比Oracle提供的函数要全面得多。

0
相关文章