数据库:PL/SQL
变量
变量 建议使用V开头
作用: 用来保存一个数据
- 普通变量
declare
--定义一个变量(保存一个数据)
v_email varchar2(20);
--定义变量并且赋值
v_ename varchar2(20) :='张三';
beginv_email :='553215@qq.com';dbms_output.put_line(v_email);dbms_output.put_line(v_ename);
end;
- 引用型变量(保存一个数据)–引用某张表的某个字段类型来作为变量的类型
declare
ename emp.ename%type := 'smith';
sal emp.sal%type :='9000';
begindbms_output.put_line(ename||':'||sal);end;
- 记录型变量(用来保存一条数据) --用某张表的一行字段的类型 来 作为变量的类型
declarev_emp emp%rowtype;begindbms_output.put_line(v_emp.empno);dbms_output.put_line(v_emp.ename);dbms_output.put_line(v_emp.job);
end;
- 游标 用来保存多条数据
declare
cursor emp_cursor is select * from emp;
beginfor i in emp_cursor loopdbms_output.put_line(i.empno||':'||i.ename);end loop;end;
- 常量 :constant --定义常量时必须赋值,定义好的常量不能更改
declare
c_name constant varchar2(20):='tom';
beginc_name := 'jack';dbms_output.put_line(c_name);
end;
代码块
代码块就是 (一段程序),一般用来处理数据
例 --查询SMITH的工资
declare
v_sal emp.sal%type;
v_ename varchar2(20):='SMITH';
begin-- v_sal:=salselect sal into v_sal from emp where ename = v_ename;dbms_output.put_line(v_sal);
end;--把7788员工的工资+百分之10 并输出姓名和加百分之10后的工资
declare
v_ename emp.ename%type;
v_empno emp.empno%type:=7788;
v_sal number(9,2);
beginselect ename,sal*1.1 into v_ename,v_salfrom emp where empno = v_empno;dbms_output.put_line(v_ename||':'||v_sal);
end;--查出SMITH所有的信息
declare
v_emp emp%rowtype;
beginselect * into v_emp from emp where ename = 'SMITH';dbms_output.put_line(v_emp.empno||':'||v_emp.ename||':'||v_emp.sal);
end;--输入名字查询 输出姓名和职位,工资
declare
v_ename emp.ename%type:='&输入姓名';
v_job emp.job%type;
v_sal emp.sal%type;
beginselect job,sal into v_job,v_sal from emp where ename = v_ename;dbms_output.put('姓名:'||v_ename);dbms_output.put('职位:'||v_job);dbms_output.put_line('工资:'||v_sal);
end;
dbms_output.put 输出在内存 而且不换行
dbms_output.put_line 把内存的数据进行输出,并且换行
练习
1 查出ALLEN的工资和职位
2 查出scott的入职时间
3 输入员工号 输出员工姓名
4 输入部门号 输出部门名
declare
--1
v_sal emp.sal%type;
v_job emp.job%type;
--2
v_hiredate emp.hiredate%type;
--3
v_empno emp.empno%type := '&员工号';
v_ename emp.ename%type;
--4
v_deptno dept.deptno%type := '&部门号';
v_dname dept.dname%type;
beginselect sal,job into v_sal,v_job from emp where ename ='ALLEN';dbms_output.put_line(v_sal);dbms_output.put_line(v_job);--2select hiredate into v_hiredate from emp where ename = upper('scott');dbms_output.put_line(v_hiredate);--3select ename into v_ename from emp where empno = v_empno;dbms_output.put_line('员工姓名'||v_ename);--4select dname into v_dname from dept where deptno =v_deptno;dbms_output.put_line('部门名'||v_dname);
end;
循环结构
for循环
语法: for 循环变量 in 范围 loop(开始循环) end loop;(结束循环)
--输出10个大数据
declare
begin for i in 1..10 loopdbms_output.put('大数据 ');end loop;dbms_output.put_line(' ');
end;--输出所有员工的姓名
beginfor i in (select ename from emp) loopdbms_output.put_line(i.ename);end loop;
end;--计算1-100之间所有单数和
declare
v_sum number := 0;
beginfor i in 1..100 loopif mod(i,2) = 1 thenv_sum := v_sum+i;end if;end loop;dbms_output.put_line(v_sum);
end; --找到101-999之间的所有水仙花数
declare
g number;
s number;
b number;
beginfor i in 101..999 loopg := substr(i,3,1); -- g = mod(i,10)s := substr(i,2,1); -- s = mod(floor(i/10),10) s = floor(mod(i,100)/10)b := substr(i,1,1); -- b = floor(i/100)if power(g,3)+power(s,3)+power(b,3) = i thendbms_output.put_line(i);end if;end loop;
end; --查出10部门 工资大于1500的人数, 和总工资; 不使用函数
declare
v_sum number := 0;
v_number number := 0;
begin for i in (select sal from emp where deptno = 10) loopv_sum := v_sum+i.sal;if i.sal>1500 thenv_number := v_number + 1;end if;end loop;dbms_output.put_line('部门总工资: '||v_sum);dbms_output.put_line('工资大于1500人数: '||v_number);
end;
while循环
语法:
while 条件 loopsql
end loop;
--有张纸,厚度是1mm,珠穆朗玛峰海拔8848m,请问,这张纸对折多少次,厚度会超过山的高度
declare
v_count number :=0;
v_houdu number := 1;
v_hight number := 8848000;
beginwhile v_houdu<=v_hight loopv_houdu := v_houdu*2;v_count:= v_count+1;dbms_output.put_line('对折次数:'||v_count||' 纸张厚度:'||v_houdu);
end loop;
end;--假如从今天开始存1分钱,每天翻倍,明天2分,后天4分,大后天8分,请问要多少天才能存够100万元
declare
v_deposit number :=0; --存款
v_day number :=0; --存款天数
beginwhile v_deposit<100000000 loopv_deposit := v_deposit+power(2,v_day);v_day := v_day+1;dbms_output.put_line('存款天数:'||v_day||' 存款:'||v_deposit);end loop;
end;
loop循环
语法:
loop exit when 条件 end loop;
--条件满足就退出循环
--用loop循环解决上述两个问题
declare
v_count number := 0; --对折次数
v_houdu number := 1; --纸张厚度
beginloop exit whenv_houdu > 8848000; v_count:=v_count+1;v_houdu:=v_houdu*2;dbms_output.put_line('对折次数:'||v_count||' 纸张厚度:'||v_houdu);end loop;end;declare
v_deposit number := 0; --存款
v_day number := 0; --天数
begin loop exit when v_deposit >= 100000000;v_deposit := v_deposit+power(2,v_day);v_day:=v_day+1;dbms_output.put_line('天数:'||v_day||' 存款:'||v_deposit);end loop;end;
动态sql
语法 execute immediate sql
–DDL 语句在plsql 只能使用动态SQL(create drop alter)
–DML 语句在plsql 可以直接执行 (update,insert delete)
–DQL 语句在plsql 需要使用into (select)(把查询的结果通过into赋值给变量)
--输入表名 删除该表
declare
v_table_name varchar2(20) :='&表名';begin execute immediate 'drop table '||v_table_name;end;
--输入旧表名 输入新表名 复制一张新表
declare
v_old_name varchar2(20) := '&旧表名';
v_new_name varchar2(20) := '&新表名';
beginexecute immediate 'create table '||v_new_name||' as select * from '||v_old_name;
end;
--动态sql 向部门表插入数据
declare
v_sql varchar2(200) :='';
v_deptno number :='&部门编号';
v_dname varchar2(20) :='&部门名称';
v_loc varchar2(30) :='&部门地址';
beginv_sql :='insert into dept values('||v_deptno||','''||v_dname||''','''||v_loc||''')';dbms_output.put_line(v_sql);execute immediate v_sql;end;
游标
用来保存一个查询的结果集
-
静态游标 游标的数据不能发生改变
- 显示游标(自己手动创建 可以看到cursor关键字)
- 隐式游标(程序执行DML 或者select into 语句会自动创建 看不到cursor关键字)
-
动态游标 游标的数据可以发生改变
静态游标
显式游标
--使用while 循环操作游标
--使用游标显示每个人的姓名和工资
declare
--定义游标
cursor emp_cursor is select * from emp;
--定义记录型变量
v_emp emp%rowtype;
begin--打开游标open emp_cursor;--提取数据fetch emp_cursor into v_emp;while emp_cursor%found loop --判断是否提取到数据dbms_output.put_line(v_emp.ename||':'||v_emp.sal);fetch emp_cursor into v_emp;--继续提取游标中的数据,确保循环会终止end loop;--关闭游标close emp_cursor;
end;
--使用for循环操作游标 for循环会自动打开 提取 关闭 游标
declare
cursor emp_cursor is select * from emp;
beginfor i in emp_cursor loopdbms_output.put_line(i.ename||':'||i.sal);end loop;end;select * from dept;
练习
1 使用游标修改工资10部门的员工加百分之十 20部门的员工加百分之二十 30部门的员工加百分之三十
declare
cursor emp_cursor is select * from emp;
beginfor i in emp_cursor loopif i.deptno = 10 then update emp set sal = i.sal*1.1 where empno = i.empno ;elsif i.deptno = 20 thenupdate emp set sal = i.sal *1.2 where empno = i.empno ;elsif i.deptno = 30 thenupdate emp set sal = i.sal*1.3 where empno = i.empno;end if;end loop;end;2 使用游标 输出张三的总成绩,平均成绩 和姓名 (不使用函数)
declare
cursor sc_cursor is select a.cno,a.score from sc_a02 a,student_a02 b where sname = '张三' and a.sno = b.sno;
v_count number :=0; --记录科目数
v_sum_score number :=0; --总成绩
v_avg_score number;
beginfor i in sc_cursor loopv_count:=v_count+1;v_sum_score := i.score+v_sum_score;end loop;v_avg_score := round(v_sum_score/v_count);dbms_output.put_line('总成绩:'||v_sum_score);dbms_output.put_line('平均成绩:'||v_avg_score);dbms_output.put_line('姓名:张三');end;3 使用游标 把平均分大于80的学生信息插入到一张新表 (字段:姓名,年纪,性别,平均分 先创建该表)
beginexecute immediate 'create table exc_stu_info(sname varchar2(20),sage number(3),sex varchar2(2),avg_sc number(5))';
end;
declare
cursor exc_cursor is
select sname,sage,ssex, 平均成绩 from student_a02 a,
(select sno,round(avg(score)) 平均成绩 from sc_a02 group by sno) b
where a.sno= b.sno and 平均成绩 >80;
beginfor i in exc_cursor loopinsert into exc_stu_info values(i.sname,i.sage,i.ssex,i.平均成绩);end loop;
end;
select * from exc_stu_info;
隐式游标
(程序执行DML 或者 select into 语句会自动创建 看不到cursor 关键字 默认游标名SQL)
begin delete from emp where empno=7369;if SQL%found thendbms_output.put_line('删除成功');end if;
end;
–SQL%found 判断是否有数据 有就返回True 没有返回False
–SQL%notfound 判断是否没有数据 没有返回true 有就返回false
–SQL%rowcount
–显示游标代表行数
–隐式游标代表影响(删除,修改)的行数
beginupdate emp set sal = 10000 where deptno =10;if SQL%found then dbms_output.put_line('成功修改'||SQL%rowcount||'条数据');end if;
end;
动态游标
游标的数据可以发生改变(游标可以改变指向) 但是不能用for循环,只能手动打开游标查询数据语法 要先定义动态游标的类型 再定义动态游标变量
declaretype ref_cursor is ref cursor;data_cursor ref_cursor;--定义记录型变量v_dept dept%rowtype;beginopen data_cursor for select * from emp;fetch date_cursor into v_emp; --提取游标数据赋值给记录型变量while data_cursor%found loopdbms_ouput.put_line(v_emp.ename);fetch data_cursor into v_emp;end loop;clos data_cursor;--修改动态游标指向open data_cursor for select * from dept;fetch data_cursor into v_dept;while data_cursor%found loopdbms_output.put_line(v_dept.dname);fetch data_cursor into v_dept;end loop;close data_cursor;
end;
–定义两个静态游标一样可以实现
declare
cursor emp_cursor is select * from emp;
cursor dept_cursor is select * from dept;
beginfor i in emp_cursor loopdbms_output.put_line(i.ename);end loop;for i in dept_cursor loopdbms_output.put_line(i.dname);end loop;
end;
练习
1 --输入部门号 --如果部门号不存在,输出 没有该部门
--如果该部门没有员工 ,输出该部门没有员工 --如果该部门有员工 ,输出该部门所有员工姓名
declare
v_deptno emp.deptno%type :='&部门号';
v_ename varchar2(100);
v_flag number :=0; --0 没有该部门 1 有该部门
v_empnum number :=0;
beginfor i in (select deptno from dept) loopif v_deptno = i.deptno thenV_flag :=1;select count(1) into v_empnum from emp where deptno =v_deptno; if v_empnum=0 thendbms_output.put_line('该部门没有员工');else select LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) into v_ename from emp where deptno = v_deptno group by deptno;dbms_output.put_line(v_ename);end if;end if;end loop;if v_flag = 0 thendbms_output.put_line('没有该部门');end if;end;
2 --使用游标输出公司最高工资,(不使用函数)
declare
cursor emp_cursor is select * from emp;
v_maxsal number:=0;
beginfor i in emp_cursor loopif i.sal > v_maxsal then v_maxsal := i.sal; end if;end loop;dbms_output.put_line(v_maxsal);end;
3 --使用动态SQL 把所有的分区表删除 (select * from user_tab_partitions )
select * from user_tab_partitions;
declare
CURSOR c_part_tables IS SELECT distinct table_name FROM user_tab_partitions;
beginfor i in c_part_tables loopexecute immediate 'drop table "'||i.table_name||'"';execute immediate 'PURGE TABLE "'|| i.table_name||'"';end loop;end;
4 --使用动态SQL 把所有E开头的表复制出来一个新表 (新表名为 原表名+当前时间)--如emp 复制出一张 emp20240911 --提示 查看所有表的语句 (select * from user_tables; )
execute immediate 'create table '||v_new_name||' as select * from '||v_old_name;select * from user_tables;
declare
cursor tab_cursor is select * from user_tables;
beginfor i in tab_cursor loopif substr(i.table_name,1,1) = 'E' thenexecute immediate 'create table '||i.table_name||to_char(sysdate,'yyyymmdd')||' as select * from '||i.table_name;end if;end loop; end;
存储过程
有名字的代码块, 为了完成特定的功能
语法 create or replace procedure 名字(参数) as 声明变量begin 代码块 end
--创建存储过程,添加部门
create or replace procedure add_dept(dno number,dname varchar2,dloc varchar2)
as
begininsert into dept values(dno,dname,dloc);
end;
--调用过程
call add_dept(3,'财务部','东莞');
select * from dept;
--创建一个过程 计算两个数之和
create or replace procedure plus(num1 number,num2 number, result out number)
as
beginresult:=num1+num2;
end;--带有返回值的过程,要在匿名代码块中调用 ,否则不能声明变量接收返回值
declare
r_sum number;
beginplus(100,200,r_sum);dbms_output.put_line(r_sum);
end;
–in 参数 (是一个变量,用于接收传入的数据) 调用者给它赋值
–out 参数 (过程执行完毕得到的数据) 理解为函数的返回值
--传入部门号返回部门的最高工资,最低工资
create or replace procedure get_max_min_sal(dno in number,maxsal out number,minsal out number)
as
beginselect max(sal),min(sal) into maxsal,minsal from emp where deptno = dno;
end;
declare
ma number;
mi number;
beginget_max_min_sal(10,ma,mi);dbms_output.put_line('最高工资'||ma);dbms_output.put_line('最低工资'||mi);
end;--创建一个过程 传入部门号进行删除数据 返回删除的行数
create or replace procedure delete_date(dno in number,d_row out number)
as
begindelete from emp where deptno = dno;d_row := SQL%rowcount;
end;declare
row_d number;
begindelete_date(40,row_d);dbms_output.put_line('删除了'||row_d||'个员工');
end;--作业
1 创建一个过程返回当前时间(年月日时分秒 都要)
create or replace procedure get_date(curr_time out timestamp)
as
begincurr_time := systimestamp;
end;
declare
c_time timestamp;
beginget_date(c_time);dbms_output.put_line('当前时间:'||to_char(c_time,'yyyy-mm-dd HH24:mi:ss'));
end;2 创建一个过程实现和power函数相同功能,返回结果
create or replace procedure v_pow(dishu in number,zhishu in number,result out number)
as
beginif dishu = 0 thendbms_output.put_line('底数不能为0');elsif mod(zhishu,1) = 0 then --限定整数指数if zhishu >0 thenresult :=1;for i in 1..zhishu loopresult := result * dishu;end loop;elsif zhishu = 0 then result :=1;else --指数小于0result :=1;for i in 1..ABS(zhishu) loopresult := result * dishu;end loop;result := 1/result;end if; else result := power(dishu,zhishu);end if;
end;
declare
mi number(10,3);
beginv_pow(2,-2,mi);dbms_output.put_line(mi);
end;3 创建一个过程删除没有员工的部门
create or replace procedure delete_01
as
begindelete from dept where deptno not in (select distinct deptno from emp);
end;call delete_01(); create or replace procedure delete_dept
as
v_count number;
beginfor i in (select deptno from dept) loopselect count(deptno) into v_count from emp where emp.deptno = i.deptno;if v_count = 0 thendelete from dept where deptno = i.deptno;end if;end loop;dbms_output.put_line(sql%rowcount);
end;
select *from dept;
declare
begindelete_dept();
end;4 创建一个过程把30号部门改为33,原来30号的员工 部门号也改为33
create or replace procedure up_info(n out number)
as
v_dept dept%rowtype;
beginselect * into v_dept from dept where deptno=30;--添加部门号33insert into dept values(33,v_dept.dname,v_dept.loc);--修改员工的部门号update emp set deptno = 33 where deptno =v_dept.deptno;n:=sql%rowcount;--删除30号部门delete from dept where deptno = 30;
end;
declare
row_num number;
begin up_info(row_num);dbms_output.put_line('修改了'||row_num||'名员工的部门号');
end;
存储函数
- 存储过程 procedure(DML)
- 可以不返回数据,要返回数据就用out参数
- 存储函数 function(计算)
- 必须要有一个返回值
- 如果要返回多个值,那么也可以用out参数
- 有out参数就不能使用select调用
- 可以用于DML操作,有了之后不能用select调用
--计算两个数之和,返回结果
create or replace function sum_01(num1 number,num2 number)
return number --定义返回类型
as
begin--返回数据return num1+num2;
end;
--select 调用
select sum_01(1,2) from dual;
--declare 调用
declare
n number;
beginn :=sum_01(3,4);dbms_output.put_line(n);dbms_output.put_line(sum_01(5,6));end;
--使用函数 根据部门号返回部门人数和平均工资create or replace function get_sum_count(vno in number, v_sal out number)return numberasv_count number;beginselect count(1),round(avg(sal)) into v_count,v_sal from emp where deptno = vno;return v_count;
end;declare
v_count number;
v_avgsal number;
beginv_avgsal:=get_sum_count(33,v_count);dbms_output.put_line(v_count);dbms_output.put_line(v_avgsal);
end;
触发器
--作用 --1.验证数据--2.数据备份--3.记录日志
--语法
--create or replace trigger 触发器名
--before --被触发的语句先执行 --after --被触发的语句后执行
--操作(delete,update,insert)
--on 表名
--for each for --行级触发
--begin 被触发sql end;
----当员工表 有员工离职时, 自动把该员工的数据插入到离职表
--emp 在职员工表
--emp_back 离职员工表
--获取触发器 操作 的数据
--:old --用于删除,代表旧数据 代表修改之前的数据
--:new --用于添加,代表新数据 代表修改之后的数据
create table emp_back as select * from emp where 1=2;
select * from emp_back;
select * from emp; create or replace trigger delete_emp_trigger
before delete
on emp
for each row
begininsert into emp_back values(:old.empno,:old.ename,:old.job,:old.mgr,:old.hiredate,:old.sal,:old.comm,:old.deptno);
end;--触发sql
delete from emp where empno =7369;--使用触发器,实现订单表和库存表之间的关系
--订单表增加数据,库存表自动减少数量
--库存表
create table stock(
sname varchar2(10),
scount number
);
--订单表
create table orders(
oname varchar2(10),
ocount number
);
insert into stock values('IphoneX',100);
insert into stock values('华为P60',100);insert into orders values('IphoneX',0);
insert into orders values('华为P60',0);
select * from stock;
select * from orders;create or replace trigger stock_order_trigger
after update on orders
for each row
beginupdate stock set scount = scount-(:new.ocount-:old.ocount) where sname = :old.oname;
end;update orders set ocount = ocount+5 where oname = 'IphoneX'; 数据校验
--禁止删除KING 新员工的工资不能超过3000 涨工资不能超过30%
create or replace trigger check_trigger
before delete or update or insert
on emp
for each row
begin if delete thenif :old.ename ='KING' then--手动制造一个错误raise_application_error('-20002','不能删除老板');end if;end if;if insert thenif :new.sal >3000 thenraise_application_error('-20003','新员工工资不能超过3000');end if;end if;if update then if :new.sal >:old.sal*1.3 thenraise_application_error('-20003','工资涨幅不能超过百分之30');end if;end if;
end;数据同步--使用触发器 备份 部门表--创建一个备份表create table dept_back as select * from dept;select * from dept;select * from dept_back;
create or replace trigger backups_trigger
before insert or update or delete on dept
for each row
beginif inserting then insert into dept_back values(:new.deptno,:new.dname,:new.loc);end if;if updating thenupdate dept set dname = :new.dname, loc = :new.loc where deptno = :old.deptno;end if;if deleting thendelete from dept_back where deptno = :old.deptno;end if;
end;记录日志
--(什么人 什么时候 对表做了什么操作)
--创建一个部门日志表
create table dept_log(
deptno number,
dname varchar2(20),
dloc varchar2(20),
ddate varchar2(20),--时间
duser varchar2(20),--操作人
dtype varchar2(20));--操作类型select * from dept_log;create or replace trigger dept_log_trigger
after insert or update or delete on dept
for each row
begin if inserting theninsert into dept_log values(:new.deptno,:new.dname,:new.loc,to_char(sysdate,'yyyy-mm-dd HH24:mi:ss'),user,'insert');end if;if deleting theninsert in dept_log values(:old.deptno,:old.dname,:old.loc,to_char(sysdate,'yyyy-mm-dd HH24:mi:ss'),user,'delete');end if;if updating theninsert in dept_logvalues(:old.deptno,:old.dname,:old.loc,to_char(sysdate,'yyyy-mm-dd HH24:mi:ss'),user,'update_before');insert in deot_logvalues(:new.deptno,:new.dname,:new.loc,to_char(sysdate,'yyyy-mm-dd HH24:mi:ss'),user,'update_after');end if;
end;
程序包
- 包
–可以减少名称的定义
–管理相同的表/业务
–不同的程序包,函数、过程的名称可以重复
--创建程序包--在包里面声明有哪些过程和函数(具体的功能不需要去实现)--过程写到参数部分结束 --函数写到返回值部分结束
--语法
create or replace package 包名
as
过程名(参数)
......
函数名(参数)返回值类型
end 包名
- 包体
--创建包体--实现过程和函数 写具体代码
create or replace body 对应的包名
asprocedure 过程名(参数)asbegin代码end;function 函数名(参数)return 返回值类型asbegin代码return ...;end;
end 包名;
create or replace procedure backup_all_tables
as
cursor back_cursor is select * from user_tables;
beginfor i in back_cursor loopexecute immediate 'create table '||i.table_name||tochar(sysdate,'mmdd')||' as select * from '||i.table_name;end loop;end;call backup_all_tables();
--作业create or replace function my_random(P_LENGTH number,P_INCLUDE_CHAR number)return varchar2asresult_char varchar2(4000) :='';beginif P_INCLUDE_CHAR = 0 thenfor i in 1..P_LENGTH loopresult_char := result_char||floor(dbms_random.value(0,10));end loop;elsif P_INCLUDE_CHAR = 1 thenfor i in 1..P_LENGTH loopresult_char := result_char||dbms_random.string('x',1);end loop;elseraise_application_error('-20000','只能输入0或1');end if;return result_char;
end;declare
begindbms_output.put_line(my_random(5,1));end;--3 有一个字符串abcdefg,需要将这个字符串拆分,每个字母占一行来显示--先创建一个表类型,这个 is table of 表示它是一个表格,这个表格在此处只能有一个字段
create type ty_string is table of varchar2(1);--2创建一个自定义函数,这个函数返回的类型就是上边定义的表类型
create or replace function func_split_str(s varchar2)
return ty_string
as
--将表格类型赋值给一个变量,得到一个表格
t ty_string := ty_string(); --必须赋初值 赋值的过程就是在内存中创建一个空表的过程
beginfor i in 1..length(s) loop--因为表格没有任何内容,甚至连行都没有,所有向表格添加数据前要先创建一个空行t.extend();t(i) := substr(s,i,1); --截取字符串end loop;return t;
end;3.运行这个表类型函数
--在 from 后面 通过table()的方式来调用这个函数,当成一个表格来输出结果
select * from table(func_split_str('abcdefg'));
相关文章:

数据库:PL/SQL
变量 变量 建议使用V开头 作用: 用来保存一个数据 普通变量 declare --定义一个变量(保存一个数据) v_email varchar2(20); --定义变量并且赋值 v_ename varchar2(20) :张三; beginv_email :553215qq.com;dbms_output.put_line(v_email);dbms_output…...

迅雷笔试 最长相等子段数列长度 滑动窗口
👨🏫 牛马Code:最长相等子段数列长度 import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Arrays; import java.util.HashMap;public class Main {// 创建一个输入流读取器,用于读取控制台输…...

MMD模型一键完美导入UE5-VRM4U插件方案(一)
1、下载pmx模型 1、去模之屋官网下载MMD模型,模之屋 2、下载完成得到pmx和Texture文件 2、下载并启用VRM4U插件 1、下载VRM4U插件, VRM4U,点击Latest下载对应引擎版本 2、将插件放到Plugins目录,然后...

bench.sh:一行命令测试Linux服务器基准测试
简介 bench.sh 是一个 Linux 系统性能基准测试工具。它的测试结果如下图:给出服务器的整体配置信息,IO 性能,网络性能。很多人使用它测试 vps 性能。 一键运行 服务器在国外可以使用以下命令运行测试 wget -qO- bench.sh | bash复制…...

广播IP与共享IP的关系
什么是广播IP? 广播IP是指一种特殊的IP地址,用于在网络中向所有设备发送信息。广播地址通常是某个网络段的最后一个地址,例如,在一个子网掩码为255.255.255.0的网络中(即/24子网),其网络地址可…...

正则表达式和re模块
正则表达式(Regular Expression,简称Regex或RegExp)是计算机科学中的一个重要概念,它通常被用来检索、替换那些符合某个模式(规则)的文本。正则表达式是对字符串操作的一种逻辑公式,通过事先定义…...

不同的浏览器、服务器和规范对 URL 长度的限制
不同的浏览器、服务器和规范对 URL 长度的限制有所不同。通常的限制如下: 1. 浏览器限制: 常见浏览器对 URL 长度的限制在 2,000 到 8,000 个字符之间。例如: Internet Explorer: 大约 2,083 个字符。Google Chrome: 理论上支持超过 32,00…...

NASA:ATLAS/ICESat-2 L3 A沿线内陆地表水数据V006数据集
目录 简介 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ATLAS/ICESat-2 L3A Along Track Inland Surface Water Data V006 简介 ATLAS/ICESat-2 L3 A沿线内陆地表水数据V006 ATLAS/ICESat-2 L3 A沿线内陆地表水数据V006是指由ATLAS/ICESat-2卫星获取的针对陆地…...

数据结构之链表(1),单链表
目录 前言 一、什么是链表 二、链表的分类 三、单链表 四、单链表的实现 五、SList.c文件完整代码 六、使用演示 总结 前言 本文讲述了什么是链表,以及实现了完整的单链表。 ❤️感谢支持,点赞关注不迷路❤️ 一、什么是链表 1.概念 概念:链…...

如何构建鲁棒高性能 Prompt 的方法?
你好,我是三桥君 在当今时代,利用大型语言模型如ChatGPT进行文本生成和交互已成为一种趋势。然而,要充分发挥这些模型的能力,尤其是在生产环境中,我们需要精心设计和优化我们的提示词(prompt)。…...

基于Springboot+微信小程序 的高校社团管理小程序(含源码+数据库+lw)
1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…...

Vue 响应式监听 Watch 最佳实践
一. 前言 上一篇文章我们学习了 watch 的基础知识,了解了它的基本使用方法及注意事项,本篇文章我们继续了解在Vue 中 响应式监听 watch 的妙用。了解 watch 的基础使用请参考上一篇文章: 详解 Vue 中 Watch 的使用方法及注意事项https://bl…...
md编辑器语法
这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

RabbitMQ常用管理命令及管理后台
RabbitMQ管理命令 1、用户管理1.1、新增一个用户1.2、查看当前用户列表1.3、设置用户角色1.4、设置用户权限1.5、查看用户权限 2、RabbitMQ的web管理后台2.1、查看rabbitmq 的插件列表2.2、启用插件2.3、禁用插件2.4、访问RabbitMQ的web后台2.4、通过web页面新建虚拟主机 ./rab…...

从准备面试八股文,感悟到技术的本质
工作前几年听说过,大学最重要的几门课其实是数据结构和算法、操作系统、计算机组成原理、计算机网络。 初听时不以为然,感觉没什么用。 近期准备面试八股文得到了一些感悟。这句话随着工作年限和对程序的理解越来越深入,含金量越来越高。 最…...

云手机的默认ip地址是什么
云手机(Cloud Phone)是一种基于云计算技术的虚拟手机,它可以在云端运行,使用户能够通过互联网访问手机应用和服务。云手机的IP地址通常取决于以下几个因素: 1. 云服务提供商 不同的云服务提供商(如AWS、G…...

对接阿里asr和Azure asr
1:对接阿里asr 1.1:pom <dependency><groupId>com.alibaba.nls</groupId><artifactId>nls-sdk-recognizer</artifactId><version>2.2.1</version> </dependency>1.2:生成token package c…...

未来数字世界相关技术、应用:AR/VR/MR;数字人、元宇宙、全息显示
一、AR/VR/MR 增强现实(AR)、虚拟现实(VR)和混合现实(MR)是三种不同的技术,它们都旨在增强用户对现实世界的感知和交互体验。以下是它们的详细介绍: 增强现实(AR) 增强现实(Augmented Reality, AR) 是一种将虚拟信息叠加到现实世界中的技术。通过AR技术,用户可…...

在 Java 中提供接口方法而不是实现接口
问题 我正在阅读有关Java中的接口的文章。其中提到我们必须实现compareTo方法才能在ArrayList容器上调用sort,例如Employee类应该实现 Comparable接口。 后面解释了为什么Employee类不能简单地提供compareTo方法而不实现Comparable接口?之所以需要接口…...

伪类选择器
一、基本概念 伪类选择器以冒号(:)开头,后面跟着伪类名。它不直接对应DOM中的任何元素,而是用于描述元素的特殊状态或位置。通过使用伪类选择器,可以在不修改HTML文档结构的情况下,为元素添加或修改样式。…...

亚信安全天穹5分钟勒索体检 免费试用今起上线
对于勒索攻击的认知 你是否还停留在“2.0时代”? 勒索攻击无疑是企业面临的最大威胁,2024年上半年,勒索组织数量同步增长超过50%,勒索攻击数量也持续攀升,平均勒索赎金突破520万美元。 当前,勒索攻击治理…...

高校竞赛管理系统的设计与实现
摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统高校竞赛管理系统信息管理难度大,容错率低&am…...

物联网行业中通信断线重连现象介绍以及如何实现
01 概述 断线重连是指在计算机网络中,当网络连接遇到异常中断或者断开时,系统会自动尝试重新建立连接,以保证网络通信的连续性和稳定性。这是一种常见的网络通信技术,广泛应用于各种计算机网络场景,包括互联网、局域…...

新手上路:Anaconda虚拟环境创建和配置以使用PyTorch和DGL
文章目录 前言步骤 1: 安装 Anaconda步骤 2: 创建新的 Anaconda 环境步骤 3: 安装最新版本的 PyTorch步骤 4: 安装特定版本的 PyTorch步骤 5: 安装最新版本的 DGL步骤 6: 安装特定版本的 DGL步骤 7: Pycharm中使用虚拟环境解释器第一种情况:创建新项目第二种情况&am…...

centos7系统安装宝塔面板
1、开始安装 适用系统 Centos/OpenCloud/Alibaba 稳定版9.0.0 urlhttps://download.bt.cn/install/install_lts.sh;if [ -f /usr/bin/curl ];then curl -sSO $url;else wget -O install_lts.sh $url;fi;bash install_lts.sh ed8484bec等待命令执行,安装完成&#…...

汽车总线之----J1939总线
instruction SAE J1939 是由美国汽车工程协会制定的一种总线通信协议标准,广泛应用于商用车,船舶,农林机械领域中,J1939协议是基于CAN的高层协议,我们来看一下两者之间的关系。在J1939 中,物理层和数据链路…...

基于skopt的贝叶斯优化基础实例学习实践
贝叶斯方法是非常基础且重要的方法,在前文中断断续续也有所介绍,感兴趣的话可以自行移步阅读即可: 《数学之美番外篇:平凡而又神奇的贝叶斯方法》 《贝叶斯深度学习——基于PyMC3的变分推理》 《模型优化调参利器贝叶斯优化bay…...

OJ在线评测系统 后端 用策略模式优化判题机架构
判题机架构优化(策略模式) 思考 我们的判题策略可能会有很多种 比如 我们的代码沙箱本身执行程序需要消耗时间 这个时间可能不同的编程语言是不同的 比如沙箱执行Java要额外花费2秒 我们可以采用策略模式 针对不同的情况 定义不同独立的策略 而不是把所有情况全部放在一个i…...

element ui 精确控制日期控件 date-picker
https://github.com/element-plus/element-plus/discussions/17378 -- 某组件 xxx.vue ... <el-date-pickerv-model"timeRange"type"daterange"range-separator"-"start-placeholder"开始日期"end-placeholder"结束日期"…...

centos7安装指定版本php及扩展
安装EPEL仓库(如果尚未安装) sudo yum install epel-release导入REMI仓库的公钥: sudo rpm --import http://rpms.remirepo.net/RPM-GPG-KEY-remi启用REMI仓库(你可以选择PHP 7.0或者7.4,以下以7.0为例)&am…...