LightDB24.1 存储过程支持inner和outer对变量的引用

news2024/12/26 10:36:20

背景

Oracle

oracle plsql支持如下场景:
在for循环中,将select查询的结果给一个record类型,这一操作也被称为隐式游标操作。record类型中一个字段用来接收查询结果中的一个select查询语句(update,delete,insert在这个语法中都会报错),这个字段被用作open for动态打开一个游标的对象。这个rec变量可以为关键字,在业务适配的过程中,我们发现了这一点,客户现场使用的关键字有两个outer和inner。
test1

LIghtDB

在之前版本中,我们发现LightDB不支持上面描述的oracle plsql支持的场景,通常在内核语法解析就直接报错。经调查发现,
(1)inner和outer都是TYPE_FUNC_NAME_KEYWORD关键字,
(2)在gram.y没有对未保留关键字的解析。
因此我们需要在内核去实现这两步。但是由于inner还有一重含义,就是内联。如果表名、别名能够出现inner,会导致语法解析的时候产生已经冲突。异常在与oracle的表现上会呈现以下几点区别:
1、类型名(具体指联合数组、可变数组和嵌套表)和for循环变量的名字相同时,报错

declare
  type outer is varray(1) of number;
  v_busin_array1 outer := outer();
  CURSOR c_a IS select * from record_filed;
  zqdm_p record_filed.id%TYPE;
begin
FOR outer IN c_a LOOP
  zqdm_p := outer.zqdm;
end loop;
end;
/

declare
  type outer is varray(1) of number;
  v_busin_array1 outer := outer();
  CURSOR c_a IS select * from record_filed;
  zqdm_p record_filed.id%TYPE;
begin
FOR outer IN c_a LOOP
  zqdm_p := outer.zqdm;
end loop;
end;
/

2、已创建outer同名的对象后,不允许再创建outer类型

create table outer(outer int);
create view outer as select * from dual;
create domain outer as char(100);
drop type outer;

3、OUTER为非保留关键字,可以作为表名、列名、函数名、类型名等,INNER为函数名类型名关键字,只能作为函数名;

测试

--------------------------lightdb add at 2024/03/19 for S202312144054----------------------------
--------------------------test of outer---------------------------------
create table outer(outer int);
select * from outer;
create table select_outer_test(id int);
select outer.id as outer from select_outer_test as outer where outer.id > 1;
update select_outer_test outer set outer.id = 1;
with outer as (select outer.id as outer from select_outer_test as outer) select outer from outer;
drop table outer;
drop table select_outer_test;

--If an outbound table has already been created and the outer type is created, an error is reported.
create domain outer as char(100);
drop type outer;

create type outer as (id int);
drop type outer;

create table record_filed(id int, zqdm varchar(100));
insert into record_filed values(12,'hello world!');

-- create a custom type...
-- error
CREATE TYPE outer AS object (
    i integer,
    i2 integer,
    member function outer() return varchar,
    member procedure outer()
);

CREATE TYPE outer AS object (
    i integer,
    i2 integer,
    member function outer1() return varchar,
    member procedure outer2()
);

drop type outer;


CREATE TYPE test_object_type AS object (
    i integer,
    i2 integer,
    member function outer() return varchar
);

--error
CREATE TYPE test_object_type AS object (
    i integer,
    i2 integer,
    member function outer() return varchar,
    member procedure outer()
);


CREATE TYPE BODY test_object_type AS
    member function outer() return varchar as
    begin
        return '(' || self.i || ',' || self.i2 || ')';
    end;

END;
/

declare
	ind test_object_type;
	ind_func int;
begin
	ind_func := ind.outer();
end;
/

CREATE or replace TYPE BODY test_object_type AS
    member function outer() return varchar as
	  CURSOR c_a IS
		 select * from record_filed;
	  zqdm_p  record_filed.id%TYPE;
	BEGIN
      FOR outer IN c_a LOOP
	    zqdm_p := outer.id;
	  end loop;
	  return 1;
	end;
END;
/

declare
	ind test_object_type;
	ind_func int;
begin
	ind_func := ind.outer();
end;
/

--error
CREATE TYPE BODY test_object_type AS
    member function outer() return varchar as
	    outer int;
    begin
        return '(' || self.i || ',' || self.i2 || ')';
    end;
END;
/

drop type test_object_type;

-- test of anonymous block, function, procedure, package
--outer
--anonymous block
DECLARE
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;
/

DECLARE
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
execute immediate 'create table outer(outer int)';
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;
/

DECLARE
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
execute immediate 'drop table outer';
execute immediate 'DECLARE
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;';
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;
/


--record
select dbms_output.serveroutput(true);

declare
type outer is record (
	a1 varchar2(1000) not null,
	a2 NVARCHAR2(1000),
	a3 VARCHAR(1000),
	a4 CHAR(1000),
	a5 NCHAR(1000),
	b1 NUMBER(8,2),
	b2 FLOAT,
	b3 BINARY_FLOAT,
	b4 BINARY_DOUBLE,
	c long,
	d1 rowid,
	d2 raw,
	e1 DATE,
	e2 TIMESTAMP,
	e3 TIMESTAMP WITH TIME ZONE,
	e5 INTERVAL YEAR TO MONTH,
	e6 INTERVAL DAY TO SECOND,
	f1 blob,
	f2 clob
);
  CURSOR c_a IS select * from record_filed;
  zqdm_p record_filed.id%TYPE;
  rec_pool outer;
begin
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
  dbms_output.put_line(zqdm_p);
end loop;
end;
/
select dbms_output.serveroutput(false);
--varray
declare
  type outer is varray(1) of number;
  v_busin_array1 outer := outer();
  CURSOR c_a IS select * from record_filed;
  zqdm_p record_filed.id%TYPE;
begin
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;
/

--Associative Arrays
DECLARE
  type outer is table of number index by varchar2(4);
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p record_filed.id%TYPE;
BEGIN
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;
/

--Nested Tables
DECLARE
  CURSOR c_a IS
     select * from record_filed;
  type outer is table of number;
  zqdm_p record_filed.id%TYPE;
BEGIN
FOR outer IN c_a LOOP
  zqdm_p := outer.id;
end loop;
end;
/

DECLARE
  outer int;
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
  outer := 12;
  FOR outer IN c_a LOOP
    zqdm_p := outer.id;
  end loop;
end;
/
---------------------------------------test of inner-----------------------------------
create table inner(inner int);
select * from inner;
create table select_inner_test(id int);
select inner.id as inner from select_inner_test as inner where inner.id > 1;
update select_inner_test inner set inner.id = 1;
with inner as (select inner.id as inner from select_inner_test as inner) select inner from inner;
drop table inner;
drop table select_inner_test;

--If an outbound table has already been created and the inner type is created, an error is reported.
create domain inner as char(100);
drop type inner;

create type inner as (id int);
drop type inner;

create table record_filed(id int, zqdm varchar(100));
insert into record_filed values(12,'hello world!');

-- create a custom type...
-- error
CREATE TYPE inner AS object (
    i integer,
    i2 integer,
    member function inner() return varchar,
    member procedure inner()
);

CREATE TYPE inner AS object (
    i integer,
    i2 integer,
    member function inner1() return varchar,
    member procedure inner2()
);

drop type inner;

--error
CREATE TYPE test_object_type AS object (
    i integer,
    i2 integer,
    member function inner() return varchar,
    member procedure inner()
);

CREATE TYPE test_object_type AS object (
    i integer,
    i2 integer,
    member function inner() return varchar
);

CREATE TYPE BODY test_object_type AS
    member function inner() return varchar as
    begin
        return '(' || self.i || ',' || self.i2 || ')';
    end;

END;
/

--error
CREATE TYPE BODY test_object_type AS
    member function inner() return varchar as
	    inner int;
    begin
        return '(' || self.i || ',' || self.i2 || ')';
    end;
END;
/

CREATE or replace TYPE BODY test_object_type AS
    member function inner() return varchar as
	  CURSOR c_a IS
		 select * from record_filed;
	  zqdm_p  record_filed.id%TYPE;
	BEGIN
      FOR inner IN c_a LOOP
	    zqdm_p := inner.id;
	  end loop;
	  return 1;
	end;
END;
/

declare
  ind test_object_type;
  ind_func int;
begin
  ind_func := ind.inner();
end;
/

drop type test_object_type;

-- test of anonymous block, function, procedure, package
--inner
--anonymous block
DECLARE
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
FOR inner IN c_a LOOP
  zqdm_p := inner.id;
end loop;
end;
/

--record
select dbms_output.serveroutput(true);

declare
type inner is record (
	a1 varchar2(1000) not null,
	a2 NVARCHAR2(1000),
	a3 VARCHAR(1000),
	a4 CHAR(1000),
	a5 NCHAR(1000),
	b1 NUMBER(8,2),
	b2 FLOAT,
	b3 BINARY_FLOAT,
	b4 BINARY_DOUBLE,
	c long,
	d1 rowid,
	d2 raw,
	e1 DATE,
	e2 TIMESTAMP,
	e3 TIMESTAMP WITH TIME ZONE,
	e5 INTERVAL YEAR TO MONTH,
	e6 INTERVAL DAY TO SECOND,
	f1 blob,
	f2 clob
);
  CURSOR c_a IS select * from record_filed;
  zqdm_p record_filed.id%TYPE;
  rec_pool inner;
begin
FOR inner IN c_a LOOP
  zqdm_p := inner.id;
  dbms_output.put_line(zqdm_p);
end loop;
end;
/
select dbms_output.serveroutput(false);
--varray
declare
  type inner is varray(1) of number;
  v_busin_array1 inner := inner();
  CURSOR c_a IS select * from record_filed;
  zqdm_p record_filed.id%TYPE;
begin
FOR inner IN c_a LOOP
  zqdm_p := inner.id;
end loop;
end;
/

--Associative Arrays
DECLARE
  type inner is table of number index by varchar2(4);
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p record_filed.id%TYPE;
BEGIN
FOR inner IN c_a LOOP
  zqdm_p := inner.id;
end loop;
end;
/

--Nested Tables
DECLARE
  CURSOR c_a IS
     select * from record_filed;
  type inner is table of number;
  zqdm_p record_filed.id%TYPE;
BEGIN
FOR inner IN c_a LOOP
  zqdm_p := inner.id;
end loop;
end;
/

DECLARE
  inner int;
  CURSOR c_a IS
     select * from record_filed;
  zqdm_p  record_filed.id%TYPE;
BEGIN
  inner := 12;
  FOR inner IN c_a LOOP
    zqdm_p := inner.id;
  end loop;
end;
/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1532221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ELK快速搭建图文详细步骤

目录 一、下载地址二、安装docker-compose(已安装则跳过)三、初始化ELK1. 赋予/setup/entrypoint.sh执行权限2. 初始化 docker-elk 所需的 Elasticsearch 用户和组3. 重置默认用户的密码4. 替换配置文件中的用户名和密码5. 重启 Logstash 和 Kibana,使用新密码重新连…

蓝桥杯单片机快速开发笔记——NE555测频

一、原理分析 NE555作为一种多功能集成电路,在信号发生和频率测量方面具有广泛的应用。通过合理配置和连接外部元件,可以实现不同类型的信号发生和频率测量功能。 原理: 信号发生器: NE555可以配置为多种不同的振荡器电路&#x…

鸿蒙Harmony应用开发—ArkTS-转场动画(组件内转场)

组件内转场主要通过transition属性配置转场参数,在组件插入和删除时显示过渡动效,主要用于容器组件中的子组件插入和删除时,提升用户体验。 说明: 从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记…

leetcode代码记录(移除链表元素

目录 1. 题目:2. 我的代码:小结: 1. 题目: 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head […

学点Java打小工_Day2Day3_一点作业

1 猜数字(10次机会) 随机生成[1,1000]的一个数,输入你猜的数程序会给出反馈,直到猜对或次数用尽(10次)。 //猜数字 10次机会Testpublic void guessNumber() {Random random new Random();// [0, 1000) 1// [1, 1000]int num ra…

基于 Echarts + Python Flask ,我搭建了一个动态实时大屏监管系统

一、效果展示 1. 动态实时更新数据效果图 2. 鼠标右键切换主题 二、确定需求方案 支持Windows、Linux、Mac等各种主流操作系统;支持主流浏览器Chrome,Microsoft Edge,360等;服务器采用python语言编写,配置好python环…

linux---文件查找

知识点: whereis 可以搜索传统命令的可执行文件路径和说明文档 which 搜索可执行文件 #whereir包含了which locate 在数据库中进行快速查找 find . -name 文件名/文件名要求 #按文件名查找. -iname 文件名 #按文件名查找且…

【史上最全万字mysql进阶语法】

前言: 💞💞大家好,书生♡,今天主要和大家分享一下mysql的进阶语法,数据库的分组/分页/排序/子查询以及详细案例,希望对大家有所帮助。 💞💞前路漫漫,希望大家坚持下去&am…

2024年最新Anaconda3 2024版中Jupyter Notebook安装

一、 Anaconda3 2024版下载 1.下载:Free Download | Anaconda 2.等待 解释:默认选择等等下载 ,时间可能数分钟 3.安装 解释:打开刚刚下载的Anaconda Navigator,并如图安装低版本,高版本会直接报错 4. …

ES8生产实践——性能压测工具esrally

引言 什么是压测 压测,即压力测试,是指对计算机系统、软件应用或网络服务等进行负载测试,以模拟实际使用场景中的高负载情况,检验系统在压力下的性能、稳定性和可靠性。压测旨在确定系统在正常或极端负载下的性能极限&#xff0…

首个业内DNA存储技术规范发布

在DNA数据存储的检索过程中,采用了三个输入对应一个输出逻辑实现的算法模式来生成数据表示的模式。这一算法模式的设计是为了有效编码和解码存储在DNA分子上的信息。 其中提到的“扰动比例”δ(n)是一个关键概念,它衡量的是在总的细胞数目(此…

【MySQL】图形化界面工具DataGrip安装&配置&使用

前言 大家好吖,欢迎来到 YY 滴MySQL系列 ,热烈欢迎! 本章主要内容面向接触过C Linux的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! YY的《C》专栏YY的《C11》专栏YY的…

Redis6.0多线程的疑惑解答

1.Redis6.0之前的版本真的是单线程吗? Redis在处理客户端的请求是,包括获取(socket读)、解析、执行、内容返回(socket 写)等都有一个 顺序串行的主线程处理,这就是所谓的"单线程"。但如果严格来讲并不是单线程,除了主线…

2024蓝桥杯每日一题(并查集)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一:奶酪 试题二:合并集合 试题三:连通块中点的数量 试题四:网络分析 试题一:奶酪 【题目描述】 现有一块大奶酪,它的高度为 hℎ…

Java SE入门及基础(44)

目录 I / O流(上) 1. 什么是I / O流 过程分析 I / O的来源 Java 中的 I / O流 2. 字节流 OutputStream 常用方法 文件输出流 FileOutputStream 构造方法 示例 InputStream 常用方法 文件输入流 FileInputStream 构造方法 示例 综合练习 字节流应用场景 Java SE文…

命名空间——初识c++

. 个人主页:晓风飞 专栏:数据结构|Linux|C语言 路漫漫其修远兮,吾将上下而求索 文章目录 经典的Hello Word 起航c关键字c语言的命名冲突问题域作用限定符::命名空间 namespace命名空间定义命名空间的使用1.加命名空间名称及作用域限定符2.使用…

web集群-lvs-DR模式基本配置

目录 环境: 一、配置RS 1、安装常见软件 2、配置web服务 3、添加vip 4、arp抑制 二、配置LVS 1、添加vip 2、安装配置工具 3、配置DR 三、测试 四、脚本方式配置 1、LVS-DR 2、LVS-RS 环境: master lvs 192.168.80.161 no…

数据结构与算法4-冒泡排序

文章目录 1. 认识冒泡排序2. 图示2.1 图示12.2 图示2 3. 代码 1. 认识冒泡排序 双层for循环,每次选出最大的数“浮”到数组的最后面;时间复杂度O( n 2 n^2 n2),空间复杂度O(1);重复地遍历待排序的数列,一次比较两个元素&#xff…

HCIP配置实验(路由配置)

要求: 1、R6为ISP,接口IP地址均为公有地址,该设备只能配置IP地址,之后不能冉对其进行任何配置; 2、R1-R5为局域网,私有IP地址192.168.1.0/24;请合理分配; 3、R1、R2、R4,各有两个环回IP地址; R5, R6各有一个…

小字辈[天梯赛]

文章目录 题目描述思路AC代码 题目描述 思路 深度优先搜索 具体流程 1.读入每个人的祖先,标记辈分最高的老祖宗对应的下标pos 2.从pos开始dfs,每次判断当前遍历的深度,如果>原来的深度,更新,并将存储最小辈分的数组…