達夢6.0試用之資料型別

yangtingkun發表於2010-07-18

前幾天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)

首先看一下字元型別CHARVARCHAR

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頁面大小,字元型別CHARVARCHAR的最大值是8188,而如果是16K頁面大小,則字元型別最大值是8000,對於當前8K頁面大小,字元型別最大值只有3900,而如果頁面大小為4K,則字元型別最大長度只要1900

對於Oracle資料庫而言,CHAR型別最大值是2000VARCHAR24000,雖然達夢資料庫絕大部分情況下,都比這個範圍要大,不過個人並不認為這是一個很好的設計。不同資料庫之前的遷移對於一個成熟系統而言是很常見的,而不同資料庫的頁面大小不同也是很平常的事情,達夢的這種設計雖然使得不同頁面的最大值儘量擴大,但是卻給不同頁面間資料庫的遷移埋下了問題。當資料庫向頁面更大的資料庫遷移不會存在問題,但是反之可能造成表無法建立、資料丟失或資料被截斷的情況。

而且感覺達夢資料庫在實現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.

雖然達夢支援數值型別NUMBEROracleNUMBER型別十分相似,但是二者還是有區別的,顯然達夢不支援標度小於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型別和OracleNUMBER型別並不完全一致,但是二者對於精度和標度的描述還是一致的。不過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)的寫法。

達夢和SQLSERVERSYBASE等資料庫一樣,對於表示整數的資料型別實現了自增列:

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.

達夢資料庫中的DATEOracle中的DATE有本質的區別,這一點似乎和SQLSERVER中的DATE型別比較相似。它把日期和時間分成了兩個部分,對應兩種不同的型別DATETIMEDATE的精度只到天,而TIME的精度到毫秒。達夢中也有即包括年月日也包括時分秒的資料型別DATETIME,也就是TIMESTAMP型別。不過這個型別和OracleDATE不同,它包含毫秒資訊,相比較和OracleTIMESTAMP型別更相似一些,不過OracleTIMESTAMP不但支援到微秒,而且還可以包含時區的資訊。

還有一點也是達夢的時間型別所不支援的,公元前的日期:

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那麼多的限制。TEXTBLOBCLOB的最大長度都是2G-1,相當於Oracle LONG欄位的長度,比8i中的BLOBCLOB長度小了一半。在達夢資料庫中沒有BFILE對應的資料型別。

達夢還提供了OracleSQL型別中沒有支援的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.

可以看到,達夢資料庫對於NULL的布林邏輯判斷和Oracle中是不同的,在Oracle中,NULL & 0結果是FALSE,而NULL | 1結果是TRUE。在達夢中,NULL進行任何布林運算的結果都仍然是NULL

此外達夢資料庫對於位操作提供了很多方便的函式,比如按位與、按位或、異或等,在位操作方面確實比Oracle提供的函式要全面得多。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-668348/,如需轉載,請註明出處,否則將追究法律責任。

相關文章