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

PL/SQL入门到实践

一、什么是PL/SQL

  1. PL/SQL是Procedural Language/Structured Query Language的缩写。
  2. PL/SQL是一种过程化编程语言,运行于服务器端的编程语言。
  3. PL/SQL是对SQL语言的扩展。PL/SQL结合了SQL语句和过程性编程语言的特性,可以用于编写存储过程、触发器、函数等数据库对象。它现在是Oracle数据库系统的核心语言,Oracle的许多部件都是由PL/SQL编写的。

二、PL/SQL特点

  1. 扩展性:PL/SQL是Oracle对SQL的扩展,增加了过程处理语句(控制结构),使SQL的功能更加强大。
  2. 过程化:PL/SQL不仅支持SQL的数据查询、数据操纵和数据定义功能,还具有强大的过程化功能。
  3. 块结构(模块化):PL/SQL是一种块结构的语言,组成PL/SQL程序的单元是逻辑块,每个块都可以划分为三个部分:声明部分、执行部分和异常处理部分。
  4. 可重用性:PL/SQL代码可以定义存储过程和函数,在客户端需要的时候可以调用,实现了模块的可重用性。
  5. 可移植性:PL/SQL代码可以使用任何ASCII文本编辑器编写,对任何Oracle能够运行的操作系统都非常便利。
  6. 改善性能(降低网络拥挤):PL/SQL是以整个语句块发给服务器,降低了网络拥挤,从而提高性能。因为SQL语句是以语句为单位进行发送的,在网络环境下会占用大量的服务器时间,可能导致网络拥挤。

三、PL/SQL的结构

PL/SQL 块概念

块(block)是 PL/SQL的基本程序单元,编写pl/sql程序实际上就是编写pl/sql块,要完成相对简单的应用功能,可能只需要编写一个pl/sql块,要完实现复杂的功能,可能需要再一个pl/sql块中嵌套其他的pl/sql块。

一个 PL/SQL 块通常由三个部分组成:声明部分、执行部分和异常处理部分。

PL/SQL 块的基本结构

DECLARE  -- 声明变量、常量、类型、游标等  
BEGIN  -- 执行 SQL 语句和 PL/SQL 语句  
EXCEPTION  -- 处理异常  
END;  

DECLARE 部分(可选)

在这一部分,你可以声明 PL/SQL 变量、常量、类型、游标、子程序等。这些声明的对象在 PL/SQL 块的其余部分(BEGIN...END 之间)是可见的。

示例:

DECLARE  v_name VARCHAR2(50);  
BEGIN  -- 使用变量...  
END;  

BEGIN 部分(必需)

这是 PL/SQL 块的主要部分,包含要执行的 SQL 语句和 PL/SQL 语句。你可以在这里对前面声明的变量进行赋值、执行查询、控制流语句(如 IF、LOOP、CASE 等)等。

DECLARE  v_name VARCHAR2(50);  
BEGIN  v_name := 'John Doe';  DBMS_OUTPUT.PUT_LINE('Hello, ' || v_name);  
END;  

EXCEPTION 部分(可选)

如果在 BEGIN...END 部分的代码执行过程中出现了异常(如除零错误、无效的 SQL 语句等),那么代码会跳转到 EXCEPTION 部分进行处理。在 EXCEPTION 部分,你可以捕获异常并编写相应的处理代码。

DECLARE  v_divisor NUMBER;  
BEGIN  v_divisor := 0;  DBMS_OUTPUT.PUT_LINE(10 / v_divisor); -- 这会引发一个异常  
EXCEPTION  WHEN ZERO_DIVIDE THEN  DBMS_OUTPUT.PUT_LINE('除数不能为零!');  
END;  

PL/SQL 块类型

  • 匿名块:没有名称的 PL/SQL 块,通常在 SQL*Plus 或其他工具中直接执行。
  • 子程序:包括存储过程和函数,它们有名称,可以在 PL/SQL 程序中调用。
  • 触发器:与数据库表事件关联的 PL/SQL 块,当满足特定条件时自动执行。
  • :将相关的 PL/SQL 类型、变量、常量、子程序等组合到一起的数据库对象。

四、PL/SQL中的标识符

标识符定义规范

pl/sql程序设计中的标识符定义与sql的标识符定义的要求相同。

  • 标识符名不能超过30字符
  • 第一个字符必须为字母
  • 不分大小写
  • 不能是sql保留字

变量推荐命名方法

五、PL/SQL块的数据类型

基本数据类型

基本数据类型使用

-- 声明变量
DECLAREv_name varchar2(100);v_id varchar2(100);v_number NUMBER :=1;--给变量赋值
BEGIN --主体部分SELECT name,loginid INTO v_name,v_id FROM TAUSER WHERE userid = '1';dbms_output.put_line(v_name||','||v_id||','||v_number);
END;

参照表的列类型

使用方式:表名.字段名%type

-- 声明变量
DECLAREv_name tauser.name%type;v_id tauser.loginid%type;v_number NUMBER :=1;--给变量赋值
BEGIN --主体部分SELECT name,loginid INTO v_name,v_id FROM TAUSER WHERE userid = '1';dbms_output.put_line(v_name||','||v_id||','||v_number);
END;

 记录类型

格式:

type 类型名 is record(变量名1,变量名2,
......);
-- 声明变量
DECLARETYPE user_record IS RECORD (v_name tauser.name%TYPE,v_id tauser.loginid%type);u user_record;
BEGIN --主体部分SELECT name,loginid INTO u FROM TAUSER WHERE userid = '1';dbms_output.put_line(u.v_name||','||u.v_id);
END;

参照记录类型

 格式:表名%rowtype

-- 声明变量
DECLAREu tauser%rowtype;
BEGIN --主体部分SELECT * INTO u FROM TAUSER WHERE userid = '1';dbms_output.put_line(u.name||','||u.loginid);
END;

注意:

在PL/SQL中,%ROWTYPE属性定义了一个记录类型,该记录类型的结构与指定的表或视图的整行结构相匹配。因此,如果你使用%ROWTYPE,那么该记录类型将包含表或视图中的所有列。

以下为错误用法:

六、流程控制语句

if语句

语法格式:

IF condition THEN  -- 如果condition为真,则执行这里的代码  [statements]  
[ELSIF condition THEN  -- 如果需要额外的条件检查,可以使用ELSIF(可选)  -- 如果前面的条件都为假,但此条件为真,则执行这里的代码  [elsif_statements]  
...] 
ELSE  -- 如果condition为假,并且提供了ELSE部分,则执行这里的代码  [else_statements]  END IF;

 示例:

DECLARE  v_number NUMBER := 10;  
BEGIN  IF v_number > 0 THEN  DBMS_OUTPUT.PUT_LINE('The number is positive.');  ELSIF v_number = 0 THEN  DBMS_OUTPUT.PUT_LINE('The number is zero.');  ELSE  DBMS_OUTPUT.PUT_LINE('The number is negative.');  END IF;  
END;  

 

循环语句

在PL/SQL中,有几种不同类型的循环可以使用,包括FOR循环、WHILE循环和LOOP(无限循环,通常与EXIT WHEN条件一起使用)。以下是这些循环的使用方式的示例:

FOR 循环

FOR循环通常用于遍历一个集合,如数组或游标。对于数字范围,可以使用FOR ... IN ... LOOP结构。

BEGIN  FOR i IN 1..10 LOOP  DBMS_OUTPUT.PUT_LINE('Value of i: ' || i);  END LOOP;  
END;  

在PL/SQL中,1..10 是一个范围(range)的表示法,它定义了一个从1开始到10结束(包括1和10)的整数序列。这种表示法经常用于FOR循环中,以便迭代一个指定的数字范围 

WHILE 循环

WHILE循环在条件为真时重复执行代码块。

DECLARE  v_counter NUMBER := 1;  
BEGIN  WHILE v_counter <= 10 LOOP  DBMS_OUTPUT.PUT_LINE('Value of v_counter: ' || v_counter);  v_counter := v_counter + 1;  END LOOP;  
END;  

 LOOP 循环(与 EXIT WHEN 一起使用)

LOOP语句创建了一个无限循环,直到遇到EXIT WHEN条件。

DECLARE  v_counter NUMBER := 1;  
BEGIN  LOOP  DBMS_OUTPUT.PUT_LINE('Value of v_counter: ' || v_counter);  v_counter := v_counter + 1;  EXIT WHEN v_counter > 10;  END LOOP;  
END;  
/

在PL/SQL中,EXIT语句用于立即终止当前循环(LOOPFORWHILE循环)的执行,并将控制权转移到循环之后的代码。当与WHEN条件结合使用时(即EXIT WHEN),它允许在特定条件满足时退出循环。 

CURSOR FOR LOOP

当使用游标时,可以使用FOR ... IN ... LOOP结构来遍历游标的结果集。

DECLARE  CURSOR c_employees IS  SELECT employee_id, first_name, last_name FROM employees;  
BEGIN  FOR r_employee IN c_employees LOOP  DBMS_OUTPUT.PUT_LINE('Employee ID: ' || r_employee.employee_id ||   ', Name: ' || r_employee.first_name || ' ' || r_employee.last_name);  END LOOP;  
END;  
/

 在这个示例中,我们定义了一个名为c_employees的游标来从employees表中检索数据,并使用FOR ... IN ... LOOP结构来遍历游标的结果集。在循环体中,我们可以访问游标中每一行的列值。

 七、游标

游标的概念

游标是指向查询结果的指针,指针指向哪条记录,提取的就是哪条记录的数据。

游标的使用流程

  1. 声明游标:定义游标的名称、声明光标变量以及定义光标属性等。
  2. 打开游标:执行查询并将结果存储在游标变量中。
  3. 读取游标:通过FETCH语句从游标中提取数据,并逐行处理。
  4. 关闭游标:使用CLOSE语句关闭游标,释放资源。

游标的属性

游标的属性在PL/SQL中提供了关于游标当前状态和数据检索的详细信息。无论是显式游标还是隐式游标,它们都具有一些共同的属性。以下是游标的属性及其解释:

  1. %FOUND
    • 类型:布尔型(Boolean)
    • 描述:此属性返回一个布尔类型的值,用于指示游标的指针是否指向有效的数据行。如果游标指向的数据不为空(即存在有效数据),则返回TRUE;否则返回FALSE
  2. %NOTFOUND
    • 类型:布尔型(Boolean)
    • 描述:与%FOUND相反,此属性在游标指向的数据为空(即没有有效数据)时返回TRUE。当游标已经遍历完所有数据或尚未开始检索数据时,此属性通常也返回TRUE
  3. %ROWCOUNT
    • 类型:数值型(Numeric)
    • 描述:此属性返回一个数值,表示游标指向的缓冲区(或结果集)中的数据条数。它通常用于跟踪游标已经检索了多少行数据,或者在执行DML操作后确定受影响的行数。
  4. %ISOPEN
    • 类型:布尔型(Boolean)
    • 描述:此属性返回一个布尔类型的值,用于判断当前游标是否打开。如果游标处于打开状态,则返回TRUE;否则返回FALSE。请注意,隐式游标的%ISOPEN属性始终为FALSE,因为隐式游标由Oracle数据库自动管理。

这些属性可以帮助开发人员编写更健壮和可维护的PL/SQL代码,因为它们提供了关于游标状态和数据检索的详细信息。例如,开发人员可以使用%FOUND%NOTFOUND属性来控制循环的迭代,或者使用%ROWCOUNT属性来验证DML操作的结果。

需要注意的是,不同的游标类型(如静态游标、动态游标、隐式游标等)可能在某些方面有所不同,但它们通常都支持上述属性。此外,在使用游标时,还需要注意游标的打开、读取和关闭等操作,以确保正确地处理数据并释放资源。

游标的使用

基本使用

DECLARE  v_name tauser.name%TYPE;v_id tauser.loginid%TYPE;CURSOR tauser_cursor IS SELECT name,loginid FROM TAUSER t ;
BEGIN  OPEN tauser_cursor;FETCH tauser_cursor INTO v_name,v_id;WHILE tauser_cursor%FOUND LOOPdbms_output.put_line(v_name||','||v_id);FETCH tauser_cursor INTO v_name,v_id; --让游标指向下一行end LOOP;
END;  

注意:

错误用法:

 参数化游标

DECLARE  v_name tauser.name%TYPE;v_id tauser.loginid%TYPE;CURSOR tauser_cursor(u_id varchar2) IS SELECT name FROM TAUSER t WHERE userid = u_id ;
BEGIN  OPEN tauser_cursor('1');  -- 传入实际参数 这里传入userid为1FETCH tauser_cursor INTO v_name;WHILE tauser_cursor%FOUND LOOPdbms_output.put_line(v_name);FETCH tauser_cursor INTO v_name;end LOOP;
END;  

游标For循环

DECLARE  CURSOR tauser_cursor IS SELECT name,loginid FROM TAUSER t  ;
BEGIN  FOR u IN tauser_cursor LOOPdbms_output.put_line(u.name);end LOOP;END;  

 带参数的游标For循环

DECLARE  CURSOR tauser_cursor(u_id varchar2) IS SELECT name,loginid FROM TAUSER t WHERE userid=u_id ;
BEGIN  FOR u IN tauser_cursor('1') LOOPdbms_output.put_line(u.name);end LOOP;END;  

 隐式游标

在 PL/SQL 中,隐式游标(Implicit Cursor)是 Oracle 数据库自动为你管理的一种游标,主要用于处理那些不需要显式声明和控制的 SQL 语句。最常见的隐式游标是当你执行 DML(数据操纵语言)语句(如 INSERT、UPDATE、DELETE)和单行 SELECT INTO 语句时,Oracle 会自动为你创建一个隐式游标。

隐式游标的主要特点是:

  1. 自动管理:你不需要显式地声明、打开、获取数据和关闭隐式游标。Oracle 数据库会自动为你完成这些操作。
  2. 属性:隐式游标有一些属性,如 %NOTFOUND%FOUND%ROWCOUNT 和 %ISOPEN。但由于隐式游标是自动管理的,%ISOPEN 总是返回 FALSE,因为它在查询完成后会自动关闭。

示例:

假设你有一个名为 employees 的表,并且你想删除某个员工(假设其 ID 为 1001):

BEGIN  DELETE FROM employees WHERE employee_id = 1001;  IF SQL%NOTFOUND THEN  DBMS_OUTPUT.PUT_LINE('没有找到员工 ID 1001');  ELSE  DBMS_OUTPUT.PUT_LINE('员工 ID 1001 已被删除');  END IF;  
END;  

在上面的示例中,SQL%NOTFOUND 是一个隐式游标的属性,用于检查 DELETE 语句是否影响了任何行。如果没有找到员工 ID 1001,则输出“没有找到员工 ID 1001”;否则输出“员工 ID 1001 已被删除”。注意,这里我们使用了 SQL%NOTFOUND 而不是 employees_cursor%NOTFOUND,因为这是一个隐式游标操作,没有显式声明的游标。

八、异常

在PL/SQL中,异常(Exception)是用于处理运行时错误的一种机制。当PL/SQL块中的代码遇到错误时,它会抛出一个异常。如果没有适当的异常处理代码,程序将终止并返回一个错误消息给用户。但是,通过编写异常处理部分(EXCEPTION section),你可以捕获异常并采取适当的措施,如记录错误信息、回滚事务或提供友好的错误消息给用户。

在PL/SQL中,有两种类型的异常:

  1. 预定义异常:Oracle已经为常见的错误情况定义了异常。例如,NO_DATA_FOUND(当SELECT INTO语句没有返回任何行时)和TOO_MANY_ROWS(当SELECT INTO语句返回多行时)。预定义异常不需要显式声明,但你可以在EXCEPTION部分中捕获它们。

  2. 用户定义异常:你可以使用DECLARE部分中的EXCEPTION关键字来声明你自己的异常。这允许你定义和处理特定的错误情况。

示例:使用预定义异常

DECLARE  v_employee_name VARCHAR2(50);  
BEGIN  SELECT first_name INTO v_employee_name  FROM employees  WHERE employee_id = 1001;  -- 如果这里employee_id为1001的员工不存在,将会抛出NO_DATA_FOUND异常  DBMS_OUTPUT.PUT_LINE('Employee name: ' || v_employee_name);  
EXCEPTION  WHEN NO_DATA_FOUND THEN  DBMS_OUTPUT.PUT_LINE('No employee found with ID 1001');  WHEN OTHERS THEN  DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);  
END;  

示例:使用用户定义异常

DECLARE  v_employee_salary NUMBER;  salary_too_high EXCEPTION; -- 声明用户定义异常  
BEGIN  SELECT salary INTO v_employee_salary  FROM employees  WHERE employee_id = 1001;  IF v_employee_salary > 100000 THEN  RAISE salary_too_high; -- 触发用户定义异常  END IF;  -- 其他代码...  
EXCEPTION  WHEN salary_too_high THEN  DBMS_OUTPUT.PUT_LINE('Salary is too high for this employee');  WHEN OTHERS THEN  DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);  
END;  

九、函数和过程

函数和过程介绍

1.Oracle提供可以把PL/SQL程序存储在数据库中,并可以再任何地方来运行它,这样就叫存储过程或函数。

2.过程和函数统称PL/SQL子程序,它们是被命名的PL/SQL块,均存储在数据库中,并通过输入、输出参数或者输入/输出参数预期调用者交换信息。

3.过程和函数的唯一区别是函数总向调用者返回数据(函数必须有返回值),而过程则不返回数据(过程没有返回值)。

函数的创建

创建语法:

CREATE OR REPLACE FUNCTION function_name (  parameter1 datatype [DEFAULT value],  parameter2 datatype [DEFAULT value],  ...  
) RETURN return_datatype  
IS  -- 声明变量  variable_declaration;  
BEGIN  -- 函数体  -- 执行逻辑,返回结果  RETURN result;  
EXCEPTION  -- 异常处理  WHEN exception_name THEN  -- 处理异常的代码  ...  
END;  

其中:

  • function_name:函数的名称。
  • parameter1, parameter2, ...:函数的参数列表。每个参数都有一个名称和数据类型,可以有一个默认值。
  • return_datatype:函数返回值的数据类型。
  • variable_declaration:在 IS 和 BEGIN 之间,你可以声明函数体内将使用的变量。
  • RETURN result;:函数体中的这一行表示函数将返回的值。
  • EXCEPTION 部分是可选的,用于处理在函数执行过程中可能发生的异常。

函数的参数类型

在 PL/SQL 中,函数(Function)允许你封装一段逻辑代码,并可以传递参数和返回结果。PL/SQL 是 Oracle 数据库中的过程化 SQL 语言扩展,它允许你在数据库中创建存储过程、函数、触发器等。

函数的参数可以有不同的模式(Mode)和数据类型。在 PL/SQL 中,函数的参数主要有以下几种模式:

  1. IN 模式:这是默认的参数模式,用于向函数传递值。在函数体内,这些参数是只读的,不能被修改。
  2. OUT 模式:这种参数用于从函数返回多个值。在调用函数之前,OUT 参数不需要被赋值。在函数体内,OUT 参数可以被赋予新的值,并在函数执行完毕后返回给调用者。
  3. IN OUT 模式:这种参数既可以接收传入的值,也可以返回修改后的值。

下面是一个简单的 PL/SQL 函数示例,该函数接受一个 IN 模式的 NUMBER 类型参数,并返回它的平方:

CREATE OR REPLACE FUNCTION square_number(p_number IN NUMBER)  
RETURN NUMBER IS  v_result NUMBER;  
BEGIN  v_result := p_number * p_number;  RETURN v_result;  
END square_number;  

注意:无论是返回值类型还是参数类型,都只需要写数据类型,不需要写括号。

例如:varchar2,number是正确的,varchar2(50),number(7,2)这种写法是错误的。

函数的调用

一旦你创建了函数,你就可以在 SQL 语句或 PL/SQL 块中调用它。

示例:

SELECT square_number(5) FROM DUAL;

过程的创建

在PL/SQL中,存储过程(Stored Procedure)是存储在数据库中的一组为了完成特定功能的SQL语句集。存储过程可以被视为一个命名的PL/SQL块,它可以从应用程序中被调用,并且可以接受参数和返回状态值。

以下是PL/SQL中存储过程的基本创建语法:

CREATE OR REPLACE PROCEDURE procedure_name   [ (parameter_name [ IN | OUT | IN OUT ] data_type [, ...] ) ]   
IS   [declaration_section]   
BEGIN   executable_section   
[EXCEPTION   exception_handling_section]   
END [procedure_name];
  • CREATE OR REPLACE PROCEDURE: 用于创建或替换一个已存在的存储过程。
  • procedure_name: 存储过程的名称。
  • parameter_name: 参数的名称。
  • IN | OUT | IN OUT: 参数的模式。IN是默认值,表示参数是输入参数;OUT表示参数是输出参数,用于从存储过程返回数据;IN OUT表示参数既可以输入也可以输出。
  • data_type: 参数的数据类型。
  • declaration_section: 可选部分,用于声明变量、常量、游标等。
  • executable_section: 存储过程的主体部分,包含要执行的PL/SQL语句和逻辑。
  • exception_handling_section: 可选部分,用于处理在executable_section中可能发生的异常。

下面是一个简单的存储过程示例,它接受一个输入参数并插入到一张表中:

CREATE OR REPLACE PROCEDURE insert_into_employees (p_emp_id IN NUMBER, p_emp_name IN VARCHAR2)   
IS   
BEGIN   INSERT INTO employees (emp_id, emp_name) VALUES (p_emp_id, p_emp_name);   COMMIT;   
EXCEPTION   WHEN OTHERS THEN   ROLLBACK;   RAISE_APPLICATION_ERROR(-20001, 'An error occurred: ' || SQLERRM);   
END insert_into_employees;  

在这个示例中,存储过程insert_into_employees接受两个输入参数p_emp_idp_emp_name,并将它们插入到employees表中。如果在插入过程中发生任何错误,它会回滚事务并抛出一个自定义的错误。

过程的调用

要调用存储过程,你可以使用EXECUTE语句或者匿名PL/SQL块:

EXECUTE insert_into_employees(100, 'John Doe');
BEGIN  insert_into_employees(100, 'John Doe');  
END;  

函数和存储过程示例

从Oracle自定义函数和存储过程案例学习PL/SQL的使用-CSDN博客

十、包

在 PL/SQL 中,包(Package)是一个数据库对象,它允许你将相关的 PL/SQL 类型、变量、常量、子程序、游标等组合成一个逻辑单元。包的主要目的是封装和组织代码,提高代码的可读性、可维护性和重用性。

一个包由两部分组成:包头(Package Specification)和包体(Package Body)。

包头(Package Specification)

  • 定义了包中公共类型、变量、常量、子程序、游标等的接口。
  • 其他数据库对象或用户只能看到和引用包头中定义的这些公共元素。
  • 包头中的声明决定了哪些元素是公共的(可以在包外部访问),哪些是私有的(只能在包内部访问)。

包体(Package Body)

  • 包含了包头中声明的公共元素和私有元素的实现。
  • 私有元素在包体外部是不可见的,但它们可以在包体内的任何子程序中引用。
  • 包体可以包含类型、变量、常量、子程序、游标等的定义和实现。

使用包的好处

  1. 封装性:包可以将相关的代码和数据封装在一起,隐藏实现细节,只暴露必要的接口。
  2. 重用性:通过封装公共的类型、子程序等,包提高了代码的重用性。
  3. 性能优化:由于包中的代码和数据在内存中只存储一次,因此可以提高访问速度和执行效率。
  4. 易于维护:通过组织和封装代码,包使得代码更易于阅读、理解和维护。
  5. 安全性:通过控制对包中元素的访问权限,可以提高数据的安全性。

示例

以下是一个简单的 PL/SQL 包示例:

包头(my_package_spec.pks):

CREATE OR REPLACE PACKAGE my_package AS  -- 公共类型  TYPE my_type IS TABLE OF VARCHAR2(50);  -- 公共常量  CONSTANT my_constant NUMBER := 100;  -- 公共子程序  FUNCTION get_data RETURN my_type;  PROCEDURE process_data(p_data IN my_type);  
END my_package;  

包体(my_package_body.pkb)

CREATE OR REPLACE PACKAGE BODY my_package AS  -- 私有变量  PRIVATE my_private_var NUMBER := 0;  -- 公共子程序实现  FUNCTION get_data RETURN my_type IS  v_data my_type := my_type('Data1', 'Data2', 'Data3');  BEGIN  RETURN v_data;  END get_data;  PROCEDURE process_data(p_data IN my_type) IS  BEGIN  -- 处理数据的逻辑  FOR i IN 1..p_data.COUNT LOOP  DBMS_OUTPUT.PUT_LINE(p_data(i));  END LOOP;  END process_data;  
END my_package;  

 在这个示例中,我们创建了一个名为 my_package 的包,它包含一个公共类型 my_type、一个公共常量 my_constant、一个公共函数 get_data 和一个公共过程 process_data。包体还包含一个私有变量 my_private_var

相关文章:

PL/SQL入门到实践

一、什么是PL/SQL PL/SQL是Procedural Language/Structured Query Language的缩写。PL/SQL是一种过程化编程语言&#xff0c;运行于服务器端的编程语言。PL/SQL是对SQL语言的扩展。PL/SQL结合了SQL语句和过程性编程语言的特性&#xff0c;可以用于编写存储过程、触发器、函数等…...

双非本 985 硕,我马上要入职上海AI实验室大模型算法岗

暑期实习基本结束了&#xff0c;校招即将开启。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解惑答疑&…...

C盘清理和管理

本篇是C盘一些常用的管理方法&#xff0c;以及定期清理C盘的方法&#xff0c;大部分情况下都能避免C盘爆红。 C盘清理和管理 C盘存储管理查看存储情况清理存储存储感知清理临时文件清理不需要的 迁移存储 磁盘清理桌面存储管理应用存储管理浏览器微信 工具清理 C盘存储管理 查…...

晚上睡觉要不要关路由器?一语中的

前言 前几天小白去了一个朋友家&#xff0c;有朋友说&#xff1a;路由器不关机的话会影响睡眠吗&#xff1f; 这个影响睡眠嘛&#xff0c;确实是会的。毕竟一时冲浪一时爽&#xff0c;一直冲浪一直爽……刷剧刷抖音刷到根本停不下来&#xff0c;肯定影响睡眠。 所以晚上睡觉要…...

ardupilot开发 --- 坐标变换 篇

Good Morning, and in case I dont see you, good afternoon, good evening, and good night! 0. 一些概念1. 坐标系的旋转1.1 轴角法1.2 四元素1.3 基于欧拉角的旋转矩阵1.3.1 单轴旋转矩阵1.3.2 多轴旋转矩阵1.3.3 其他 2. 齐次变换矩阵3. visp实践 0. 一些概念 相关概念&am…...

git clone 别人项目后正确的修改和同步操作

简介 git clone主要是克隆别人的开源项目。但更高端的操作是实现本地修改的同时&#xff0c;能同步别人的在线修改&#xff0c;并且不相互干扰&#xff1a; 克隆原始项目&#xff1a;从远程仓库克隆项目到本地。添加上游仓库&#xff1a;将原始项目的远程仓库添加为上游仓库。…...

JAVA连接FastGPT实现流式请求SSE效果

FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排&#xff0c;从而实现复杂的问答场景&#xff01; 一、先看效果 真正实流式请求&#xff0c;SSE效果&#xff0c;SSE解释&am…...

二分查找1

1. 二分查找&#xff08;704&#xff09; 题目描述&#xff1a; 算法原理&#xff1a; 暴力解法就是遍历数组来找到相应的元素&#xff0c;使用二分查找的解法就是每次在数组中选定一个元素来将数组划分为两部分&#xff0c;然后因为数组有序&#xff0c;所以通过大小关系舍弃…...

什么美业门店管理系统好用?2024美业收银系统软件排名分享

美业SAAS系统在美容、美发、美甲等行业中十分重要&#xff0c;这种系统为美业提供了一种数字化解决方案&#xff0c;帮助企业更高效地管理业务和客户关系。 美业门店管理系统通常提供预约管理、客户管理、库存管理、报表生成等一系列功能&#xff0c;以满足美容院、美发沙龙等…...

【文件上传】

文件上传漏洞 FileUpload 0x01 定义 服务端未对客户端上传文件进行严格的 验证和过滤造成可上传任意文件情况&#xff1b;0x02 攻击满足条件&#xff1a; 1. 上传文件能够被Web容器解释执行   2. 找到文件位置   3.上传文件未被改变内容。&#xff08;躲避安全检查&#…...

Golang 单引号、双引号和反引号的概念、用法以及区别

在 Golang&#xff08;Go 语言&#xff09;中&#xff0c;单引号 ()、双引号 (") 和反引号 () 用于不同类型的字符串和字符表示。以下是它们的概念、用法和区别&#xff1a; 1. 单引号 () 概念 单引号用于表示 字符&#xff08;rune 类型&#xff09;。一个字符表示一个…...

linux和mysql基础指令

Linux中nano和vim读可以打开记事文件。 ifdown ens33 ifup ens33 关闭&#xff0c;开启网络 rm -r lesson1 gcc -o code1 code1.c 编译c语言代码 ./code1 执行c语言代码 rm -r dir 删除文件夹 mysql> show databases-> ^C mysql> show databases; -------…...

JDK 为什么需要配置环境变量

前言 首先&#xff0c;我们要知道 Java 程序的执行过程。首先将 xxx.java 文件&#xff08;使用 javac 编译指令&#xff09;编译成 xxx.class 文件&#xff08;字节码文件&#xff09;&#xff0c;再将字节码文件&#xff08;使用 java 执行指令&#xff09;解释成电脑所能认识…...

ViewBinding的使用(因为kotlin-android-extensions插件的淘汰)

书籍&#xff1a; 《第一行代码 Android》第三版 开发环境&#xff1a; Android Studio Jellyfish | 2023.3.1 问题&#xff1a; 3.2.4在Activity中使用Toast章节中使用到了kotlin-android-extensions插件,但是该插件已经淘汰,根据网上了解,目前使用了新的技术VewBinding替…...

IOS Swift 从入门到精通:ios 连接数据库 安装 Firebase 和 Firestore

创建 Firebase 项目 导航到Firebase 控制台并创建一个新项目。为项目指定任意名称。 在这里插入图片描述 下一步,启用 Google Analytics,因为我们稍后会用到它来发送推送通知。 在这里插入图片描述 在下一个屏幕上,选择您的 Google Analytics 帐户(如果已创建)。如果没…...

QT4-QT5(6)-const char* QString 乱码转换

我简单粗暴的给出个结论&#xff1a; QString GBK编码正常&#xff0c;可以转UTF-8编码&#xff0c;但会有少量乱码。 const char* 编码就不要转编码&#xff0c;转哪个都是乱码。 UTF-8.cpp 下 1.QString GBK->UTF-8 2.const char * GBK->UTF-8 const char *…...

报错:RuntimeError_ cuDNN error_ CUDNN_STATUS_EXECUTION_FAILED

原因&#xff1a;pytorch与cuda版本不对 也有可能是内存空间不足&#xff0c;可以更改虚拟空间大小&#xff0c;参考&#xff1a;解决电脑内存不足问题&#xff1a;Win10虚拟内存设置指南...

黑马点评项目总结1-使用Session发送验证码和登录login和 使用Redis存储验证码和Redis的token登录

黑马先是总结了从session实现登录&#xff0c;然后是因为如果使用了集群方式的服务器的话&#xff0c;存在集群共享session互相拷贝效率低下的问题&#xff0c;接着引出了速度更快的内存型的kv数据库Redis&#xff0c; 使用Session发送验证码和登录login 举个例子&#xff1a…...

【大模型】Vllm基础学习

前言&#xff1a;vllm是一个大语言模型高速推理框架&#xff0c;旨在提高大模型的服务效率。优势是内存管理&#xff0c;实现的核心是pageattetion算法。仅在gpu上加速&#xff0c;不在cpu加速。 目录 1. PageAttention2. 实践2.1 安装2.2 离线推理2.3 适配OpenAI的api 1. Page…...

使用vue动态给同一个a标签添加内容 并给a标签设置hover,悬浮文字变色,结果鼠标悬浮有的字上面不变色

如果Vue的虚拟DOM更新机制导致样式更新不及时&#xff0c;你可以尝试以下几种方法来解决这个问题&#xff1a; 确保使用响应式数据&#xff1a; 确保你使用的数据是响应式的&#xff0c;并且任何对这些数据的更改都会触发视图的更新。在Vue中&#xff0c;你应该使用data对象中的…...

【ajax实战06】进行文章发布

本文章目标&#xff1a;收集文章内容&#xff0c;并提交服务器保存 一&#xff1a;基于form-serialize插件收集表单数据 form-serialize插件仅能收集到表单数据&#xff0c;除此之外的数据无法收集到 二&#xff1a;基于axios提交到服务器保存 三&#xff1a;调用alert警告…...

Codeforces Round 954 (Div. 3)(A~E)

目录 A. X Axis B. Matrix Stabilization C. Update Queries D. Mathematical Problem A. X Axis Problem - A - Codeforces 直接找到第二大的数&#xff0c;答案就是这个数与其他两个数的差值的和。 void solve() {vector<ll>a;for (int i 1; i < 3; i){int x;…...

基于Java微信小程序同城家政服务系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…...

[21] Opencv_CUDA应用之使用Haar级联的对象检测

Opencv_CUDA应用之使用Haar级联的对象检测 Haar级联使用矩形特征来检测对象,它使用不同大小的矩形来计算不同的线和边缘特征。矩形包含一些黑色和白色区域,如下图所示,它们在图像的不同位置居中 类Haar特征检测算法的思想是计算矩形内白色像素和黑色像素之间的差异这个方法的…...

CXL:拯救NVMe SSD缓存不足设计难题-2

LMB提出了基于CXL协议的内存扩展框架和内核模块。该方案利用CXL内存扩展器作为物理DRAM源&#xff0c;旨在提供一个统一的内存分配接口&#xff0c;使PCIe和CXL设备都能方便地访问扩展的内存资源。通过这个接口&#xff0c;NVMe驱动和CUDA的统一内存内核驱动可以直接高效地访问…...

Opencv学习项目6——pyzbar

在之前我们学习了解码图片中的二维码&#xff0c;这次我们开启摄像头来解码视频中二维码 开启摄像头 # 打开摄像头 cap cv2.VideoCapture(0) cap.set(3, 640) # 设置摄像头画面宽度 cap.set(4, 480) # 设置摄像头画面高度 我使用的是笔记本上的摄像头来进行的&#xff0c;…...

Switch 刷安卓11 (LineageOS 18.1) 大气层双系统图文教程

很多朋友手上已经拥有了完成硬破的 Switch &#xff0c;但又不甘心仅仅使用 Switch 本身的地平线系统&#xff0c;Switch 刷安卓 (Android 11) 会是一个好的选择&#xff0c;虽然 Switch 的 CPU 性能拉跨&#xff0c;但和桌面平台同一设计思路的TegraX1 GPU 可谓是先于时代&…...

Spring Boot与Spring Batch的深度集成

Spring Boot与Spring Batch的深度集成 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨在Spring Boot应用中如何实现与Spring Batch的深度集成…...

RTSP协议在视频监控系统中的典型应用、以及视频监控设备的rtsp地址格式介绍

目录 一、协议概述 1、定义 2、提交者 3、位置 二、主要特点 1、实时性 2、可扩展性 3、控制功能 4、回放支持 5、网络适应性 三、RTSP的工作原理 1、会话准备 2、会话建立 3、媒体流控制 4、会话终止 5、媒体数据传输 四、协议功能 1、双向性 2、带外协议 …...

Kotlin基础——异步和并发

同步和异步 同步指的是一种行为&#xff1a;当执行IO操作的时候&#xff0c;在代码层面上我们需要主动去等待结果&#xff0c;直到结果返回阻塞指的是一种状态&#xff1a;当执行IO操作的时候&#xff0c;线程处于挂起状态&#xff0c;就是该线程没有执行了 故同步不是阻塞&a…...