Oracle数据库中的动态SQL(Dynamic SQL)
Oracle数据库中的动态SQL是一种在运行时构建和执行SQL语句的技术。与传统的静态SQL(在编写程序时SQL语句就已经确定)不同,动态SQL允许开发者在程序执行过程中根据不同的条件或用户输入来构建SQL语句。这使得动态SQL在处理复杂查询、存储过程中灵活处理未知或变化的数据结构时非常有用。
1、 动态SQL的类型
Oracle中动态SQL主要有两种形式:
-
本地动态SQL(Native Dynamic SQL):
- 使用
EXECUTE IMMEDIATE
语句来执行单个的SQL语句或PL/SQL匿名块。 - 主要用于执行不需要返回结果的SQL语句,如INSERT、UPDATE、DELETE、DDL(数据定义语言)语句等。
- 也可以使用
INTO
子句将查询结果存储在PL/SQL变量中。
- 使用
-
DBMS_SQL包:
- 提供了一套用于执行动态SQL语句的接口,允许执行更复杂的动态SQL,包括查询和DML操作。
- 可以处理游标和绑定变量,使得处理查询结果集和参数化查询成为可能。
- 使用步骤包括打开游标、绑定变量、执行SQL语句、处理结果集(如果有的话)、关闭游标。
2、 使用EXECUTE IMMEDIATE
EXECUTE IMMEDIATE
语句非常适合执行简单的动态SQL语句,如:
2.1、从动态PL/SQL块调用子程序
Invoking Subprogram from Dynamic PL/SQL Block
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram created at schema level.
create or replace procedure sp_insert_dept
( deptid in out number,dname in varchar2,mgrid in number,locid in number
) authid definer as
begindeptid := departments_seq.nextval;insert into departments (DEPARTMENT_ID,DEPARTMENT_NAME,MANAGER_ID, LOCATION_ID) values(deptid,dname,mgrid,locid);commit;
end;
/-- 定义输入参数并执行
DECLAREplsql_block VARCHAR2(500);new_deptid NUMBER(4);new_dname VARCHAR2(30) := 'super';new_mgrid NUMBER(6) := 200;new_locid NUMBER(4) := 1700;
BEGIN-- Dynamic PL/SQL block invokes subprogram:plsql_block := 'BEGIN sp_insert_dept(:a, :b, :c, :d); END;';/* Specify bind variables in USING clause.Specify mode for first parameter.Modes of other parameters are correct by default. */EXECUTE IMMEDIATE plsql_block USING IN OUT new_deptid, new_dname, new_mgrid, new_locid;
END;
/
-- 执行结果
deptid = 280 new_dname= dbms_output.put_line new_mgrid= 202 new_locid= 3200PL/SQL procedure successfully completed.-- 检查表数据
HR@192.168.80.190:1521/racdb> select * from departments;DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------10 Administration 200 170020 Marketing 201 180030 Purchasing 114 170040 Human Resources 203 240050 Shipping 121 1500。。。。。。。。中间省略 。。。。。。。。。。。。。280 super 200 1700
2.2、用BOOLEAN形式参数动态调用子程序
Dynamically Invoking Subprogram with BOOLEAN Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of the PL/SQL data type BOOLEAN.
CREATE OR REPLACE PROCEDURE sp_test_boolean (x BOOLEAN) AUTHID DEFINER AS
BEGINIF x THENDBMS_OUTPUT.PUT_LINE('x is true');END IF;
END;
/DECLAREdyn_stmt VARCHAR2(200);b BOOLEAN := TRUE;
BEGINdyn_stmt := 'BEGIN sp_test_boolean(:x); END;';EXECUTE IMMEDIATE dyn_stmt USING b;
END;
/
-- 执行结果
x is truePL/SQL procedure successfully completed.
-- 注意执行成功的数据库版本oracle19c
-- 测试如果是oracle11g的环境会报错
ERROR at line 6:
ORA-06550: line 6, column 36:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored
2.3、用RECORD形式参数动态调用子程序
Dynamically Invoking Subprogram with RECORD Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of the PL/SQL (but not SQL) data type RECORD. The record type is declared in a package specification, and the subprogram is declared in the package specification and defined in the package body.
CREATE OR REPLACE PACKAGE pkg_record_datatype
AUTHID DEFINER
ASTYPE rec IS RECORD (n1 NUMBER, n2 NUMBER);PROCEDURE sp_record_datatype (x OUT rec, y NUMBER, z NUMBER);
END pkg_record_datatype ;
/CREATE OR REPLACE PACKAGE BODY pkg_record_datatype
ASPROCEDURE sp_record_datatype (x OUT rec, y NUMBER, z NUMBER) ASBEGINx.n1 := y;x.n2 := z;END sp_record_datatype ;
END pkg_record_datatype ;
/DECLAREr pkg_record_datatype.rec;dyn_str VARCHAR2(3000);
BEGINdyn_str := 'BEGIN pkg_record_datatype.sp_record_datatype(:x, 100, 1008); END;';EXECUTE IMMEDIATE dyn_str USING OUT r;DBMS_OUTPUT.PUT_LINE('r.n1 = ' || r.n1);DBMS_OUTPUT.PUT_LINE('r.n2 = ' || r.n2);
END;
/
执行结果 – 注意(oracle19c版本),oracle11g依旧报错
r.n1 = 100
r.n2 = 1008
3、 使用DBMS_SQL包
DBMS_SQL
包用于执行更复杂的动态SQL,包括查询和需要处理结果集的DML操作。以下是使用DBMS_SQL
包的基本步骤:
3.1、DBMS_SQL.RETURN_RESULT Procedure
In this example, the procedure p invokes DBMS_SQL.RETURN_RESULT without the optional to_client parameter (which is TRUE by default). Therefore, DBMS_SQL.RETURN_RESULT returns the query result to the subprogram client (the anonymous block that invokes p). After p returns a result to the anonymous block, only the anonymous block can access that result.
CREATE OR REPLACE PROCEDURE sp_dbms_sql_test AUTHID DEFINER ASc1 SYS_REFCURSOR;c2 SYS_REFCURSOR;
BEGINOPEN c1 FORSELECT first_name, last_nameFROM employeesWHERE employee_id = 176;DBMS_SQL.RETURN_RESULT (c1);-- Now p cannot access the result.OPEN c2 FORSELECT city, state_provinceFROM locationsWHERE country_id = 'AU';DBMS_SQL.RETURN_RESULT (c2);-- Now p cannot access the result.
END;
/BEGINsp_dbms_sql_test ;
END;
/
执行结果
ResultSet #1FIRST_NAME LAST_NAME
-------------------- -------------------------
Jonathon TaylorResultSet #2CITY STATE_PROVINCE
------------------------------ -------------------------
Sydney New South Wales
注意:Oracle12c中PL/SQL(DBMS_SQL)新特性之隐式语句结果,DBMS_SQL.RETURN_RESULT隐式返回查询结果,Oracle11g执行上面的示例会报错,不支持RETURN_RESULT。
动态SQL为Oracle数据库应用提供了极大的灵活性和功能,但使用时也需要注意SQL注入等安全问题。因此,在处理用户输入时,应该使用参数化查询或适当的输入验证来防止潜在的安全风险。
3.2、DBMS_SQL.GET_NEXT_RESULT
希望通过客户端应用来处理这些结果集,这可以通过DBMS_SQL包的 GET_NEXT_RESULT过程来解决
DECLAREl_sql_cursor PLS_INTEGER;l_ref_cursor SYS_REFCURSOR;l_return PLS_INTEGER;l_col_cnt PLS_INTEGER;l_desc_tab DBMS_SQL.desc_tab;l_count NUMBER;l_EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE;l_FIRST_NAME EMPLOYEES.FIRST_NAME%TYPE;l_LAST_NAME EMPLOYEES.LAST_NAME%TYPE;
BEGIN-- 执行过程l_sql_cursor := DBMS_SQL.open_cursor(treat_as_client_for_results => TRUE);DBMS_SQL.parse(c => l_sql_cursor,statement => 'BEGIN get_result_emp(30); END;',language_flag => DBMS_SQL.native);l_return := DBMS_SQL.execute(l_sql_cursor);-- 循环遍历每个结果集LOOP-- 获取下个结果集BEGINDBMS_SQL.get_next_result(l_sql_cursor, l_ref_cursor);EXCEPTIONWHEN NO_DATA_FOUND THENEXIT;END;-- 检查结果集列数l_return := DBMS_SQL.to_cursor_number(l_ref_cursor);DBMS_SQL.describe_columns (l_return, l_col_cnt, l_desc_tab);l_ref_cursor := DBMS_SQL.to_refcursor(l_return);-- 根据列数处理结果集CASE l_col_cntWHEN 1 THENDBMS_OUTPUT.put_line('The column is COUNT:');FETCH l_ref_cursorINTO l_count;DBMS_OUTPUT.put_line('l_count=' || l_count);CLOSE l_ref_cursor;WHEN 3 THENDBMS_OUTPUT.put_line('The columns are EMPLOYEE_ID and FIRST_NAME and l_LAST_NAME:');LOOPFETCH l_ref_cursorINTO l_EMPLOYEE_ID, l_FIRST_NAME,l_LAST_NAME;EXIT WHEN l_ref_cursor%NOTFOUND;DBMS_OUTPUT.put_line('l_EMPLOYEE_ID=' || to_char(l_EMPLOYEE_ID) || CHR(9) || 'l_FIRST_NAME=' || l_FIRST_NAME || CHR(9)|| 'l_LAST_NAME=' || l_LAST_NAME);END LOOP;CLOSE l_ref_cursor;ELSEDBMS_OUTPUT.put_Line('I wasn''t expecting that!');END CASE;END LOOP;
END;
/
执行结果
The columns are EMPLOYEE_ID and FIRST_NAME and l_LAST_NAME:
l_EMPLOYEE_ID=114 l_FIRST_NAME=Den l_LAST_NAME=Raphaely
l_EMPLOYEE_ID=115 l_FIRST_NAME=Alexander l_LAST_NAME=Khoo
l_EMPLOYEE_ID=116 l_FIRST_NAME=Shelli l_LAST_NAME=Baida
l_EMPLOYEE_ID=117 l_FIRST_NAME=Sigal l_LAST_NAME=Tobias
l_EMPLOYEE_ID=118 l_FIRST_NAME=Guy l_LAST_NAME=Himuro
l_EMPLOYEE_ID=119 l_FIRST_NAME=Karen l_LAST_NAME=Colmenares
The column is COUNT:
l_count=107PL/SQL procedure successfully completed.
相关文章:
Oracle数据库中的动态SQL(Dynamic SQL)
Oracle数据库中的动态SQL是一种在运行时构建和执行SQL语句的技术。与传统的静态SQL(在编写程序时SQL语句就已经确定)不同,动态SQL允许开发者在程序执行过程中根据不同的条件或用户输入来构建SQL语句。这使得动态SQL在处理复杂查询、存储过程中…...
Python判断两张图片的相似度
在Python中,判断两张以numpy的ndarray格式存储的图片的相似度,通常可以通过多种方法来实现,包括但不限于直方图比较、像素差比较、结构相似性指数(SSIM)、特征匹配等。以下是一些常见方法的简要介绍和示例代码。 1. 像…...

MySQL高级功能-窗口函数
背景 最近遇到需求,需要对数据进行分组排序并获取每组数据的前三名。 一般涉及到分组,第一时间就是想到使用group by对数据进行分组,但这样分组,到最后其实只能获取到每组数据中的一条记录。 在需要获取每组里面的多条记录的时候…...
9.12总结
今天学了树状dp和tarjan 树状dp 树状dp,是一种在树形数据结构上应用的动态规划算法。动态规划(DP)通常用于解决最优化问题,通过将问题分解为相对简单的子问题来求解。在树形结构中,由于树具有递归和子结构的特性&…...

小众创新组合!LightGBM+BO-Transformer-LSTM多变量回归交通流量预测(Matlab)
小众创新组合!LightGBMBO-Transformer-LSTM多变量回归交通流量预测(Matlab) 目录 小众创新组合!LightGBMBO-Transformer-LSTM多变量回归交通流量预测(Matlab)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现LightGBMBO-Transformer-L…...
《CSS新世界》书评
《CSS新世界》是由张鑫旭所著,人民邮电出版社在2021年8月10日出版的一本专门讲解CSS3及其之后版本新特性的进阶读物。这本书是“CSS世界三部曲”中的最后一部,全书近600页,内容丰富,涵盖了CSS的全局知识、已有属性的增强、新布局方…...
python 实现euler modified变形欧拉法算法
euler modified变形欧拉法算法介绍 Euler Modified(改进)变形欧拉法算法,也被称为欧拉修改法或修正欧拉法(Euler Modified Method),是一种用于数值求解微分方程的改进方法。这种方法在传统欧拉法的基础上进…...
strcpy 函数及其缺点
目录 一、概念 二、strcpy 函数有什么缺点 1. 缺乏边界检查 2. 容易引发未定义行为 3. 不适合动态和未知长度的字符串操作 4. 替代方案的可用性 5. 效率问题 一、概念 strcpy 是 C 语言中的一个标准库函数,用于将源字符串复制到目标字符串中。它定义在 <…...

区块链-P2P(八)
前言 P2P网络(Peer-to-Peer Network)是一种点对点的网络结构,它没有中心化的服务器或者管理者,所有节点都是平等的。在P2P网络中,每个节点都可以既是客户端也是服务端,这种网络结构的优点是去中心化、可扩展…...

数据库管理的利器Navicat —— 全面测评与热门产品推荐
在数据库管理领域,Navicat无疑是一款深受欢迎的软件。作为一个强大的数据库管理和开发工具,它支持多种数据库类型,包括MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL等。本文将全面测评Navicat的核心功能,同时推荐几款…...

如何让Google收录我的网站?
其实仅仅只是收录,只要在GSC提交网址,等个两三天,一般就能收录,但收录是否会掉,这篇内容收录了是否有展现,排名,就是另外一个课题了,如果不收录,除了说明你的网站有问题&…...

03 Flask-添加配置信息
回顾之前学习的内容 02 Flask-快速上手 Flask 中最简单的web应用组成 1. 导入核心库 Flask from flask import Flask2. 实例化 web应用 注意:不要漏了 app Flask(__name__) 中的 __name__ 表示:是从当前的py文件实例化 app Flask(__name__)3. 创…...

Codes 开源研发项目管理平台——敏捷测试管理创新解决方案
前言 Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对30人以下团队免费。它通过整合迭代、看板、度量和自动化等功能,简化测试协同工作,使敏捷测试更易于实施。并提供低成本的…...

耗时一个月,我做了一个网页视频编辑器
最近又肝了一个多月,终于把这个网页视频编辑器做好了,下面我来简单介绍一下如何使用 注意目前该功能还处在测试阶段,可能会有很多问题,后续我会不断修复 体验地址 app.zyjj.cc 界面介绍 整个剪辑界面包括4个区,左边是…...

uniapp 做一个查看图片的组件,图片可缩放移动
因为是手机端,所以需要触摸可移动,双指放大缩小。 首先在components里建个组件 查看图片使用 uni-popup 弹窗 要注意 transform的translate和scale属性在同一标签上不会一起生效 移动就根据触摸效果进行偏移图片 缩放就根据双指距离的变大变小进行缩…...

卡车配置一键启动无钥匙进入手机控车
卡车智能一键启动无钥匙进入手机控车,通过手机应用程序与汽车内置硬件、软件的无线通信,实现对汽车的远程控制。 卡车改装一键启动的步骤包括安装门把手的感应装置、拆卸仪表台和门板,取出内部的待接线束,并将一键启动…...
计算机网络基础概念 交换机、路由器、网关、TBOX
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、VLAN是什么?二 、交换机三、路由器四、网关五、TBOX六、问题1 、网关和交换机的区别2、网关和路由器的区别 总结 前言 工作有感而发࿰…...

labview禁用8080端口
需求背景 最近电脑上安装了labview全家桶,发现idea的8080端口项目启动报错,一直提示8080端口被占用。最简单的办法就是找到8080端口的服务,然后关闭这个服务。但是我不想这么做,我想把labview的web服务器的端口给修改了。 操作教程 1、cmd查看8080端口 2、windows进程 同…...
字符串的KMP算法详解及C/C++代码实现
1. 原由 紧接上文,我们知道了暴力匹配的算法在时间运行上的缺陷,假设字符串T的长度为n,字符串P的长度为m,则整个算法的时间复杂度为O( n * m ),而对于一个复杂的现实情况而言 n >> m >> 2 (即…...

2024年数学建模比赛题目及解题代码
目录 一、引言 1. 1竞赛背景介绍 1.1.1数学建模竞赛概述 1.1.2生产过程决策问题在竞赛中的重要性 1.2 解题前准备 1.2.2 工具与资源准备 1.2.3 心态调整与策略规划 二、问题理解与分析 三、模型构建与求解 3.1 模型选择与设计 3.1.1 根据问题特性选择合适的数学模型类…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...