Oracle--PL/SQL编程
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除
PL/SQL(Procedural Language/SQL)是Oracle数据库中的一种过程化编程语言,构建于SQL之上,允许编写包含SQL语句的程序。它结合了SQL的数据操纵和查询能力与过程化编程的控制结构,如IF语句和LOOP语句,支持变量定义和数据传递,能够实现复杂的业务逻辑。作为Oracle的专用语言,PL/SQL是对标准SQL的扩展,增强了数据库编程的灵活性和功能。
一、PL/SQL块结构
PL/SQL程序以块(block)为基本单位,整个PL/SQL块分为3部分,即声明部分(用DECLARE开头)、执行部分(以BEGIN开头)和异常处理部分(以EXCEPTION开头)。其中,执行部分是必须的,其他两个可选
标准PL/SQL块的语法格式如下:
[DECLARE] --声明部分,可选BEGIN --执行部分,必须[EXCEPTION] --异常处理部分END
1、声明部分
由关键字DECLARE开始,到BEGIN关键字结束。在这里可以声明PL/SQL程序块中用到的变量、常量和游标等。注意,在某个PL/SQL块中声明的内容只能再当前块使用
2、执行部分
以关键字BEGIN开始,结束方式有两种:如果PL/SQL块中的代码在运行时出现异常,则执行完异常处理部分的代码就结束;如果没有使用异常处理或PL/SQL块未出现异常,则以关键字END结束。执行部分是整个PL/SQL块的主体,主要的逻辑控制和运算都在这部分被完成,所以在执行部分可以包含多个PL/SQL语句和SQL语句
3、异常处理部分
以关键字EXCEPTION开始,在该关键字所包含的代码被执行完毕后,整个PL/SQL块也将结束。在执行过程中,可能会产生意想不到的错误,可以在异常处理部分通过编写一定量的代码来纠正错误或给一些提示,甚至将各数据回退到异常前。对于可能出现的多种异常情况,可以使用WHEN THEN语句来实现多分支判断,然后在每个分支下通过编写代码来处理相应的异常。
对于PL/SQL块中的语句,每一条PL/SQL语句都必须以分号结束,而每条PL/SQL语句均可以被写成多行的形式,同样必须使用分号来结束;另外,一行中也可以有多条PL/SQL语句,但是它们之间必须以分号分隔。
示例:定义一个PL/SQL块,计算两个正数的和与这两个整数的差的商:
--实现在服务端显示执行结果set serveroutput on--PL/SQL块declarea int:=100;b int:=200;c number;beginc:=(a+b)/(a-b);dbms_output.put_line(c);exceptionwhen zero_divide thendbmx_output.put_line('除数不允许为零!');end;
二、代码注释和标识符
1、单行注释
单行注释由两个连接字符"--"开始,后面紧跟着注释内容
set serveroutput ondeclareNum_sal number; --声明一个注释变量Var_ename varchar2(20); --声明一个字符串变量beginselect ename,sal into Var_ename,Num_sal from emp --检索指定的值并存储到变量中where empno=7369;dbms_output.put_line(Var_ename||'的工资是'||Num_sal); --输出变量中值end;
2、多行注释
多行注释由"/*"开头,以"*/"结尾,这种多行注释的方法在大多数的编程语言中是相同的
set serveroutput ondeclareNum_sal number; /*声明一个数值变量*/Var_ename varchar2(20); /*声明一个字符串变量*/begin/*检索指定的值并存储到变量中*/select ename,sal into Var_ename,Num_sal from empwhere empno=7369;/*输出变量中的值*/dbms_output.put_line(Var_ename||'的工资是'||Num_sal);end
3、标识符
标识符(identifier)用于定义PL/SQL块和程序单元的名称;通过使用标识符,可以定义常量、变量、异常、显示游标、游标变量、参数、子程序以及包的名称。当使用标识符定义PL/SQL块或程序单元时,需要满足以下规则:
- 当定义变量、常量时,每行只能定义一个变量或者常量(行终止符为";")
- ~,名称必须以英文字符(A-Z,a-z)开始,并且最大长度为30个字符。如果以其他字符开始,那么必须使用双引号引住。
- 名称只能使用A-Z,a-z,0-9以及符号_、$和#。如果使用其他字符,那么必须使用双引号引住
- 名称不能使用Oracle关键字,若需要则以双引号引住
所有PL/SQL程序元素都是由一些字符序列组合而成的,而这些字符序列中的字符都必须取自PL/SQL所允许使用的字符集:
- 大写和小写字母:A-Z或a-z
- 数字:0-9
- 非显示的字符:制表符、空格和按Enterjian
- 数学符号:+、-、*、/、<、>、=等
- 间隔符:()、{}、[]、?、!、;、:、@、#、%、$、&等
4、文本
文本指实际数值的文字,包括数字文本、字符文本、布尔文本、日期时间文本、字符串文本等
- 数字文本:整数或者浮点数。编写PL/SQL代码时,可以十一科学计数法和幂操作符(**)表示。这只适用与PL/SQL语句,不适用SQL语句
- 字符文本:用单引号引住的单个字符。这些字符可以是PL/SQL支持的所有字符
- 布尔文本:通常指BOLLEAN值(TRUE、FALSE和NULL),主要用在条件表达式中
- 日期时间文本:指日期和时间值。日期文本必须用单引号引住,并且日期值必须与日期格式和日期语言匹配
- 字符串文本:由两个或两个以上字符组成的多个字符值。字符串文本必须由单引号引住,
在Oracle Database 10g之前,如果字符串文本包含单引号,必须使用两个单引号表示:例如
string_vat:= 'I''m a string,you''re a string.';
在Oracle Database 10g之后,增加可以使用其他分隔符([]、{}、<>)赋值、需要在分隔符前后加上单引号,而且需要带有前缀q:
string_var:= q'[I'm a string,you're a string.]';
三、基本数据类型
1、数组类型
数组类型包括NUMBER、BINARY_INTEGER和PLS_INTEGER3种类型
- NUMBER类型的变量可以存储整数或浮点数;
- BINARY_INTEGER和PLS_INTEGER类型的变量只能存储整数
NUMBER类型还可以通过NUMBER(p,s)的形式来格式化数字,其中,参数p表示精度,参数s表示刻度范围。精度是指数值中所有有效数字的个数,而刻度范围是指小数点右边小数位的个数,在这里精度和刻度范围都是可选的。
--声明一个精度为8且刻度范围为3的标识金额的变量Num_MoneyNum_Money NUMBER(8,3);
PL/SQL子类型,是与NUMBER类型等价的类型别名,甚至可以说是NUMBER类型的多种重命名形式;这些等价的子类型主要包括DEC、DECIMAL、DOUBLE、INTEGER、INT、NUMERIC、SMALLINT、BINARY_INTEGER、PLS_INTEGER等。
2、字符类型
字符类型主要包括VARCHAR2、CHAR、LONG、NCHAR和HVARCHAR2,用来存储字符串或字符数据。
-
VARCHAR2类型:PL/SQL中的VARCHAR2类型和数据库类型中VARCHAR2比较类似,用于存储可变长度的字符串,其格式:
VARCHAR2(maxlength)
参数maxlength表示可存储字符串的最大长度,定义变量时必须给出(因为VARCHAR2类型没有默认的最大长度),最大值32767字节。
注意:数据库类型中的VARCHAR2的最大长度是4000字节,所以一个长度大于4000字节的PL/SQL中的类型VARCHAR2变量不可以赋值给给数据库中的一个VARCHAR2变量,而只能赋值给LONG类型的数据库变量
-
CHAR类型:表示指定长度的字符串,其语法格式如下:
CHAR(maxlength)
CHAR类型的默认最大长度为1。与VARCHAR2不同,maxlength可以不指定,默认为1。如果赋给CAHR类型的值不足maxlength, 则会在其后面用空格补全,这也是不同于VARCHAR2的地方
注意:数据库类型中的CHAR只有2000字节,所以如果PL/SQL中的CAHR类型变量的长度大于2000字节,则不能赋给数据库中的CHAR。
- LONG类型:表示可变的字符串,最大长度是32 767字节。数据库类型中的LONG最大长度可达2GB。
- NCHAR和NVARCHAR2类型:PL/SQL 8.0以后加入的类型,它们长度根据国字符集来确定。
3、日期类型
日期类型只有一种,即DATE类型,用来存储日期和时间信息。DATE类型的存储空间是7字节,分别使用1字节存储世纪、年、月、天、小时、分钟和秒。
4、布尔类型
布尔类型也只有一种,即BOOLEAN类型,主要用于程序的流程控制和业务逻辑判断,其变量值可以是TRUE、FALSE或NULL中的一种。
特殊数据类型
5、特殊数据类型
5.1、%TYPE类型
使用%TYPE关键字 可以声明一个与指定列相同的数据类型,它通常紧跟在指定列名的后面
--声明一个与emp表中job列的数据类型完全相同的变量var_jobdeclarevar_job emp.job%type;
使用%TYPE定义变量有两个好处:
- 无需手动指定数据类型
- 自动适配数据类型变化
--使用%TYPE类型的变量输出emp表中编号为7369的员工名称和职务信息set serveroutput ondeclarevar_ename emp.ename%type; --声明与ename列类型相同的变量var_job emp.job%type; --声明与job列类型相同的变量beginselect ename,jobinto var_ename,var_jobfrom empwhere empno=7369; --检索数据,并保存在变量中dbms_output.puty_line(var_ename||'的职务是'||var_job); --输出变量的值end;
注意:由于INFO子句中的变量只能存储一个单独的值,因此要求SELECT子句只能返回一行数据,这个由WHERE子句进行了限定。若SELECT子句返回多行数据,则代码运行后会返回错误信息
5.2、RECORD类型
在PL/SQL中,RECORD
类型是一种复合数据类型,用于在单个变量中存储多个相关字段,每个字段可以有不同的数据类型。RECORD
类型常用于从数据库表或多列查询中检索数据,并将这些数据存储在一个单一的变量中,便于操作和传递。
TYPE record_type IS RECORD --record_type表示要定义的记录数据类型名称(var_menber1 data_type [not_null] [:=default_value], --data_type:表示成员变量的数据类型...var_membern data_type [not_null] [:=default_value])
记录类型的声明类似于C或C++中的结构类型,并且成员变量的声明与普通PL/SQL变量的声明相同。
声明一个记录类型 emp_type,然后使用该类型的变量存储emp表中的一条记录信息,并输出这条记录信息,代码:
declaretype emp_type is record --声明RECORD类型emp_type(var_ename varchar2(20), --定义字段/成员变量var_job varchar2(20),var_sal number);empinfo emp_type; --定义变量beginselect ename,job,salinto empinfofrom empwhere empno=7369; --检索数据/*输出员工信息*/dbms_output.put_line('员工'||empinfo.var_ename||'的职务是'||empinfo.var_job||'、工资是'empinfo.var_sal);end;
5.3、%ROWTYPE类型
%ROWTYPE类型的变量结合了"%TYPE类型"和"记录类型"变量的优点,它可以根据数据表中行的结构定义一种特殊的数据类型,用来存储从数据表中检索到的一行数据,其语法:
rowVar_name table_name%ROWTYPE;
--示例:声明一个%ROWTYPE类型的变量rowVAR_emp,然后使用该变量存储emp表中的一行数据declarerowVar_emp emp%rowType; --定义能够存储emp表中一行数据的变量rowVar_empbeginselect *into rowVar_empfrom empwhere empno=7369; --检索数据/*输出员工信息*/dbms_output.put_line('员工'||rowVar_emp.empno||',职务是'||rowVar_emp.job);end;
6、自定义变量和常量
6.1、定义常量
<变量名><数据类型>[(长度):=<初始值>];
--示例:定义一个用于存储国家名称的可变字符串变量var_countryname,该变量的最大长度是50,并且该变量初始值是"中国"var_countryname varchar2(50):= '中国';
6.2、变量的初始化
PL/SQL定义了一个未初始化变量应该存储的内容,其值被赋值为NULL
6.3、PL/SQL表达式
(1)字符表达式
唯一的字符运算符就是并置运算符 "||",它的作用是把几个字符串连在一起,如表达式'Hello'||'World'||'!'的值就等于'Hello Wordl!'。
(2)布尔表达式
PL/SQL控制结构都涉及布尔表达式。布尔表达式是一个判断结果为真还是假的条件表达式,值有TRUE、FALSE或NULL;
布尔表达式有3个布尔运算符,即AND、OR和NOT,与高级语言中的逻辑运算符一样,它的操作对象时布尔变量或表达式
此外,BETWEEN操作符可以划定一个范围,在范围内则为真,否则为假;
IN操作符判断某一元素是否属于某个集合,属于则问真,不属于则为假
7、流程控制语句
控制语句 | 说明 |
---|---|
if...then | 判断IF正确,则执行THEN |
if...then...else | 判断IF正确,则执行THEN,否则执行ELSE |
if...then...elsif | 嵌套式判断 |
case | 有逻辑地从数值中做出选择 |
loop...exit...END | 循环控制,用判断语句执行EXIT |
loop...exit when...END | 同上,当WHRN为真时执行EXIT |
while...loop...END | 当WHILE为真时循环 |
for...in...loop...END | 已知循环次数的循环 |
goto | 无条件转向控制 |
7.1、选择语句
(1)IF...THEN语句
只做一种情况或条件的判断,其语法:
IF <condition_expression> THEN
plsql_sentence
END IF;
--定义两个字符串变量,赋值,使用IF...THEN比较其长度,并输出结果set serveroutput ondeclarevar_name1 varchar2(50); --定义两个字符串变量var_name2 varchar2(50);beginvar_name1:='Wast'; --给两个字符串变量赋值var_name2:='xiaofei';if length(var_name1) < length(var_name2) then --比较长度大小/*输出比较后的结果*/dbms_output.put_line('字符串"'||var_name1||'"的长度比字符串"'||var_name2||'"的长度小')end if;end;
如果IF后面的条件表达式存在"并且"或者"非"等逻辑运算,则可以使用AND、OR、NOT等逻辑运算符。另外,如果要判断IF后面的条件表达式的值是否为空值,则需要在条件表达式中使用is和null关键字,如:
if last_name is null then...end if;
(2)IF...THEN...ELSE语句
可以实现判断两种情况,只有IF后面的条件表达式为FALSE,程序就会执行ELSE语句下面的PL/SQL语句,其格式:
IF < condition_expression> THEN
plsql_sentence1;
ELSE plsql_sentence2;
END IF;
--只有年龄大于或等于60岁,才可以申请退休的功能,否则程序会提示不可申请退休set serveroutput ondeclareage int:=55;beginif age >= 60 thendbms_output.put_line('您可以申请退休了!');elsedbms_output.put_line('您小于60岁,不可以申请退休!')end if;end;
(3)IF...THEN...ELSIF语句
实现多分支判断选择,使程序的判断条件更丰富。如果该语句中的哪个判断分支的表达式为TRUE,那么程序就会执行对应的PL/SQL语句,其格式:
IF < condition_expression1 > THEN
plsql_sentence_1;
ELSIF < condition_expression2 >
THEN plsql_sentence_2;
...
ELSE plsql_sentence_n;
END IF;
--首先指定一个月份数值,然后使用其语句判断它所属的季节,并输出季节信息:set serveroutput ondeclaremonth int:=6;beginif month >= 0 and month <= 3 thendbms_output.put_line(month||'月是春季');elsif month >= 4 and month <= 6 thendbms_output.put_line(month||'月是夏季');elsif month >= 7 and month <= 9 thendbms_output.put_line(month||'月是秋季');elsif month >= 10 and month <= 12 thendbms_output.put_line(month||'月是冬季');elsedbms_output.put_line('对不起,月份不合法!');end if;end;
(4)case语句
CASE语句的执行方式与IF..THEN...ELSIF语句十分相似。在CASE关键字的后面有一个选择器,它通常是一个变量,程序就是从这个选择器开始执行
CASE < selector>
WHTN <expression_1> THEN plsql_sentence_1;
WHTN <expression_2> THEN plsql_sentence_2;
...
WHTN <expression_n> THEN plsql_sentence_n;
[ELSE plsql_sentence;]
END CASE;
--示例:指定一个季度数的值,然后使用CASE语句判断它所包含的月份信息并输出set serveroutput ondeclaresession int:=3;aboutInfo varchar2(50);begincase seasonwhen 1 thenaboutInfo := season||'季度包括1,2,3月份';case seasonwhen 2 thenaboutInfo := season||'季度包括4,5,6月份';case seasonwhen 3 thenaboutInfo := season||'季度包括7,8,9月份';case seasonwhen 4 thenaboutInfo := season||'季度包括10,11,12月份';else aboutInfo := season||'季度不合法';end case;dbms_output.put_line(aboutinfo);end;
在执行多种情况判断时,建议使用CASE语句替换IF...THEN...ELSIF语句。
7.2、循环语句
(1)LOOP语句
LOOP语句会先执行一次循环体,然后判断EXIT WHEN关键字后面的条件表达式的值是TRUE还是FALSE。如果是TRUE,程序会退出循环体;否则再次执行循环体。这使得程序至少能执行一次循环体,其格式:
LOOP
plsql_sentence;
EXIT WHEN end_condition_exp
END LOOP
--示例:使用LOOP计算前100个自然数的和,并输出到屏幕set serveroutput ondeclaresum_i int:= 0;i int:= 0;beginloopi:=i+1;sum_i = sum_i+i;exit when i =100; --当循环到100时退出循环体end loop;dbms_output.put_line('前100个自然数的和是:'||sum_i);end;
(2)WHILE语句
WHILE语句根据它的条件表达式的值执行零次或多次循环体,在每次执行循环体之前,首先要判断条件表达式的值是否为TRUE,若为TRUE,则程序执行循环体;否则退出WHILE循环,然后继续执行WHILE语句后面的其他代码,其语法:
WHILE condition_expression LOOP
plsql_sentence;
END LOOP;
--示例:使用WHILE语句计算前100个自然数的和,并输出到屏幕set serveroutput ondeclaresum_i int := 0;i int := 0;beginwhile i<=99 loop --当i的值等于100时,程序退出WHILE循环i:=i+1sum_i := sum_i+i,end loop;dbms_output.pu_line('前100个自然数的和是:'||sum_i);end;
(3)FOR语句
FOR语句时一个可预置循环次数的循环控制语句,它有一个循环计数器,通常是一个整型变量,通过这个循环计数器来控制循环执行的次数。该计数器可以从小到大进行记录,也可相反。另外,该计数器值的合法性由上限值和下限值控制,若计数器值在上限值和下限值的范围内,则程序执行循环;否则终止;其格式:
FOR variable_counter_name in [REVERSE] lower_limit..upper_limit LOOP
plsql_sentence;
END LOOP;
--示例:使用FOR语句计算前100个自然数中偶数之和,并输出到屏幕set serveroutput ondeclaresum_i := 0;beginfor i in reverse 1..100 loop --遍历前100个自然数if mod(i,2)=0 then --判断是否为偶数sum_i:=sum_i+i; --计算偶数和end if;end loop;dbms_output.put_line('前100个自然数中偶数之和是:'||sum_i);end;
(4)GOTO语句
GOTO label;
这个是无条件转向语句。当执行GOTO语句时,控制程序会立即转到由标签标识的语句中。其中,label是在PL/SQL中定义的符号。标签使用双箭头括号(<<>>)括起来
--示例.. --程序其他部分<<goto_mark>> --定义了一个转向标签goto_mark.. --程序其他部分IF no>98050 THENGOTO goto_mark; --如果条件成立,则转向goto_mark继续执行.. --程序其他部分
8、游标
游标提供了一种从表中检索数据并进行操作的灵活手段,游标主要用在服务器上,处理由客户端发送给服务端的SQL语句,或是批处理、存储过程、触发器中的数据处理请求。游标的作用就相当于指针,通过游标PL/SQL程序可以一次处理查询结果集中的一行,并可以对该数值执行特定操作。
在Oralce中,通过游标操作数据主要使用显式游标和隐式游标。另外还包括具有引用类型特性的REF游标
8.1、基本原理
在PL/SQL块中执行SELECT、INSERT、UPDATE和DELETE语句时,Oracle会在内存中为其分配上下文区,即一个缓冲区。游标是指向该区的一个指针,或是命名一个工作区,或是一种结构化数据类型。游标为应用程序提供了一种具有对多行数据查询结果集中的每一行数据分别进行单独处理的方法,是设计嵌入式SQL语句的应用程序的常用编程方法。
8.2、显式游标
显式游标是由用户声明和操作的一种游标,通常用于操作查询结果集,使用它处理数据的步骤包括声明游标、打开游标、读取游标和关闭游标4个步骤。其中,读取游标可能需要反复操作,因为游标每次只能读取一行数据,所以对于多条记录,需要反复读取。
(1)声明游标
声明游标主要包括指定游标名称和为游标提供结果集的SELECT语句,其格式:
CURSOR cur_name[(input_parameter1[,input_paramater2]...)] [RETURN ret_type]
IS select_ setence;
--cur_name:表名所声明的游标名称
--ret_type:表名执行游标操作后的返回值类型,这是一个可选项
--select_sentence:游标所使用的SELECT语句,为游标的反复读取提供了结果集
--input_paramater1:作为游标的"输入参数"可以有多个,这是一个可选项。它指定用户在打开游标后向游标中传递的值,该参数的定义和初始化格式如下:
para_name [IN] DATATYPE [{:= | DEFAULT} para_value]
--示例:声明游标,用来读取emp表中职务为销售员(SALESMAN)的员工信息declarecursor cur_emp(var_job in varchar2:='SALESMAN')is select empno,ename,salfrom empwhere job=var_job;
在上述代码中,首先声明了一个名称为cur_emp的游标,并定义了一个输入参数var_job(类型为varchar2,但不可以指定长度,否则程序报错),该参数用来存储员工的职务(初始值为SALESMAN);然后使用SELECT语句检索得到职务是销售员的结果集,以等待游标逐行读取它。
(2)打开游标
游标声明完后,必须打开游标才能使用,其格式:
OPEN cur_name[(para_value[,para_value2]...)];
打开游标就是执行定义的SELECT语句。执行完毕,将查询结果装入内存,游标停在查询结果的首部(注意,并不是第一行)。打开一个游标时,会完成以下几件事:
- 检查联编变量的取值
- 根据联编变量的取值,确定活动集
- 活动集的指针指向第一行
--打开游标cur_emp,给游标的"输入参数"赋值为"MANAGER"OPEN cur_emp('MANAGER'); --若省略('MANAGER')则表示使用默认值
(3)读取游标
当打开一个游标后,就可以读取游标中的数据了,读取游标就是逐行将结果集中的数据保存到变量中。读取游标使用FETCH...INTO语句,其格式:
FETCH cur_name INTO {variable};
在游标中包含一个数据行指针,它用来指向当前数据行。刚打开游标时,指针指向结果集中的第一行,当使用FETCH...INTO语句读取数据完毕之后,游标中的指针将自动指向下一行数据。这样,就可以在循环结构中使用FETCH...INTO来读取数据,知道指针指向结果集中最后一条记录为止,这时游标的%FOUND属性值为FALSE;
--声明一个检索emp表中员工信息的游标,然后打开游标,并指定检索职务是MANAGER的员工信息,接着使用FETCH...INTO语句和WHILE循环语句读取游标中的所有员工信息,最后输出读取的员工信息set serveroutput ondeclare/*声明游标,检索员工信息*/cursor cur_emp(var_job in varchar2:='SALESMAN')is select empno,ename,salfrom empwhere job=var_job;type record_emp is record --声明一个记录类型(/*定义当前记录的成员变量*/var_empno emp.empno%type,var_ename emp.ename%type,var_sal emp.sal%type);emp_row record_emp; --声明一个record_emp类型的变量beginopen cur_emp('MANAGER'); --打开游标fetch cur_emp into emp_row; --先让指针指向结果集中的第一行,并将值报错到emp_row中while cur_emp%found loopdbms_output.put_line(emp_row.var_ename||'的编号是'||emp_row.var_empno||',工资是'||emp_row.var_sal);fetch cur_emp into emp_row; --让指针指向结果集中的下一行,并将值保存到emp_row中end loop;close cur_emp; --关闭游标end;/
(4)关闭游标
当所有活动集都被检索以后,游标就应该被关闭。其语法:
CLOSE cur_name;
一旦关闭了游标,SELECT操作就会被关闭,并释放占用的内存区。如果再从游标提取数据就是非法的,这样做会产生以下两种错误:
ORA-1001:Invalid CUSOR --非法游标ORA-1002:FETCH out of sequence --超出界限
8.3、隐式游标
在执行一个SQL语句时,Oracle会自动创建一个隐式游标,这个游标是内存中处理该语句的工作区域。隐式游标主要是处理数据操作语语句(如UPDATE、DELETE语句)的执行结果,当然在特殊情况下,也可以处理SELECT语句的查询结果。由于隐式游标也有属性,因此当使用隐式游标的属性时,需要在属性前面加上隐式游标的默认名称-SQL
在实际的PL/SQL编程中,经常使用隐式游标来判断更新数据行或删除数据行的情况
--示例:把emp表中销售员的工资上调20%,然后使用隐式游标SQL的%ROWCOUNT属性输出上调工资的员工数量set serveroutput onbeginupdate empset sal=sal*(1+0.2)where job='SALESMAN';if sql%notfound thendbms_output.put_line('没有员工需要上调工资');else --若UPDATE语句没有影响到一行数据dbms_output.put_line('有'||sql%rowcount||'个员工工资上调20%');end if;end;/
8.4、游标的属性
无论是显式游标还是隐式游标,都具有%FOUND、%NOTFOUND、%ROWCOUNT和%ISOPEN 4个属性,通过这4个属性可以获知SQL语句的执行结果以及该游标的状态信息
游标属性只能用在PL/SQL的流程控制语句内,而不能用在SQL语句内。
(1)是否找到游标(%FOUND)
布尔型属性,如果SQL语句至少影响到一行数据,则该属性为TRUE否则为FALSE,检查此属性可以判断是否结束游标使用
open cur_emp; --打开游标fetch cur_emp into var_ename,var_job; --将第一行数据放入变量中,游标后移loopexit when not cur_emp%found; --使用了%FOUND属性end loop;
在隐式游标中%FOUND属性的引用方法是SQL%FOUND:
delete from emp where empno = emp_id; --emp_id为一个有值变量
if sql%found then --删除成功则将该行员工编号写入success表中insert into success values(empno);
else --失败则写入fail表中insert into fail values(empno);
end if;
(2)是否没找到游标(%FOUND)
与%FOUND相反,这里省略
(3)游标行数(%ROWCOUNT)
%ROWCOUNT属性 记录了游标抽取过的记录行数,也可以理解为当前游标所在的行号。这个属性在循环判断中也很有用,使得不必抽取所有记录行就可以中断游标操作。
loopfetch cur_emp into var_empno,var_ename,var_job;exit when cur_emp%rowcount = 10; --只抽取10条记录...end loop;
还可以使用FOR语句控制游标的循环,系统隐含地定义了一个数据类型为ROWCOUNT的记录,作为循环计数器,将隐式地打开和关闭游标
(4)游标是否打开(%ISOPEN)
%ISOPEN属性 表示游标是否处理打开状态。在实际应用中,使用一个游标前,第一步往往是检查它的%ISOPEN属性,看其是否已打开,若没有,要打开游标再往下操作。
if cur_emp%isopen thenfetch cur_emp into var_empno,var_ename,var_job;elseopen cur_emp;end if;
在隐式游标中此属性的引用方法是SQL%ISOPEN。隐式游标中SQL%ISOPEN属性总为TRUE,因此在隐式游标中不用打开和关闭游标,也不用检查其打开状态
(5)参数化游标
在定义游标时,可以带上参数,使得在使用游标时,根据参数不同所选中的数据行业不同,达到动态使用的目的
--声明一个游标,用于检索指定员工编号的员工信息,然后使用游标的%FOUND属性来判断是否检索到指定员工编号的员工信息set serveroutput ondeclarevar_ename varchar2(50); var_job varchar2(50);/*声明游标,检索指定员工编号的员工信息*/cursor cur_empis select ename.jobfrom empwhere empno=7499;beginopen cur_emp;fetch cur_emp into var_ename,var_job;if cur_emp%found thendbms_output.put_line('编号是7499的员工名称为:'||var_ename||',职务是:'||var_job);elsedbms_output.put_line('无数据记录');end if;end;/
8.5、游标变量
(1)声明游标变量
游标变量时一种引用类型。当程序运行时,他们可以指向不同的存储单元。如果要使用引用类型,首先要生命该变量,然后使用相应的存储单元必须被分配。PL/SQL中的引用类型变量通过下述语法进行声明:
REF type
type是已经被定义的类型。REF关键字指明新的类型必须是一个指向经过定义的类型的指针。因此,游标变量可以使用的类型就是REF CURSOR。定义一个游标变量其语法:
TYPE <类型名> IS REF CURSORRETURN <返回类型>
游标变量的返回类型必须是一个记录类型。它可以被显式声明为一个用户定义的列表,或隐式使用%ROWTYPE进行声明。在定义了引用类型后就可以声明该变量了
set serveroutput ondeclaretype t_StudentRef is ref cursor --定义使用%ROWTYPEreturn students%rowtype;type t_AbstractstudentsRecord is record( --定义新的记录类型sname students.sname%type,sex students.sex%type);v_AbstractStudentsRecord t_AbstractstudentsRecord;type t_AbstractStudentsRed is ref corsor --使用记录类型的游标变量return t_AbstractStudentsRecord;type t_NameRef2 is ref cursor --另一类型定义return v_AbstractStudentsRecord%type;v_StudentCV t_StudentsRef; --声明上述类型的游标变量v_AbstractStudentCV t_AbstractStudentsRef;
在上述代码中极少的游标变量时受限的,它的返回类型只能是特定类型。而在PL/SQL语句中,还有一种非受限游标变量,它在声明时没有return子句,一个非受限游标变量可以为任何查询打开
declare--定义非受限游标变量type t_FlexibleRefIS ref cursor;--游标变量V_CURSORVar t_FlexiableRef;
(2)打开游标变量
如果要将一个游标变量与一个特定的SELECT语句相关联,需要使用OPEN FOR语句
OPEN<游标变量>FOR<SELECT语句>;
如果游标变量是受限的,则SELECT语句的返回类型必须与游标变量所受限的记录类型匹配,如果不匹配,则Oracle会返回错误ORA_6504。
--打开游标变量v_StudentSCVDECLARETYPE t_StudentRef IS REF CURSOR --定义使用%ROWTYPERETURN STUDENTS%ROWTYPE;v_StudentSCV t_StudentRef; --定义新的记录类型 BEGINOPEN v_StudentSCV FORSELECT * FROM STUDENTS;END;
(3)关闭游标变量
游标变量的关闭和静态游标的关闭类型,均使用CLOSE语句。关闭已经关闭的游标变量是非法的。
8.6、通过FOR语句循环游标
在使用隐式游标或显式游标处理具有多行数据的结果集时,可以配合使用FOR语句来完成。在使用FOR语句遍历游标中的数据时,可以把它的计时器看做一个自动的RECORD类型的变量
在FOR语句中变量隐式游标中的数据时,通常在关键字IN的后面提供由SELECT语句检索的结果集,在检索结果集的过程中,Oracle系统会自动提供一个隐式的游标SQL
--使用隐式游标和FOR语句检索出的职务是销售员的员工信息并输出set serveroutput onbeginfor emp_record in (select empno,ename,sal from emp where job='SALESMAN') --遍历隐式游标中的记录loopdbms_output.put('员工编号:'||emp_record.empno); dbms_output.put(':员工名称:'||emp_record.ename); dbms_output.put_line(':员工工资:'||emp_record.sal); end loop;end;/
在FOR语句中变量显式游标中的数据时,通常在关键字IN的后面提供游标的名称,其格式:
FOR var_auto_record IN cur_name LOOP
plsqlsentence;
END LOOP;
--使用显式游标和FOR语句检索部门编号是30的员工信息并输出set serveroutput ondeclarecursor cur_emp is select * from empwhere deptno = 30; --检索部门编号为30的员工信息beginfor emp_record in cur_emp --遍历员工信息loopdbms_output.put('员工编号:'||emp_record.empno);dbms_output.put(':员工名称:'||emp_record.ename);dbms_output.put_line(': 员工职务:'||emp_reocrd.job);end loop;end;/
注意:在使用游标(包括显式和隐式)的FOR循环中,可以声明游标,但不用进行打开、读取和关闭游标等操作,这些由Oracle自动完成
9、异常处理
9.1、异常处理方法
(1)预定义异常处理
每当PL/SQL程序违反了Oracle的规则或超出系统的限制时,系统就自动地产生内部异常。每个Oracle异常都有一个号码,但异常必须按名个处理。因此PL/SQL对那些常见的异常预定义了异常名。
(2)用户自定义异常
- 异常声明:包括预定义异常和用户自定义异常。用户定义的异常只能再PL/SQL块的声明部分进行声明,声明方式与变量声明类似
- 抛出异常:使用RAISE语句显式地提出
- 为内部异常命名:必须使用OTHERS处理程序或用伪命令EXCEPTION_INIT来处理未命名的内部异常
注意:异常是一种状态而不是一个对象,因此异常名不能出现在赋值语句或SQL语句中。PRAGMA EXCEPTION_INIT的作用是将一个异常名与一个Oracle错误号码联系起来。因此,用户就可以按名称引用任何内部异常,并为它编写一个特定的处理程序。
9.2、异常处理语法
(1)声明异常
exception_name EXCEPTION
(2)为内部异常命名
PRAGE EXCEPTION_INIT(exception_name.ORA_errornumber);
(3)异常定义
DECLAREexception_name EXCEPTION;BEGINIF condition THENRAISE exception_name;END IF;EXCEPTIONWHERE exception_name THENstatement;END;
(4)异常处理
SET SERVEROUTPUT ONEXCEPTIONWHEN exception1 THENstatement1WHEN exception2 THENstatement2...WHEN OTHERS THENstatement3
(5)使用SQLCODE和SQLERRM函数定义提示信息
DBMS_OUTPUT.PUT_LINE('错误号:'||SQLCODE);DBMS_OUTPUT.PUT_LINE('错误号:'||SQLERRM);
9.3、预定义异常
以下是一些在Oracle官方文档中查找预定义异常的常用链接:
- Oracle Database PL/SQL Language Reference
- Oracle Database PL/SQL Packages and Types Reference
-
Oracle Database Error Messages
--示例:使用SELECT INTO语句检索emp表中部门编号为10的员工记录信息,然后使用TOO_MANY_ROWS预定义异常捕获错误信息并输出set serveroutput ondeclarevar_empno number; --定义变量,存储员工编号var_ename varchar2(50); --定义变量,存储员工名称beginselect empno,ename into var_empno,var_enamefrom empwhere deptno=10; --检索部门编号为10的员工信息if sql%found then --若检索成功,则输出员工信息dbms_output.put_line('员工编号:'||var_empno||':员工名称'||var_ename);end if;exception --捕获异常when too_many_rows thendbms_output.put_line('返回记录超过一行');when no_data_found thendbms_output.put_line('无数据记录');end;/
9.4、自定义异常
(1)错误编号异常
错误编号是指在Oracle系统发生错误时,系统会显示错误号和相关描述信息的异常。虽然直接使用错误编号也可以完成异常处理 ,但错误编号较为抽象,不易于用户理解和记忆。对于这种异常,首先在PL/SQL块的声明部分(DECLARE部分)使用EXCEPTION类型定义一个异常变量名,然后使用语句PRAGMA EXCEPTION_INIT为"错误编号"关联"这个异常变量名",接下来就可以像对待系统预定义异常一样处理了。
--插入一条已存在的记录,会报错insert into dept values(10,'研发部','QINGDAO');--首先定义错误编号"00001"的异常处理,然后向dept表中插入一条能够违反"唯一约束条件"的记录,最后在EXCEPTION代码体中输出异常提示信息set serveroutput ondeclareprimary_iterant exception;pragma exception_init(primary_iterant,-00001);begin/*向dept表中插入一条与已有主键值重复的记录,以便引发异常*/insert into dept values(10,'研发部','青岛');exception
(2)业务逻辑异常
在实际的应用中,程序开发人员可以根据具体的业务逻辑规则自定义一个异常。这样,当用户操作违反业务逻辑规则时,就会引发一个异常,从而中断程序的正常执行,并转到自定义的异常处理部分。
无论是预定义异常,还是错误编号异常,都是由Oracle系统判断的错误,但业务逻辑异常是Oracle系统本身无法知道的,这样就需要一个引发异常的机制,引发业务逻辑异常通常使用RAISE语句来实现。当引发一个异常时,控制就会转到EXCEPTION异常处理部分执行异常处理语句。业务逻辑异常首先要在DECLARE部分使用EXCEPTION类型声明一个异常变量,然后在BEGIN部分根据一定的业务逻辑规则执行RAISE语句,最后在EXCEPTION部分编写异常处理语句
--自定义一个异常变量,向dept表中插入数据时,若判断loc字段的值为NULL,则使用RAISE语句引发异常,并将程序的执行流程转入EXCEPTION部分中进行处理set serveroutput ondeclarenull_exception exception; --声明一个EXCEPTION类型的异常变量dept_row dept%rowtype; --声明ROWTYPE类型的变量dept_rowbegindept_row.deptno := 66; --给部门编号变量赋值dept_row.dname := '公关部'; --给部门名称变量赋值insert into deptvalues(dept_row.deptno,dept_row.dname,dept_row.loc); --插入一条记录if dept_row.loc is null then --如果判断loc变量的值为NULLraise null_exception; --引发NULL异常,程序转入EXCEPTION部分end if;exceptionwhen null_exception then --当RAISE引发的异常是NULL_EXCEPTION时dbms_output.put_line('loc字段的值不许为null'); --输出异常提示信息rollback; --回滚插入的数据记录end;
学习永无止境,让我们共同进步!!
相关文章:
Oracle--PL/SQL编程
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除 PL/SQL(Procedural Language/SQL)是Oracle数据库中的一种过程化编程语言,构建于SQL之上,允许编写包含S…...
【愚公系列】《Python网络爬虫从入门到精通》063-项目实战电商数据侦探(主窗体的数据展示)
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
DAPP(去中心化应用程序)开发全解析:构建去中心化应用的流程
去中心化应用(DApp)凭借其透明性、抗审查性和用户数据主权,正重塑金融、游戏、社交等领域。本文基于2025年最新开发实践,系统梳理DApp从需求规划到部署运维的全流程,并融入经济模型设计、安全加固等核心要点࿰…...
Spark与Hadoop之间有什么样的对比和联系
一、什么是Spark Spark 是一个快速、通用且可扩展的大数据处理框架,最初由加州大学伯克利分校的AMPLab于2009年开发,并于2010年开源。它在2013年成为Apache软件基金会的顶级项目,是大数据领域的重要工具之一。 Spark 的优势在于其速度和灵活…...
spark和Hadoop之间的对比和联系
Spark 诞生主要是为了解决 Hadoop MapReduce 在迭代计算以及交互式数据处理时面临的性能瓶颈问题。 一,spark的框架 Hadoop MR 框架 从数据源获取数据,经过分析计算后,将结果输出到指定位置,核心是一次计算,不适合迭…...
LeetCode 第 262 题全解析:从 SQL 到 Swift 的数据分析实战
文章目录 摘要描述题解答案(SQL)Swift 题解代码分析代码示例(可运行 Demo)示例测试及结果时间复杂度分析空间复杂度分析总结未来展望 摘要 在实际业务中,打车平台要监控行程的取消率,及时识别服务质量的问…...
“融合Python与机器学习的多光谱遥感技术:数据处理、智能分类及跨领域应用”
随着遥感技术的快速发展,多光谱数据凭借其多波段信息获取能力,成为地质、农业及环境监测等领域的重要工具。相较于高光谱数据,Landsat、哨兵-2号等免费中分辨率卫星数据具有长时间序列、广覆盖的优势,而无人机平台的兴起进一步补充…...
JavaScript的JSON处理Map的弊端
直接使用 Map 会遇到的问题及解决方案 直接使用 Map 会导致数据丢失,因为 JSON.stringify 无法序列化 Map。以下是详细分析及解决方法: 问题复现 // 示例代码 const myMap new Map(); myMap.set(user1, { name: Alice }); myMap.set(user2, { name: B…...
python的深拷贝浅拷贝(copy /deepcopy )
先说结论: 浅拷贝: 浅拷贝对在第一层的操作都是新建,不改变原对象。 浅拷贝对于原拷贝对象中的嵌套的可变对象是引用,对原拷贝对象中的嵌套的不可变对象是新建。 对新建的对象操作不会影响原被拷贝对象。 对引用对象操作会影…...
新能源汽车充电桩:多元化运营模式助力低碳出行
摘 要:以新能源汽车民用充电桩为研究对象,在分析充电桩建设运营的政府推动模式、电网企业推动模式、汽车厂商推动模式等三种模式利弊的基础上,结合我国的实际情况,提出我国现阶段应实行汽车厂商与电网企业联盟建设充电桩的模式。建立一个考虑…...
Python 设计模式:享元模式
1. 什么是享元模式? 享元模式是一种结构型设计模式,旨在通过共享对象来减少内存使用和提高性能。它特别适用于需要大量相似对象的场景,通过共享相同的对象来避免重复创建,从而节省内存和提高效率。 享元模式的核心思想是将对象的…...
文献×汽车 | 基于 ANSYS 的多级抛物线板簧系统分析
板簧系统是用于减弱或吸收动态系统中发生的应力、应变、偏转和变形等破坏性因素的机械结构。板簧系统可能对外力产生不同的响应,具体取决于其几何结构和材料特性。板簧系统的计算机辅助分析对于高精度确定系统的变形特性和结构特性至关重要。 在这项工作中ÿ…...
Element UI、Element Plus 里的表单验证的required必填的属性不能动态响应?
一 问题背景 想要实现: 新增/修改对话框中(同一个),修改时“备注”字段非必填,新增时"备注"字段必填 结果发现直接写不生效-初始化一次性 edit: [{ required: true, message: "请输入备注", trigger: "blur" }…...
【架构】ANSI/IEEE 1471-2000标准深度解析:软件密集型系统架构描述推荐实践
引言 在软件工程领域,架构设计是确保系统成功的关键因素之一。随着软件系统日益复杂化,如何有效描述和沟通系统架构成为了一个亟待解决的问题。ANSI/IEEE 1471-2000(正式名称为"推荐软件密集型系统架构描述实践")应运而…...
深度学习中的“重参数化”总结
深度学习中的重参数化(Reparameterization)是一种数学技巧,主要用于解决模型训练过程中随机性操作(如采样)导致的梯度不可导问题。其核心思想是将随机变量的生成过程分解为确定性和随机性两部分,使得反向传…...
为TA开发人员介绍具有最新改进的Kinibi-610a
安全之安全(security)博客目录导读 目录 一、引言 二、密码学改进 三、可信应用(TA)的多线程支持 四、C 标准库支持 五、简化的支持与集成 六、参考资料 一、引言 Trustonic 推出的 Kinibi-610a 进行了多项底层优化,以实现更深度的系统集成,并更好地适应不断演进的…...
通信与推理的协同冲突与架构解耦路径
在大规模无人机集群中,AI决策系统依赖实时通信完成状态共享与策略传播,但通信带宽、延迟、信息一致性等问题正在成为系统性能的瓶颈。尤其是在山区、城市低空或信号遮蔽等通信不稳定区域,AI推理系统往往面临状态更新延迟,难以及时…...
《AI大模型应知应会100篇》第32篇:大模型与医疗健康:辅助诊断的可能性与风险
第32篇:大模型与医疗健康:辅助诊断的可能性与风险 摘要 当AI开始读懂CT影像中的细微阴影,当算法能从百万份病历中发现诊断规律,医疗健康领域正经历着一场静默的革命。本文通过技术解构与案例分析,揭示大模型如何重塑临…...
c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第七式】程序的编译
c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第七式】程序的编译 【心法】 【第零章】c语言概述 【第一章】分支与循环语句 【第二章】函数 【第三章】数组 【第四章】操作符 【第五章】指针 【第六章】结构体 【第七章】const与c语言中一些错误代码 【禁忌秘术】 【第一式】…...
[创业之路-377]:企业法务 - 有限责任公司与股份有限公司的优缺点对比
有限责任公司(简称“有限公司”)与股份有限公司(简称“股份公司”)是我国《公司法》规定的两种主要公司形式,二者在设立条件、治理结构、股东权利义务等方面存在显著差异。以下从核心特征、设立条件、治理结构、股东权…...
PowerBi中REMOVEFILTERS怎么使用?
在 Power BI 的 DAX 中,REMOVEFILTERS() 是一个非常重要的函数,常用于取消某个字段或表的筛选上下文(Filter Context),从而让你的计算不受切片器(Slicer)、筛选器或视觉对象的限制。 ✅ 一、REM…...
stat判断路径
int stat(const char *pathname, struct stat *buf); pathname:用于指定一个需要查看属性的文件路径。 buf:struct stat 类型指针,用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 struct stat 变量的指针࿰…...
智能指针之设计模式4
前面的文章介绍了使用工厂模式来封装智能指针对象的创建过程,下面介绍一下工厂类 enable_shared_from_this的实现方案。 4、模板方法模式 在前面的文章分析过,enable_shared_from_this<T>类是一个工厂基类,提供的工厂方法是shared_f…...
Linux信号的产生
Linux系列 文章目录 Linux系列一、信号的产生1.1 异常1.2 alarm()系统调用 二 、信号的默认行为 一、信号的产生 上篇文章我们已经介绍了信号的三种产生方式,这部分是对上篇文章的补充 1.1 异常 在编写程序时,我们的程序经常会出现如:除零…...
FPGA设计 时空变换
1、时空变换基本概念 1.1、时空概念简介 时钟速度决定完成任务需要的时间,规模的大小决定完成任务所需要的空间(资源),因此速度和规模就是FPGA中时间和空间的体现。 如果要提高FPGA的时钟,每个clk内组合逻辑所能做的事…...
客户端本地搭建
connect函数 主要用于客户端套接字向服务器发起连接请求。 头文件 #include <sys/socket.h> #include <arpa/inet.h> 函数原型 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数解释 sockfd:客户端文件描述符。 addr…...
广东食品销售初级考试主要考什么
广东省食品销售初级考试主要考察从业人员对食品安全法律法规、行业规范及基础操作技能的掌握程度,内容涵盖以下几个方面: 1. 食品安全法律法规 考试重点包括《食品安全法》《广东省食品安全条例》等核心法规,要求考生熟悉食品经营许可、从业…...
[盈达科技】GEO(生成式引擎优化)实战指南:从认知重构、技术落地到内容突围的三维战略
GEO(生成式引擎优化)实战指南:从认知重构、技术落地到内容突围的三维战略 引言:AI搜索重构规则,GEO成为企业新护城河 在生成式AI主导的搜索时代,传统SEO的“关键词游戏”已失效。Google数据显示࿰…...
Linux ACL访问控制权限解析:超越传统权限的精细化管理
Linux ACL权限管理示意图 标准输出:Linux文件权限结构(支持ACL) ├── 传统权限 │ ├── 所有者(user): rwx │ ├── 所属组(group): r-x │ └── 其他用户(other): r-- │ └── ACL扩展权限├── 用户条目│ ├── user…...
全面介绍AVFilter 的添加和使用
author: hjjdebug date: 2025年 04月 22日 星期二 13:48:19 CST description: 全面介绍AVFilter 的添加和使用 文章目录 1.两个重要的编码思想1. 写代码不再是我们调用别人,而是别人调用我们!2. 面向对象的编程方法. 2. AVFilter 开发流程2.1 编写AVFilter 文件2.1.…...
复刻低成本机械臂 SO-ARM100 3D 打印篇
视频讲解: 复刻低成本机械臂 SO-ARM100 3D 打印篇 清理了下许久不用的3D打印机,挤出机也裂了,更换了喷嘴和挤出机夹具,终于恢复了正常工作的状态,接下来还是要用起来,不然吃灰生锈了,于是乎想起…...
基于微信小程序的走失儿童帮助系统-项目分享
基于微信小程序的走失儿童帮助系统-项目分享 项目介绍项目摘要管理员功能图用户功能图系统功能图项目预览首页走失儿童个人中心走失儿童管理 最后 项目介绍 使用者:管理员、用户 开发技术:MySQLJavaSpringBootVue 项目摘要 本系统采用微信小程序进行开…...
C++23 中 static_assert 和 if constexpr 的窄化布尔转换
文章目录 背景与动机C23 的改进限制与例外总结 C23 引入了一项重要的语言特性变更,即在 static_assert 和 if constexpr 中允许窄化按语境转换为 bool。这一特性由 Andrzej Krzemieński 提出的 P1401R5 论文推动,旨在使编译器的行为与标准保持一致&a…...
服务网格在DevOps中的落地:如何让微服务更智能、更稳定?
服务网格在DevOps中的落地:如何让微服务更智能、更稳定? 近年来,DevOps在企业IT架构中变得至关重要,而微服务架构的广泛应用更是加速了这一趋势。然而,随着微服务数量不断增长,我们发现自己掉入了一个运维“泥潭”: 服务之间的流量调控变得复杂可观测性不足,出现问题时…...
el-table表格既出现横向滚动条,又出现纵向滚动条?
横向滚动条 自然出现? 当表格所有列的宽度总和超过表格容器宽度时,el-table会默认出现横向滚动条。 比如,给每个<el-table-column>设置固定宽度,且他们相加超过了<el-table>宽度 就会触发 强制出现? 设…...
STL常用算法——C++
1.概述 2.常用遍历算法 1.简介 2.for_each 方式一:传入普通函数(printf1) #include<stdio.h> using namespace std; #include<string> #include<vector> #include<functional> #include<algorithm> #include…...
基于国产 FPGA+ 龙芯2K1000处理器+翼辉国产操作系统继电保护装置测试装备解决方案
0 引言 近年来,我国自主可控芯片在国家政策和政 府的支持下发展迅速,并在电力、军工、机械、 通信、电子、医疗等领域掀起了国产化替代之 风,但在芯片自主可控和国产化替代方面还有明 显的不足之处。 2022年我国集成电路进口量多 达 5 3…...
1.3 本书结构概览:从理论基础到实践案例的系统阐述
本书采用由浅入深、理论联系实践的结构设计,旨在为读者提供一个关于大模型与智能代理(Agent)技术的全面认知框架与实施路径。全书共分为十章,系统性地覆盖了从技术基础到企业落地的完整知识链条,现概述如下: 首先,第一…...
【FPGA开发】Vivado开发中的LUTRAM占用LUT资源吗
LUTRAM在Vivado资源报告中的解释 LUTRAM的本质与实现原理: LUTRAM不是一种独立的物理资源,而是LUT(Look-Up Table)的一种特殊使用方式。在Xilinx FPGA架构中,部分LUT单元可以被配置为小型分布式RAM(也称为…...
【动手学强化学习】番外8-IPPO应用框架学习与复现
文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明(1)MAPPO 与 IPPO 算法的区别在于什么地方?(2)IPPO 算法应用框架主要参考来源 2.2 应用步骤2.2.1 搭建基础环境2.2.2 IPPO 算法实例复现&am…...
C++ 的 输入输出流(I/O Streams)
什么是输入输出流 C 的输入输出操作是通过 流(stream) 机制实现的。 流——就是数据的流动通道,比如: 输入流:从设备(如键盘、文件)读取数据 → 程序 输出流:程序将数据写入设备&…...
Java 安全:如何防止 SQL 注入与 XSS 攻击?
Java 安全:如何防止 SQL 注入与 XSS 攻击? 在 Java 开发领域,安全问题至关重要,而 SQL 注入和 XSS 攻击是两种常见的安全威胁。本文将深入探讨如何有效防止这两种攻击,通过详细代码实例为您呈现解决方案。 一、SQL 注…...
leetcode day36 01背包问题 494
494 目标和 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - ,然后串联起所有整数,可以构造一个 表达式 : 例如,nums [2, 1] ,可以在 2 之前添加 ,在 1 之前添加 - &…...
31Calico网络插件的简单使用
环境准备: 1、删除Flannel 2、集群所有node节点拉取所需镜像(具体版本可以依据calico.yaml文件中): docker pull calico/cni:v3.25.0 docker pull calico/node:v3.25.0 docker pull calico/kube-controllers:v3.25.0一、安装Cali…...
进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程
进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程 (图片来源: ThisIsEngineering RAEng on Pexels) 在前几篇中,我们深入研究了经典的时间序列统计模型,如 ETS 和强大的 SARIMA 家族。它们在理论上成熟且应用广泛,但有…...
实用生活c语言脚本
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> // 清理临时文件目录 void clean_temp_directory() { const char* temp_dir "/tmp"; // 可自定义需要清理的目录 char command[1024]; …...
从零开始构建微博爬虫与数据分析系统
从零开始构建微博爬虫与数据分析系统 引言 社交媒体平台蕴含着海量的信息和数据,通过对这些数据的收集和分析,我们可以挖掘出有价值的见解。本文将详细介绍如何构建一个完整的微博爬虫和数据分析系统,从数据爬取、清洗、到多维度分析与可视…...
417. 太平洋大西洋水流问题
题目 有一个 m n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights…...
chili3d调试笔记8 打印零件属性
无效, 返回的是节点不是坐标啥的, 找他的属性 把document和selectednote(空集)传给handleshowproperty方法 怎么获得selectnotes和selectnotes的property值 有selectnotes运行这段就行了 明天再搞...
uniapp Vue2升级到Vue3,并发布到微信小程序的快捷方法
目录 前言:升级项目的两种方式步骤一、新建项目 【选择-默认模版】二、修改-pages.json三、补充-缺少的文件四、修改-Main.js按照 [官方文档-vue2升级vue3迁移指南](https://uniapp.dcloud.net.cn/tutorial/migration-to-vue3.html) 修改 五、升级-uni-ui扩展组件的…...