首页 > 数据库 >PL/SQL 基础---复杂数据类型和自定义类型

PL/SQL 基础---复杂数据类型和自定义类型

时间:2023-04-03 19:13:27浏览次数:41  
标签:LOB DBMS name 自定义 -- 数据类型 --- directions table

原文地址:https://blog.csdn.net/villare/article/details/53437924

PL/SQL 基础—复杂数据类型和自定义类型
PLSQL中常用的自定义类型就两种: 记录类型、 PLSQL内存表类型(根据表中的数据字段的简单和复杂程度又可分别实现类似于简单数组和记录数组的功能)

除此之外,还有大对象类型:CLOB、BFILE

一. 内存表对象(集合)
常用函数

函数名 功能
COUNT 返回集合中元素的个数
DELETE 删除集合中所有元素
DELETE(x) 删除元素下标为x的元素 对VARRAY非法
DELETE(x,y) 删除元素下标从X到Y的元素 对VARRAY非法
EXTEND 在集合末尾添加一个元素 对Index_by非法
EXTEND(x) 在集合末尾添加x个元素 对Index_by非法
EXTEND(x,n) 在集合末尾添加元素n的x个副本 对Index_by非法
EXIST(x) 如果集合元素x已经初始化,则返回TRUE, 否则返回FALSE
FIRST 返回集合中的第一个元素的下标号,对于VARRAY集合始终返回1
LAST 返回集合中最后一个元素的下标号, 对于VARRAY返回值始终等于COUNT
LIMIT 返回VARRY集合的最大的元素个数 Index_by集合和嵌套表无用
NEXT(x) 返回在第x个元素之后及紧挨着它的元素值,如果x是最后一个元素,返回null
PRIOR(x) 返回在第x个元素之前紧挨着它的元素的值,如果x是第一个元素,则返回null
TRIM 从集合末端开始删除一个元素 对于index_by不合法
TRIM(x) 从集合末端开始删除x个元素
1 .变长数组(VARRAY) – 简单数组、下标自动生成(int)、不可从中间删除

 

-- 变长数组
TYPE type_name IS VARRAY (max_elements)
OF element_datatype [ NOT NULL ];

DECLARE
TYPE t_array IS VARRAY(5) OF NUMBER;

m_data t_array;

BEGIN
m_data := t_array(0,1,2,3,4);
FOR i IN 1..5 LOOP
DBMS_OUTPUT.put_line(m_data(i));
END LOOP;
END;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
注:

1 .VARRAY变量需要初始化存储空间

1. m_data := t_array(0,1,2,3,4);
2. m_date.EXTEND(x[,n]);
1
2
2 .下标从1开始:1..N

3 .大小不能超过类型定义的大小: TYPE t_array IS VARRAY(5) OF NUMBER

2 .索引表(Associative arrays) – 索引类型自定义(和值一一对应),可删除,下表不变

数组值和唯一的索引关联,和变长数组有下标不同

TYPE type_name IS TABLE OF element_datatype [ NOT NULL ]
--->
INDEX BY BINARY_INTEGER;
INDEX BY PLS_INTEGER;
INDEX BY POSITIVE;
INDEX BY NATURAL;
INDEX BY SIGNTYPE;
INDEX BY VARCHAR2(32767);
INDEX BY table.column%TYPE;
INDEX BY cursor.column%TYPE;
INDEX BY package.variable%TYPE;
INDEX BY package.subtype;


-- 索引表

DECLARE
TYPE t_associative_table IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
v_table t_associative_table;

BEGIN
-- 不能使用 v_table := t_associative_table(0,1,2,2,4);
v_table(1) := 1;
v_table(2) := 2;
v_table(3) := 3;
v_table(4) := 3;
v_table(5) := 5;

FOR i IN 1..5 LOOP
IF v_table.EXISTS(i) THEN
v_table.DELETE(i);
END IF;
END LOOP;
DBMS_OUTPUT.put_line(v_table.COUNT());
END;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
3 .嵌套表(Nested tables) – 索引类型为INTEGER(>0),可删除,下标不变

可以看成特殊的索引表,不需要指定索引类型,默认为整型,且不能为负数

可以和数据库中的表相对应

-- 类型声明
TYPE type_name IS TABLE OF element_datatype [ NOT NULL ];

-- 嵌套表
DECLARE
TYPE t_nested_table IS TABLE OF NUMBER;
v_table t_nested_table;


BEGIN
v_table := t_nested_table(0,1,2,2,4);
v_table.DELETE(1);
DBMS_OUTPUT.put_line(v_table.COUNT());
FOR i IN 2..5 LOOP
IF v_table.EXISTS(i) THEN
DBMS_OUTPUT.put_line(v_table(i));
END IF;
END LOOP;

END;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
二. 记录(Record)
一条数据集合,相当于数据库中一条记录


TYPE type_name IS RECORD
(field_declaration[, field_declaration]…);
identifier type_name;

--field_declaration包括以下几种方式
field_name field_type;
field_name variable%TYPE/Table.column%TYPE;
field_name Table%ROWTYPE;
[NUT NULL]
[DEFAULT value]


--示例

DECLARE
TYPE T_RECORD_DEF IS RECORD
(
employee_id NUMBER,
lats_name VARCHAR2(20) DEFAULT 'NO_NAME');
e_record_1 T_RECORD_DEF;
e_record_2 T_RECORD_DEF;

BEGIN
SELECT e.EMPLOYEE_ID,e.Last_Name
INTO e_record_1
FROM EMPLOYEES e WHERE e.EMPLOYEE_ID = 100;

DBMS_OUTPUT.put_line(e_record_1.lats_name);
DBMS_OUTPUT.put_line(e_record_2.lats_name);
END;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
注:

字段名不区分大小写

Record类型不需要初始化;

Record可以和Table类型同时使用,构成类似表结构

合理使用%TYPE 、 TABLE%ROWTYPE(这种声明方式不会包含默认值信息);

二. 大对象类型(CLOB、NCLOB、BLOB、BFILE)
作用 使用
CLOB 字符大对象,存储在数据库内部;
NCLOB 多字节字符大对象,存储在数据库内部;
BLOB 二进制大对象,存储在数据库内部;
BFILE 二进制文件,存储在数据库外部;
-- Writw...
DECLARE
directions CLOB;
amount BINARY_INTEGER;
offset INTEGER;
first_direction VARCHAR2(100);
more_directions VARCHAR2(500);
BEGIN
--Delete any existing rows for 'Munising Falls' so that this
--example can be executed multiple times
DELETE
FROM waterfalls
WHERE falls_name='Munising Falls';

--Insert a new row using EMPTY_CLOB( ) to create a LOB locator
INSERT INTO waterfalls
(falls_name,falls_directions)
VALUES ('Munising Falls',EMPTY_CLOB( ));

--Retrieve the LOB locator created by the previous INSERT statement
SELECT falls_directions
INTO directions
FROM waterfalls
WHERE falls_name='Munising Falls';

--Open the LOB; not strictly necessary, but best to open/close LOBs.
DBMS_LOB.OPEN(directions, DBMS_LOB.LOB_READWRITE);

--Use DBMS_LOB.WRITE to begin
first_direction := 'Follow I-75 across the Mackinac Bridge.';
amount := LENGTH(first_direction); --number of characters to write
offset := 1; --begin writing to the first character of the CLOB
DBMS_LOB.WRITE(directions, amount, offset, first_direction);

--Add some more directions using DBMS_LOB.WRITEAPPEND
more_directions := ' Take US-2 west from St. Ignace to Blaney Park.'
|| ' Turn north on M-77 and drive to Seney.'
|| ' From Seney, take M-28 west to Munising.';
DBMS_LOB.WRITEAPPEND(directions,
LENGTH(more_directions), more_directions);

--Add yet more directions
more_directions := ' In front of the paper mill, turn right on H-58.'
|| ' Follow H-58 to Washington Street. Veer left onto'
|| ' Washington Street. You''ll find the Munising'
|| ' Falls visitor center across from the hospital at'
|| ' the point where Washington Street becomes'
|| ' Sand Point Road.';
DBMS_LOB.WRITEAPPEND(directions,
LENGTH(more_directions), more_directions);

--Close the LOB, and we are done.
DBMS_LOB.CLOSE(directions);
END;

---Reading...
DECLARE
directions CLOB;
directions_1 VARCHAR2(300);
directions_2 VARCHAR2(300);
chars_read_1 BINARY_INTEGER;
chars_read_2 BINARY_INTEGER;
offset INTEGER;
BEGIN
--Retrieve the LOB locator inserted previously
SELECT falls_directions
INTO directions
FROM waterfalls
WHERE falls_name='Munising Falls';

--Begin reading with the first character
offset := 1;

--Attempt to read 229 characters of directions, chars_read_1 will
--be updated with the actual number of characters read
chars_read_1 := 229;
DBMS_LOB.READ(directions, chars_read_1, offset, directions_1);

--If we read 229 characters, update the offset and try to
--read 255 more.
IF chars_read_1 = 229 THEN
offset := offset + chars_read_1;
chars_read_2 := 255;
DBMS_LOB.READ(directions, chars_read_2, offset, directions_2);
ELSE
chars_read_2 := 0;
directions_2 := '';
END IF;

--Display the total number of characters read
DBMS_OUTPUT.PUT_LINE('Characters read = ' ||
TO_CHAR(chars_read_1+chars_read_2));

--Display the directions
DBMS_OUTPUT.PUT_LINE(directions_1);
DBMS_OUTPUT.PUT_LINE(directions_2);
END;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
BFILE处理
需要提前建立DIRCTORY,并且当前用户有读取此DIRECTORY的权限

CREATE DIRECTORY bfile_data AS '文件目录 如:c:\data\file.txt';

GRANT READ ON DIRECTORY bfile_data TO 当前用户名;

--使用
DECLARE
web_page BFILE;
BEGIN
--Delete row for Tannery Falls so this example can
--be executed multiple times
DELETE FROM waterfalls WHERE falls_name='Tannery Falls';

--Invoke BFILENAME to create a BFILE locator
web_page := BFILENAME('BFILE_DATA','Tannery Falls.htm');

--可以打开文件进行读写操作

--Save our new locator in the waterfalls table
INSERT INTO waterfalls (falls_name, falls_web_page)
VALUES ('Tannery Falls',web_page);
END;

--读写
DECLARE
web_page BFILE;
html RAW(60);
amount BINARY_INTEGER := 60;
offset INTEGER := 1;
BEGIN
--Retrieve the LOB locat0r for the web page
SELECT falls_web_page
INTO web_page
FROM waterfalls
WHERE falls_name='Tannery Falls';

--Open the locator, read 60 bytes, and close the locator
DBMS_LOB.OPEN(web_page);
DBMS_LOB.READ(web_page, amount, offset, html);
DBMS_LOB.CLOSE(web_page);

--Uncomment following line to display results in hex
--DBMS_OUTPUT.PUT_LINE(RAWTOHEX(html));

--Cast RAW results to a character string we can read
DBMS_OUTPUT.PUT_LINE(UTL_RAW.CAST_TO_VARCHAR2(html));
END;


--写入记录
DECLARE
Tannery_Falls_Directions BFILE
:= BFILENAME('BFILE_DATA','TanneryFalls.directions');
directions CLOB;
destination_offset INTEGER := 1;
source_offset INTEGER := 1;
language_context INTEGER := DBMS_LOB.default_lang_ctx;
warning_message INTEGER;
BEGIN
--Delete row for Tannery Falls, so this example
--can run multiple times.
DELETE FROM waterfalls WHERE falls_name='Tannery Falls';

--Insert a new row using EMPTY_CLOB( ) to create a LOB locator
INSERT INTO waterfalls
(falls_name,falls_directions)
VALUES ('Tannery Falls',EMPTY_CLOB( ));

--Retrieve the LOB locator created by the previous INSERT statement
SELECT falls_directions
INTO directions
FROM waterfalls
WHERE falls_name='Tannery Falls';

--Open the target CLOB and the source BFILE
DBMS_LOB.OPEN(directions, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.OPEN(Tannery_Falls_Directions);

--Load the contents of the BFILE into the CLOB column
DBMS_LOB.LOADCLOBFROMFILE
(directions, Tannery_Falls_Directions,
DBMS_LOB.LOBMAXSIZE,
destination_offset, source_offset,
NLS_CHARSET_ID('US7ASCII'),
language_context, warning_message);

--Check for the only possible warning message.
IF warning_message = DBMS_LOB.WARN_INCONVERTIBLE_CHAR THEN
dbms_output.put_line(
'Warning! Some characters couldn''t be converted.');
END IF;

--Close both LOBs
DBMS_LOB.CLOSE(directions);
DBMS_LOB.CLOSE(Tannery_Falls_Directions);
END;

 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
DBMS_LOB常用函数:具体用法参看相关文档

函数 功能
APPEND 将源LOB中的内容加到目的LOB中
CLOSE 关闭已经打开的LOB
FILECLOSE 关闭打开的BFILE定位符所指向的OS文件
FILECLOSEALL 关闭当前会话已经打开的所有BFILE文件
FILEEXISTS 确定file_loc对应的OS文件是否存在,1:存在 0:不存在
FILEGETNAME 获取BFILE定位符所对应的目录别名和文件名
FILEISOPEN 确定BFILE对应的OS文件是否打开
FILEOPEN 打开文件
COPY 从源LOB中复制数据到目的LOB
ERASE 删除LOB中全部或部分内容
TRIM 将LOB值减少到指定的长度
WRITE 向LOB中写入数据
INSTR 返回特定样式数据从LOB某偏移位置开始出现N次的具体位置
OPEN 打开LOB,open_mode(只读:dbms_lob.lob_readonly,写读dbms_lob.lob_readwrite)
GETLENGTH 获取LOB的长度
READ 从LOB中读出数据
SUBSTR 与字符处理函数SUBSTR使用方法一样
WRITEAPPEND 将缓冲区数据写到LOB尾部
注:
CLOB等大对象不能直接使用IS NULL判空(EMPTY_CLOB() IS NULL), 正确的判断如下:


IF some_clob IS NULL THEN
--There is no data
ELSEIF DBMS_LOB.GETLENGTH(some_clob) = 0 THEN
--There is no data
ELSE
--Only now is there data
END IF;
1
2
3
4
5
6
7
8
9
CLOB,NCLOB处理和字符串类似:支持|| 、 substr等对字符串的操作;
————————————————
版权声明:本文为CSDN博主「villare」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/villare/article/details/53437924

标签:LOB,DBMS,name,自定义,--,数据类型,---,directions,table
From: https://www.cnblogs.com/eyesfree/p/17284070.html

相关文章

  • UCUP-ZJ M. Minimum Element Problem
    题意给定一个位置x,求在\(p_x\)分别取1-n的所有情况下,对应笛卡尔树不同的排列个数。题解先不考虑\(p_x\),列出转移式,发现是卡特兰数。进一步地,可以把排列对应笛卡尔树意义下的不同构数,和二叉树不同构数等价联系起来:因为对于任何一个二叉树,按照中序遍历在上面填1-n,就可以唯一确定......
  • 2022全国职业技能大赛-云计算私有云平台搭建及注意事项
    @目录环境准备基础配置搭建yum源修改openrc.sh计算节点分区脚本安装安装平台基本服务环境准备软件包:答题云主机环境;CentOS-7-x86_64-DVD-2009.iso(centos7.9)iaas版本;chinaskills_cloud_iaas_v2.0.3.iso(openstackT版)国赛竞赛方式:1,openstack平台,现场会提供一个IP地址,登录......
  • 百度面试题-海量日志,读取IP
    4、海量日志数据,提取出某日访问百度次数最多的那个IP。回答:如果日志文件足够的大,大到不能完全加载到内存中的话。那么可以考虑分而治之的策略,按照IP地址的hash(IP)%1024值,将海量日志存储到1024个小文件中。每个小文件最多包含4M个IP地址。对于每个小文件,可以构建一个IP作为ke......
  • 对list中的字段进行自定义排序,最后放在LinkedHashMap中
    List<ProjectVO>projectList=dbProjectService.getProjectList();这里面如果第一个字段是如下的顺序:"成都分公司","北京分公司","上海分公司","深圳分公司","广州分公司","重庆分公司"Map<String,List<ProjectVO>>map=projectL......
  • Mybatis-Plus代码生产器
    【问题描述】在微服务的开发过程中,每次新创建一个微服务项目的时候,都需要手工添加controller、service、entity和mapper文件夹和文件时会比较麻烦,并且增加不少的工作量。是否有一个模块,可以自动生成对应的目录和文件呢?真的有这样的代码生产器文件:一、使用之前先确认POM文件中下......
  • 笔记九:github操作-github跨团队协作
    一:学习内容github跨团队协作流程图谱github跨团队协作流程案例实操 二:github跨团队协作流程图谱1.岳不群想要其他团队的大牛也帮忙修改一下华山剑法,让这套剑法更厉害,于是找到了东方不败帮忙,东方不败不是这个团队的人,所以不能直接操作岳不群团队的远程库,需要先fork岳不群的......
  • 笔记八:github操作-github团队内协作
    一:学习内容github团队内协作流程图谱github团队内协作流程案例实操 二:github团队内协作流程图谱1.师傅岳不群创建了一套华山剑法,把它推送到代码托管中心远程库2.弟子令狐冲将整套剑法下载到自己的本地库中3.弟子令狐冲对剑法进行修改调整,然后对修改的内容推送到代码托管中......
  • 笔记七:github操作-Push、Pull、Clone
    一:学习内容Push:推送本地分支到远程库Pull:拉取远程分支到本地库Clone:克隆远程库到本地 二:Push:推送本地分支到远程库需要注意:推送的时候,需要指定分支,也就是我把本地库的哪个分支推送到远程库1#推送本地分支到远程库,gitpush别名分支2#如果当前本地库在hot-fix分支上......
  • 笔记十一:Idea操作-集成git
    一:学习内容配置git忽略文件idea定位git程序idea初始化本地库idea添加暂存区idea提交本地库idea切换版本idea创建分支与切换分支idea合并分支-正常合并idea合并分支-冲突合并 二:配置git忽略文件1.创建git.ignore文件,即磁盘进入C:\\Users\\你的用户下,新建git.ignore......
  • 笔记十:github操作-ssh免密登录
    一:学习内容生成ssh免密登录密钥github配置ssh免密登录公钥测试ssh免密登录 二:本地生成ssh免密登录密钥因为github是国外网站国内访问https链接不稳定,所以我们会用ssh的方式访问,而ssh的方式就需要配置ssh密钥。1#添加ssh免密公钥,进入windows家目录,C:\\Users\\你的用户......