当前位置: 首页 > news >正文

Oracle数据库中的动态SQL(Dynamic SQL)

Oracle数据库中的动态SQL是一种在运行时构建和执行SQL语句的技术。与传统的静态SQL(在编写程序时SQL语句就已经确定)不同,动态SQL允许开发者在程序执行过程中根据不同的条件或用户输入来构建SQL语句。这使得动态SQL在处理复杂查询、存储过程中灵活处理未知或变化的数据结构时非常有用。

1、 动态SQL的类型

Oracle中动态SQL主要有两种形式:

  1. 本地动态SQL(Native Dynamic SQL)

    • 使用EXECUTE IMMEDIATE语句来执行单个的SQL语句或PL/SQL匿名块。
    • 主要用于执行不需要返回结果的SQL语句,如INSERT、UPDATE、DELETE、DDL(数据定义语言)语句等。
    • 也可以使用INTO子句将查询结果存储在PL/SQL变量中。
  2. 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 语言中的一个标准库函数&#xff0c;用于将源字符串复制到目标字符串中。它定义在 <…...

区块链-P2P(八)

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

数据库管理的利器Navicat —— 全面测评与热门产品推荐

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

如何让Google收录我的网站?

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

03 Flask-添加配置信息

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

Codes 开源研发项目管理平台——敏捷测试管理创新解决方案

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

耗时一个月,我做了一个网页视频编辑器

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

uniapp 做一个查看图片的组件,图片可缩放移动

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

卡车配置一键启动无钥匙进入手机控车

‌ 卡车智能一键启动无钥匙进入手机控车&#xff0c;通过手机应用程序与汽车内置硬件、软件的无线通信&#xff0c;实现对汽车的远程控制‌。 卡车改装一键启动的步骤包括安装门把手的感应装置、拆卸仪表台和门板&#xff0c;取出内部的待接线束&#xff0c;并将一键启动…...

计算机网络基础概念 交换机、路由器、网关、TBOX

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、VLAN是什么&#xff1f;二 、交换机三、路由器四、网关五、TBOX六、问题1 、网关和交换机的区别2、网关和路由器的区别 总结 前言 工作有感而发&#xff0…...

labview禁用8080端口

需求背景 最近电脑上安装了labview全家桶,发现idea的8080端口项目启动报错,一直提示8080端口被占用。最简单的办法就是找到8080端口的服务,然后关闭这个服务。但是我不想这么做,我想把labview的web服务器的端口给修改了。 操作教程 1、cmd查看8080端口 2、windows进程 同…...

字符串的KMP算法详解及C/C++代码实现

1. 原由 紧接上文&#xff0c;我们知道了暴力匹配的算法在时间运行上的缺陷&#xff0c;假设字符串T的长度为n&#xff0c;字符串P的长度为m&#xff0c;则整个算法的时间复杂度为O( n * m )&#xff0c;而对于一个复杂的现实情况而言 n >> m >> 2 &#xff08;即…...

2024年数学建模比赛题目及解题代码

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

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...