PLS_INTEGER、BINARY_INTEGER和SIMPLE_INTEGER区别

本文详细介绍了PLS_INTEGER、BINARY_INTEGER及SIMPLE_INTEGER三种Oracle数据库中的整数数据类型。重点对比了它们之间的性能差异,特别是在密集整数运算场景下SIMPLE_INTEGER带来的显著性能提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PLS_INTEGER

PLS_INTEGER数据类型保存范围-2147483648到2147483647的有符整数。这种类型的值是通过底层硬件平台的原生整数格式来表示的。

设计PLS_INTEGER数据类型是为了运算速度。在oracle数据库10g以前,PLS_INTEGER是唯一的一个使用原生机器算法的整数类型。其他的所有数值烈性的数据类型都和NUMBER数据类型一样使用C语言算法库。如果用PLS_INTEGER值运算,oracle软件会使用原生机器算法。结果就是处理PLS_INTEGER值的速度要比处理NUMBER类型的整数快的多。因为PLS_INTEGER是整数,因此在一直硬件平台时不会遇到兼容性的问题、

如果要处理的是密集整数运算,建议使用PLS_INTEGER、不过要记住,如果使用PLS_INTEGER时要经常和NUMBER类型互相转换,那还是从一开始就使用NUMBER类型更好。

如果这个数据类型用于整数运算,结果会取整

declare
pls1 PLS_INTEGER;
pls2 PLS_INTEGER;
p_result PLS_INTEGER;
num number;
begin
pls1 := 100;
pls2 := 49;
p_result := pls2/pls1;
num := pls2/pls1;
dbms_output.put_line('integer 49/100='||p_result);
dbms_output.put_line('number 49/100='||num);
pls2 := 50;
p_result := pls2/pls1;
num := pls2/pls1;
dbms_output.put_line('integer 50/100='||p_result);
dbms_output.put_line('number 50/100='||num);
end;
/
integer 49/100=0
number 49/100=.49
integer 50/100=1
number 50/100=.5

PL/SQL 过程已成功完成。


BINARY_INTEGER

BINARY_INTEGER数据类型也可以用二进制的形式保存有符号整数。这个类型的语义在oracle数据库10g的R1版本中有所不同。从这个版本开始,BINARY_INTEGER等同于PLS_INTEGER。而在oracle数据库9i的R2版本以及更早的版本中,它和PLS_INTEGER的区别在于oracle采用平台无关的库代码来实现。

我不建议在新代码中使用BINARY_INTEGER类型。使用BINARY_INTEGER的唯一理由就是你的代码要在oracle 7.3以前版本上运行(即PLS_INTEGER引入之前)。我希望你不会还在使用这么旧的版本



SIMPLE_INTEGER类型
SIMPLE_INTEGER数据类型时在oracle数据库11g中新出现的。这个数据类型是PLS_INTEGER的性能增强版本,除了很少几个警告。SIMPLE_INTEGER和PLS_INTEGER有相同的取值范围,但是它不支持NULL值,也不会检查溢出条件。所以你可能很奇怪为何需要使用这个看起来有缺陷的PLS_INTEGER。很好,如果你的变量永远不会为NULL,也不会溢出,而且用原生的方式编译你的代码,SIMPLE_INTEGER类型能带来令人尖叫的性能。

首先,创建一个使用pls_integer的计算密集型的过程
create or replace procedure pls_test(interations in pls_integer)
as
int1 pls_integer := 1;
int2 pls_integer := 2;
begints timestamp;
endts timestamp;
begin
begints := systimestamp;

for cnt in 1..interations loop
int1 := int1 + int2 * cnt;
end loop;

endts := systimestamp;
dbms_output.put_line( interations
|| 'interations had run time of:'
|| to_char(endts - begints));
end;
/

接下来用simple_integer创建相同的过程
create or replace procedure simple_test(interations in simple_integer)
as
int1 simple_integer := 1;
int2 simple_integer := 2;
begints timestamp;
endts timestamp;
begin
begints := systimestamp;

for cnt in 1..interations loop
int1 := int1 + int2 * cnt;
end loop;

endts := systimestamp;
dbms_output.put_line( interations
|| 'interations had run time of:'
|| to_char(endts - begints));
end;
/

首先以解释的方式重新编译代码
alter procedure pls_test compile plsql_code_type=interpreted;
/

alter procedure simple_test compile plsql_code_type=interpreted;
/

exec pls_test(12345);
exec simple_test(12345);



alter procedure pls_test compile plsql_code_type=native;
/

alter procedure simple_test compile plsql_code_type=native;
/

我做的实验simple_integer更慢了。。

书上的实验:
在使用解释代码时,simple_integer只有少许系能提升(windows)。在使用原生编译时,PLS_INTEGER和SIMPLE_INTEGER两个都更快,但是原生simple_integer要比原生PLS_INTEGER快300%!作为一个教学用的练习,用NUMBER再做一下这个实验——我发现SIMPLE_INTEGER要比NUMBER块1000%。在运行与Linux服务器上的Oracle数据库11g的R2版本中,使用SIMPLE_INTEGER类型后同样得到显著的性能提升(快上百分之几百)。
<think>我们正在处理用户关于PL/SQL中定义INDEX BY表类型(关联数组)的请求。根据提供的引用,特别是引用[2]中的错误信息,我们可以推断用户需要正确的语法示例解析。 引用[1]介绍了PLS_INTEGER类型,引用[2]展示了一个错误的示例(INDEX BY pls_integer重复写了两遍导致错误),引用[3]提到官方文档实践指南,引用[4]则涉及包对象的引用方式。 用户意图:了解如何正确声明PL/SQL中的关联数组(索引表)类型。 关联数组(也称为索引表)是PL/SQL中的一种集合类型,它由键值对组成,键可以是整数或字符串。定义语法如下: TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY index_type; 其中: - type_name:自定义的类型名称。 - element_type:数组中元素的数据类型(可以是任何PL/SQL数据类型,如VARCHAR2, NUMBER, 甚至可以是记录类型)。 - index_type:索引类型,可以是PLS_INTEGER, VARCHAR2等。 注意:在引用[2]的错误示例中,错误地将“INDEX BY pls_integer”写了两次,导致一系列错误。正确的写法应该是“INDEX BY pls_integer”一次。 下面我们提供几个示例: 示例1:索引类型为PLS_INTEGER的关联数组(整数索引) 示例2:索引类型为VARCHAR2的关联数组(字符串索引) 另外,我们还可以展示如何在存储过程或函数中使用这些类型。 根据引用[3],条件判断循环控制是流程控制的重要部分,因此我们也可以展示如何遍历关联数组。 注意:在PL/SQL中,关联数组是稀疏的,也就是说,索引可以不连续。 步骤: 1. 声明一个关联数组类型。 2. 声明一个该类型的变量。 3. 给数组赋值(使用下标)。 4. 访问数组元素。 我们还可以展示一些常见的操作,如遍历、检查元素是否存在等。 由于引用[2]中的错误,我们特别要注意避免重复写INDEX BY子句。 下面我们给出具体示例。</think>### PL/SQL 关联数组(INDEX BY 表)定义与示例解析 在 PL/SQL 中,关联数组(Associative Arrays)也称为索引表(INDEX BY Tables),是一种键值对集合,支持通过唯一键快速访问数据。其核心定义语法如下: ```sql TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY { PLS_INTEGER | VARCHAR2(size) | BINARY_INTEGER }; ``` #### 基础结构解析 1. **类型声明** `TYPE type_name`:自定义类型名称(如 `t_emp_table`) 2. **元素类型** `element_type`:支持标量类型(如 `NUMBER`, `VARCHAR2`)、记录类型或对象类型 3. **索引类型** `INDEX BY`:指定键类型: - `PLS_INTEGER`:高性能整数索引(范围 -2³¹ ~ 2³¹-1)[^1] - `VARCHAR2(size)`:字符串索引(需指定长度) - `BINARY_INTEGER`:兼容旧版整数类型(效率低于 `PLS_INTEGER`) --- #### 示例 1:整数索引表(员工ID映射姓名) ```sql DECLARE -- 定义整数索引的关联数组类型 TYPE t_emp_name IS TABLE OF employees.last_name%TYPE INDEX BY PLS_INTEGER; -- 推荐使用高性能整数索引[^1] v_emp_names t_emp_name; -- 声明变量 BEGIN -- 赋值(键为员工ID) v_emp_names(101) := 'King'; v_emp_names(102) := 'Kochhar'; -- 动态添加元素 v_emp_names(103) := 'De Haan'; -- 通过键访问值 DBMS_OUTPUT.PUT_LINE('ID 102: ' || v_emp_names(102)); END; ``` --- #### 示例 2:字符串索引表(部门代码映射预算) ```sql DECLARE TYPE t_dept_budget IS TABLE OF NUMBER INDEX BY VARCHAR2(10); -- 字符串索引(键长度10) v_budgets t_dept_budget; BEGIN v_budgets('IT') := 500000; v_budgets('HR') := 300000; -- 检查键是否存在 IF v_budgets.EXISTS('SALES') THEN DBMS_OUTPUT.PUT_LINE('Sales budget: ' || v_budgets('SALES')); ELSE DBMS_OUTPUT.PUT_LINE('Sales budget not defined'); END IF; END; ``` --- #### 错误规避要点 1. **索引类型冲突** ```sql -- ❌ 错误:重复声明索引类型(引用[2]错误示例) TYPE t_error IS TABLE OF NUMBER INDEX BY PLS_INTEGER INDEX BY VARCHAR2(20); ``` 正确写法应仅保留一个 `INDEX BY` 子句。 2. **类型兼容性** 赋值时键值必须严格匹配索引类型: ```sql DECLARE TYPE t_num_index IS TABLE OF DATE INDEX BY PLS_INTEGER; v_dates t_num_index; BEGIN v_dates(100) := SYSDATE; -- ✅ 正确 v_dates('2024') := SYSDATE; -- ❌ 错误:键类型不匹配[^2] END; ``` --- #### 高级应用:记录类型元素 ```sql DECLARE TYPE t_emp_rec IS RECORD ( name employees.last_name%TYPE, salary employees.salary%TYPE ); TYPE t_emp_db IS TABLE OF t_emp_rec INDEX BY PLS_INTEGER; v_employees t_emp_db; BEGIN -- 插入记录 v_employees(100).name := 'Patel'; v_employees(100).salary := 7500; -- 批量赋值 SELECT last_name, salary INTO v_employees(101) FROM employees WHERE employee_id = 101; END; ``` --- ### 关键特性总结 | 特性 | 说明 | |---------------------|----------------------------------------------------------------------| | **稀疏存储** | 键可不连续(如 `v_arr(1)`, `v_arr(1000)`) | | **高效查找** | 通过哈希实现 $O(1)$ 时间复杂度访问 | | **动态增长** | 无需预定义大小 | | **方法支持** | `.EXISTS(key)`, `.FIRST`, `.LAST`, `.COUNT` 等[^3] | | **作用域** | 在包中定义可全局使用,在块中定义仅局部有效 | > 关联数组是 PL/SQL 集合三大类型之一(另两种是嵌套表 `VARRAY`),适合处理内存键值映射快速查找场景[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值