原文链接:www.gbase.cn/community/p...
更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。
今天,我们将探讨使用CREATE DISTINCT TYPE语句来创建distinct数据类型(单值数据类型)。这种数据类型是基于现有的内置数据类型或其他已定义的复杂数据类型(如不透明类型、命名ROW类型或Distinct类型)创建的。Distinct数据类型与其源类型在物理存储上具有相同的表示法,但在逻辑上是完全独立的,它们不能直接进行比较或操作,除非通过显式强制转型。
CREATE DISTINCT TYPE 语句简介
语法图如下:

参数说明:
元素 | 描述 | 限制 |
---|---|---|
distinct_type | distinct数据类型声明的名称 | 在兼容ANSI的数据库中,所有者和数据类型的组合在数据库中必须是唯一的。在不兼容ANSI的数据库中,名称在数据库中的数据类型名称中必须是唯一的 |
source_type | 新类型所基于的现有类型名称 | 必须为内置数据类型或用CREATE DISTINCT TYPE、CREATE OPAQUE TYPE或CREATE ROW TYPE语句创建的类型 |
使用说明
(1)Distinct类型是基于内置数据类型或现有不透明数据类型、命名ROW数据类型或其它Distinct数据类型创建的数据类型。Distinct数据类型是强归类的。虽然它与其源类型对数据有相同的物理表示法,但两种类型的值在没有显式强制转型的情况下无法进行比较。
(2)要创建Distinct数据类型,必须拥有对数据库的Resource权限。任何拥有Resource权限的用户均可从内置数据类型创建Distinct类型。
注意:不能在SERIAL、BIGSERIAL或SERIAL8数据类型上创建Distinct类型。
sql
> CREATE DISTINCT TYPE test_serial AS SERIAL;
9656: Cannot create a distinct type of type (serial)
Error in line 1
Near character position 41
要基于不透明类型、命名ROW类型或另一Distinct类型创建Distinct类型,必须是该数据类型的所有者 或对该数据类型拥有Usage权限。
缺省情况下,定义了Distinct类型后,该Distinct类型的所有者和DBA可以使用它。Distinct类型的所有者可将对该Distinct类型的Usage权限授予其他用户。
(3)Distinct类型与其源类型有相同的存储结构。以下语句创建了基于内置DATE数据类型的Distinct类型birthday:
sql
> CREATE DISTINCT TYPE birthday AS DATE;
Distinct type created.
虽然GBase8s对Distinct类型使用和它的源类型相同的存储格式,但Distinct类型与其源类型不能在一个操作中进行比较,除非显式强制转型到另一个类型。
如果包含了IF NOT EXISTS关键字,当指定名称的Distinct数据类型已经在当前数据库中定义过,则数据库服务器不采取任何操作(而不是向应用程序发送异常)。
sql
> CREATE DISTINCT TYPE IF NOT EXISTS birthday AS DATE;
Distinct type created.
> CREATE DISTINCT TYPE birthday AS DATE;
9996: Distinct type (gbasedbt.birthday) already exists in database.
Error in line 1
Near character position 36
对Distinct类型的权限
要创建Distinct类型,必须拥有对该数据库的Resource权限。创建Distinct类型的所有者对此类型拥有Usage权限。使用GRANT或REVOKE语句可以向其它数据库用户授予或收回Usage权限。
要找出特定类型上存在哪些特权,请在sysxtdtypes系统目录表中检查所有者名称,并在sysxtdtypeauth系统目录表中检查已授予的其它数据类型特权。有关系统目录表的更多信息,请参阅《GBase8sSQL指南:参考》。
DB-Access实用程序也可显示对Distinct类型的特权。
sysxtdtypes系统目录表
sysxtdtypes系统目录表中,存放了数据库中定义的每个 UDT(用户定义的数据类型),这些类型包括不透明和单值数据类型以及复杂数据类型(命名 ROW 类型、未命名 ROW 类型和 COLLECTION 类型)。参数说明如下:
列 | 类型 | 描述 |
---|---|---|
extended_id | serial | 扩展数据类型的唯一标识代码 |
domain | char(1) | UDT的域代码 |
mode | char(1) | 对UDT进行分类的代码:B = 基本(不透明)类型C = 集合类型或未命名ROW类型D = 单值类型R = 命名ROW类型' '(空白)= 内置类型 |
owner | char(32) | UDT所有者的名称 |
name | varchar(128,0) | UDT的名称 |
type | smallint | 对UDT分类的代码 |
source | integer | sysxtdtypes引用(仅适用于单值类型)零(0)指示从内置数据类型创建了单值UDT。 |
maxlen | integer | 可变长度数据类型的最大长度零指示固定长度UDT。 |
length | integer | 固定长度数据类型的长度(以字节计);零指示可变长度UDT。 |
byvalue | char(1) | "T"= UDT通过值传递"F"= UDT不通过值传递 |
cannothash | char(1) | "T"= UDT可通过缺省散列函数散列"F"= UDT不可通过缺省函数散列 |
align | smallint | UDT的对齐方式(=1、2、4或8) |
locator | integer | 未命名ROW类型的定位器键 |
pkg | varchar(128,0) | 定义该类型的包名 |
每个扩展数据类型都用唯一标识符(称为扩展标识符(extended_id))、数据标识符(type)以及长度和数据库类型的描述来作为特征。
对于使用内置数据类型创建的单值类型,type列代码对应于SYSCOLUMNS中列出的syscolumns.coltype列(指示源类型)的值,但要加上一个十六进制值0x0000800。文件$GBASEDBTDIR/incl/esql/sqltypes.h包含有关sysxtdtypes.type和syscolumns.coltype代码的信息。
示例如下:
sql
> select * from sysxtdtypes where name='birthday';
extended_id 2048
domain
mode D
owner gbasedbt
name birthday
type 2055
source 0
maxlen
length 4
byvalue T
cannothash F
align 1
locator 0
pkg
1 row(s) retrieved.
> select * from sysxtddesc where extended_id=2048;
extended_id 2048
seqno 1
description date
1 row(s) retrieved.
支持函数和强制转型
当创建Distinct类型时,GBase8s自动定义两种显式强制转型:
(1)从Distinct类型到其源类型的强制转型
(2)从源类型到Distinct类型的强制转型
因为这两个数据类型具有相同的表示法(相同的长度和对齐方式),所以实现以上强制转型不需要支持函数。
可以在Distinct类型与其源类型之间创建隐式强制转型。要创建隐式强制转型,请使用Table Options子句来指定外部数据的格式。注意,需要先删除Distinct类型与其源类型之间的缺省显式强制转型。
在源类型上定义的所有支持函数和强制转型可用于Distinct类型,但对Distinct类型定义的强制转型和支持函数对源类型不可用。请使用Table Options子句指定外部数据的格式。
操纵Distinct类型
当将Distinct类型与其源类型进行比较或操纵它们的数据时,在以下情况中必须显式地将一种类型强制转型为另一类型:
(1)使用一种类型的值插入或更改另一类型的列。
(2)使用关系运算符来加、减、乘、除、比较或以其它方式操作两个值,其中一个是源类型,另一个是Distinct类型。
示例: 使用版本- GBase8sV8.8_TL_3.5.1_3X1_3
假设基于NUMERIC数据类型,创建了Distinct类型dist_type。然后创建带有两列的表tb1,一个属于dist_type类型,一个属于NUMERIC类型,如下所示:
sql
> CREATE DISTINCT TYPE dist_type AS NUMERIC;
Distinct type created.
> CREATE TABLE tb1(col1 dist_type, col2 NUMERIC);
Table created.
> info columns for tb1;
Column name Type Nulls
col1 dist_type yes
col2 decimal(16) yes
要直接将Distinct类型与其源类型进行比较或者将源类型的值分配到Distinct类型的列上,必须将一种类型强制转型到其它类型,如下所示:
sql
> INSERT INTO tb1 (col1) VALUES (3.5::dist_type);
1 row(s) inserted.
> INSERT INTO tb1 (col1, col2) VALUES (4.5::dist_type, 4.5);
1 row(s) inserted.
> INSERT INTO tb1 (col1, col2) VALUES (5.5,5.5);
9632: Value does not match the type of column (col1).
Error in line 1
Near character position 44
> INSERT INTO tb1 (col1, col2) VALUES (5.5,5.5::dist_type);
9632: Value does not match the type of column (col1).
Error in line 1
Near character position 55
> INSERT INTO tb1 (col1, col2) VALUES (5.5::dist_type,5.5);
1 row(s) inserted.
> UPDATE tb1 SET col1 = 4.8::dist_type WHERE col2 = 4.5;
1 row(s) updated.
> DELETE FROM tb1 WHERE col1::NUMERIC < 3.6;
1 row(s) deleted.
> SELECT col1, col2 FROM tb1 WHERE (col1::NUMERIC) > col2;
col1 4.8000000000000000
col2 4.50000000000000
1 row(s) retrieved.
> SELECT col1, col2, (col1 + col2::dist_type) sum_col , (col1::NUMERIC - col2) diff_col FROM tb1;
col1 4.8000000000000000
col2 4.50000000000000
sum_col 9.3000000000000000
diff_col 0.30000000000000
col1 5.5000000000000000
col2 5.50000000000000
sum_col 11.0000000000000000
diff_col 0.00000000000000
2 row(s) retrieved.
有关在本地数据库外的表内存取DISTINCT数据类型的查询和其它分布DML操作的信息,请参阅分布式操作中的DISTINCT类型。
如果您有任何进一步的修改意见或补充内容,欢迎随时提出。
原文链接:www.gbase.cn/community/p...
更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。