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

背景

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;
/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CentOS安装zsh与ohmyzsh

文章目录 安装 zsh安装 ohmyzsh安装插件.zshrc 配置终端效果 安装 zsh yum install -y git curl # 安装zsh yum install -y zsh # 查看已经安装shell cat /etc/shells # 切换shell chsh -s /bin/zsh安装 ohmyzsh 国内镜像 sh -c "$(curl -fsSL https://gitee.com/pocmo…

算法·动态规划Dynamic Programming

很多人听到动态规划或者什么dp数组了,或者是做到一道关于动态规划的题目时,就会有一种他很难且不好解决的恐惧心理,但是如果我们从基础的题目开始深入挖掘动规思想,在后边遇到动态规划的难题时就迎难而解了。  其实不然&#xff…

数据结构与算法3-选择排序

文章目录 1. 认识选择排序2. 图示2.1 图示12.2 图示2 3. 代码 1. 认识选择排序 双层for循环,每次选出最小的数放到i位置,时间复杂度O( n 2 n^2 n2),空间复杂度O(1);从未排序的序列中找到最小(或最大)的元素&#xff0…

【CNN轻量化】ParameterNet: Parameters Are All You Need 参数就是你所需要的

论文链接:http://arxiv.org/abs/2306.14525 代码链接:https://github.com/huawei-noah/Efficient-AI-Backbones 一、摘要 现有的低FLOPs模型(轻量化模型)无法从大规模预训练中受益。本文旨在增加大规模视觉预训练模型中的参数数量…

程序员的最佳副业居然是炒股

前言 之前的文章 《程序员的最佳副业居然是这个》讲述了个人的副业选择,和各种做过的副业。最后选择了炒股。那么究竟是否能够在股市里赚到利润呢?以我个人最近的交易记录来看,答案是肯定的。 一个半月赚取了 2898 程序员投资的优势 程序…

netty基础_12.用 Netty 自己实现简单的RPC

用 Netty 自己实现简单的RPC RPC 基本介绍我们的RPC 调用流程图己实现 Dubbo RPC(基于 Netty)需求说明设计说明代码封装的RPCNettyServerNettyServerHandlerNettyClientHandlerNettyClient 接口服务端(provider)HelloServiceImplServerBootstrap 客户端(…

概率基础——逻辑回归多分类法

概率基础——逻辑回归多分类法 逻辑回归是一种经典的分类算法,通常用于解决二分类问题。然而,在实际应用中,我们经常会遇到多分类任务。本文将简单介绍逻辑回归的理论、多分类方法以及优缺点,并提供一个Python实现的示例。 逻辑…

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

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

npm出现内部错误,重新设置镜像

问题: 报错解释: 这个错误表明你尝试从一个指定的npm镜像源的响应时失败了。可能的原因包括网络问题、镜像源不可用、DNS解析问题或者镜像源的确已经下线或更改。 1.重新设置镜像源 设置淘宝镜像源: npm config set registry https://re…

网络面试——http 和 https 的区别

区别: 1. HTTP 是超文本传输协议,信息是明文传输,HTTPS 是具有安全性的 SSL 加密传输协议。HTTPS 是由 SSL HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全 2. 端口号:http 使用 80 端口&#…

ros小问题之差速轮式机器人轮子不显示(rviz gazebo)

在rviz及gazebo练习差速轮式机器人时,很奇怪,只有个机器人的底板及底部的两个万向轮,如下图, 后来查看相关.xacro文件,里面是引用包含了轮子的xacro文件,只需传入不同的参数即可调用生成不同位置的轮子&…

代码学习第24天----回溯算法

随想录日记part24 t i m e : time: time: 2024.03.10 主要内容:回溯算法在代码学习中尤其重要,所以今天继续加深对其的理解:1:递增子序列 ;2.全排列 ;3.全排列II 491.递…

MySQL基础-----事务(下)

目录 前言 一、并发事务问题 1.赃读 2.不可重复读 3.幻读 二、事务隔离级别 1.相关操作 2.案例演示 前言 本期我们继续上一期事务的内容,本期的主要讲解的是并发事务的相关问题以及解决方式,内容可能会比较难去理解,不过我会尽量详细说…

C++ UML类图

参考文章: (1)C UML类图详解 (2)C基础——用C实例理解UML类图 (3)C设计模式——UML类图 (4)[UML] 类图介绍 —— 程序员(灵魂画手)必备画图技能之…

31.HarmonyOS App(JAVA)鸿蒙系统app Service服务的用法

鸿蒙系统app Service服务的用法 后台任务调度和管控 HarmonyOS将应用的资源使用生命周期划分为前台、后台和挂起三个阶段。前台运行不受资源调度的约束,后台会根据应用业务的具体任务情况进行资源使用管理,在挂起状态时,会对应用的资源使用进…

《C语言深度剖析》---------关键字(1)

1.双击实质--->加载内存 windows系统里面,双击的本质就是运行程序,把程序加载到内存里面; 任何程序运行的时候都必须加载到内存里面; 程序没有运行之前在硬盘里面,为什么程序运行之前必须加载到内存里面呢&#…

Spring Web MVC入门(5)

响应 在我们前面的代码例子中, 都已经设置了响应数据Http响应结果可以是数据, 也可以是静态页面, 也可以针对响应设置状态码, Header信息等. 返回静态页面 创建前端页面index.html(注意路径) html代码如下: <!DOCTYPE html> <html lang"en"> <hea…

Nutanix 国产化替代|一文了解 SmartX 超融合替代可行性与迁移方案

2022 年 8 月 19 日&#xff0c;Nutanix&#xff08;路坦力&#xff09;宣布中国市场自 2023 财年起将转型为合作伙伴销售主导模式&#xff0c;引起了广泛关注&#xff1b;同时结合当前 IT 基础架构的国产化趋势背景&#xff0c;不少正在使用和考虑使用 Nutanix 产品的企业开始…

Vue 中预加载组件

在 Vue 中&#xff0c;利用 VueRouter 可以轻松的实现两个组件&#xff08;页面&#xff09;之间的切换&#xff0c;有个常用的设计就是需要在登录页登录后跳转至一个内容页&#xff0c;通常的做法是在登录校验完成之后立即切换路由至内容页&#xff0c;接着内容页发送网络请求…

极简生活|2024年让自己越来越好的18个极简好习惯

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 转眼间已经进入了2024年&#xff0c;新的一年&#xff0c;新的开始。 俗话说&#xff1a;百尺高台起于垒土&#xff0c;千里之堤毁于蚁穴。 好习惯积累的越多&#xff0c;坏习惯越来越少&#xff0c;我们的生活才能越…