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

oracle存储过程的使用

文章目录

    • oracle存储过程的使用
      • 基本结构
      • 管理存储过程
      • 调用存储过程的方法
      • 存储过程参数关键词: `IN` 和`out`
        • `in/out`测试案例
        • 调用`in/out`测试案例
    • 存储过程语法
      • `DECLARE`声明关键词
      • 赋值
        • 使用`in/out`将值作为子程序的参数分配给变量,看上面的案例
        • 为布尔变量赋值
      • 表达式
        • 串联符`||`
        • 运算符优先级
        • 逻辑运算符
        • 短运算符`or` 和`and`
        • 比较运算符
          • `is null /is not null`
          • 关系运算符
          • `LIKE `
          • `BETWEEN `和`IN`:
      • `case when`:
      • 条件语句`if`
        • if语法
        • if条件命令案例
      • 循环
        • 循环的3种方式
        • 跳出循环的关键词
      • `GOTO`跳转
    • 数据类型
    • 集合
      • 创建集合table
        • 全局使用的集合
        • 局部使用的集合
        • sql查询内容放入集合中
      • 集合比较
        • 可以和null比较,可以集合之间比较
        • 其他比较
      • 集合方法
        • 删除案例
    • 游标`CURSOR`
      • 隐式游标
        • 遍历隐式游标的结果
      • 显式游标
        • 定义
        • 调用游标`CURSOR`
      • 显式游标`Cursor `的属性调用
        • 使用`FETCH`提取游标查询的数据
          • 案例1
          • 案例2:将相同的显式游标提取到不同的变量中
        • 带参数调用游标`CURSOR`
    • 动态参数SQL
      • 动态sql使用占位符的方式
          • 使用`EXECUTE IMMEDIATE`调用动态sql或子程序
          • 使用`open`调用动态sql
      • 使用拼接符生成动态sql
        • 拼接案例
    • 事务管理
      • 语法词
      • 事务案例
      • 设置事务级别
      • 设置私有事务
        • 声明私有事务
        • 调用私有事务的测试
      • 设置只读事务
    • 触发器
      • DML 触发器
      • 触发器案例
    • 异常处理
    • 存储过程demo
      • 案例所需建表语句

oracle存储过程的使用

存储过程官方文档

PLSQL的语法大全

语法|标识符|分隔符等等文档

基本结构

存储过程也可以调用匿名存储过程,具体看官网

-- CREATE OR REPLACE 创建或者替换
CREATE OR REPLACE PROCEDURE P_TEST(-- 这个可以是多个参数,用',' 分割testParams IN varchar2,returnMsg2233 IN OUT varchar2 -- 返回信息的方式111: 推荐来个返回信息,比较友好,可以在存储过程的逻辑设置该值,在调用结束后就可以得到值的内容 
) IS-- 定义的变量LOOP_COUNT   number DEFAULT 5; error_message varchar2(512) DEFAULT '发生错误鸭!';
BEGIN-- 代码逻辑SELECT * FROM DUAL;returnMsg2233 := '我执行成功了哦哦!!!'; -- 返回信息的方式111DBMS_OUTPUT.PUT_LINE(returnMsg2233);-- 打印输出信息-- 异常处理部分开始EXCEPTION                 WHEN VALUE_ERROR THENDBMS_OUTPUT.PUT_LINE(error_message); -- 输出错误信息
END;

管理存储过程

CREATE OR REPLACE ... xxx ... -- 创建或者替换 
DROP PROCEDURE TEST.P_TEST;  -- 删除
ALTER PROCEDURE hr.remove_emp ... xxx ...; -- 更新

调用存储过程的方法

-- 使用call 
CALL P_TEST('test','returnMsg');
-- 使用begin end;
BEGINP_TEST('test','returnMsg');
END;

存储过程参数关键词: INout

用这个关键词可以控制,过程调用之前、期间和之后的参数值

  • IN你可以使用,但是无法赋值
  • OUT为 OUT 参数赋值

in/out测试案例

CREATE OR REPLACE PROCEDURE p (a        PLS_INTEGER,  -- IN by defaultb     IN PLS_INTEGER,c    OUT PLS_INTEGER,d IN OUT BINARY_FLOAT
) AUTHID DEFINER IS
BEGIN-- 打印参数值DBMS_OUTPUT.PUT_LINE('Inside procedure p:');DBMS_OUTPUT.PUT('IN a = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(a), 'NULL'));DBMS_OUTPUT.PUT('IN b = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(b), 'NULL'));DBMS_OUTPUT.PUT('OUT c = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(c), 'NULL'));DBMS_OUTPUT.PUT_LINE('IN OUT d = ' || TO_CHAR(d));-- 可以引用 IN 参数 a 和 b,-- 但不能为它们赋值。c := a+10;  -- 为 OUT 参数赋值d := 10/b;  -- 将值赋给 IN OUT 参数
END;

调用in/out测试案例

-- 调用 out类型参数,必须先用DECLARE进行定义 
DECLAREaa CONSTANT PLS_INTEGER  := 1;bb          PLS_INTEGER  := 2;cc          PLS_INTEGER  := 3;dd          BINARY_FLOAT := 4;ee          PLS_INTEGER;ff          BINARY_FLOAT := 5;
BEGINDBMS_OUTPUT.PUT_LINE('Before invoking procedure p:');DBMS_OUTPUT.PUT('aa = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(aa), 'NULL'));DBMS_OUTPUT.PUT('bb = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(bb), 'NULL'));DBMS_OUTPUT.PUT('cc = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(cc), 'NULL'));DBMS_OUTPUT.PUT_LINE('dd = ' || TO_CHAR(dd));p(aa, -- constantbb, -- initialized variablecc, -- initialized variabledd -- initialized variable);DBMS_OUTPUT.PUT_LINE('After invoking procedure p:');DBMS_OUTPUT.PUT('aa = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(aa), 'NULL'));DBMS_OUTPUT.PUT('bb = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(bb), 'NULL'));DBMS_OUTPUT.PUT('cc = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(cc), 'NULL'));DBMS_OUTPUT.PUT_LINE('dd = ' || TO_CHAR(dd));DBMS_OUTPUT.PUT_LINE('Before invoking procedure p:');DBMS_OUTPUT.PUT('ee = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(ee), 'NULL'));DBMS_OUTPUT.PUT_LINE('ff = ' || TO_CHAR(ff));p(1, -- literal(bb + 3) * 4, -- expressionee, -- uninitialized variableff -- initialized variable);DBMS_OUTPUT.PUT_LINE('After invoking procedure p:');DBMS_OUTPUT.PUT('ee = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(ee), 'NULL'));DBMS_OUTPUT.PUT_LINE('ff = ' || TO_CHAR(ff));
END;

存储过程语法

DECLARE声明关键词

  • 非空约束

    DECLARE acct_id INTEGER(4) NOT NULL := 9999;
    
  • 变量

    DECLARE part_number NUMBER(6);  
    
  • 常量CONSTANT

    DECLARE CONSTANT part_number NUMBER(6);  
    
  • 变量和常量的初始值

    DECLAREhours_worked    INTEGER := 40;pi     CONSTANT REAL := 3.14159;
    
  • %TYPE:声明时使用上一个变量的类型

    该属性允许您声明与以前声明的变量或列具有相同数据类型的数据项(不知道该类型是什么)。如果引用项的声明发生更改,则引用项的声明也会相应更改

    DECLAREname     VARCHAR(25) NOT NULL := 'Smith';surname  name%TYPE := 'Jones';
    

赋值

表达式

串联符||

DECLAREx VARCHAR2(4) := 'suit';y VARCHAR2(4) := 'case';
BEGINDBMS_OUTPUT.PUT_LINE (x || y);DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce');
END;
-- 输出结果:
suitcase
applesauce

运算符优先级

算子操作
**
+,-同一性,否定
*,/乘法、除法
+, ,`-``
=, , , , , , , , , , , ,<``>``<=``>=``<>``!=``~=`` ^=``IS``NULL``LIKE``BETWEEN``IN比较
NOT否定
AND连接
OR包含

逻辑运算符

xyx AND yx OR yNOT x
TRUETRUETRUETRUEFALSE
TRUEFALSEFALSETRUEFALSE
TRUENULLNULLTRUEFALSE
FALSETRUEFALSETRUETRUE
FALSEFALSEFALSEFALSETRUE
FALSENULLFALSENULLTRUE
NULLTRUENULLTRUENULL
NULLFALSEFALSENULLNULL
NULLNULLNULLNULLNULL

短运算符orand

or,前面的不成立,就不执行,and都必须成立

DECLAREon_hand  INTEGER := 0;on_order INTEGER := 100;
BEGIN-- 不会导致被零除错误;-- 求值在第一次表达式后停止IF (on_hand = 0) OR ((on_order / on_hand) < 5) THENDBMS_OUTPUT.PUT_LINE('On hand quantity is zero.');END IF;
END;

比较运算符

  • 算术比较:数字比较而已
  • 布尔比较:布尔值比较
  • 字符比较:默认情况下,如果一个字符的二进制值较大,则该字符大于另一个字符
  • 日期比较:日期打就打
is null /is not null
关系运算符
算子意义
=等于
<>, , ,!=``~=`` ^=不等于
<小于
>大于
<=小于或等于
>=大于或等于
LIKE
DECLAREPROCEDURE compare (value   VARCHAR2,pattern VARCHAR2) ISBEGINIF value LIKE pattern THENDBMS_OUTPUT.PUT_LINE ('TRUE');ELSEDBMS_OUTPUT.PUT_LINE ('FALSE');END IF;END;
BEGINcompare('Johnson', 'J%s_n');compare('Johnson', 'J%S_N');
END;
-- 输出结果
TRUE
FALSE
BETWEEN IN

和平常sql一样

case when

和平常sql一样

CASE selector
WHEN selector_value_1 THEN result_1
WHEN selector_value_2 THEN result_2
...
WHEN selector_value_n THEN result_n
[ ELSEelse_result ]
END

条件语句if

if语法

$IF boolean_static_expression $THENtext
[ $ELSIF boolean_static_expression $THENtext
]...
[ $ELSEtext
$END
]

if条件命令案例

BEGIN$IF DBMS_DB_VERSION.VER_LE_10_1 $THEN  -- 选择命令判断$ERROR 'unsupported database release' $END  -- 错误命令,输出错误信息$ELSEDBMS_OUTPUT.PUT_LINE ('Release ' || DBMS_DB_VERSION.VERSION || '.' ||DBMS_DB_VERSION.RELEASE || ' is supported.');-- 10.2版本支持下面的commit语法 :COMMIT WRITE IMMEDIATE NOWAIT;$END  -- 终结命令
END;

循环

循环的3种方式

  1. LOOP简单循环

    LOOP-- 代码逻辑
    END LOOP;
    
  2. WHILE循环

    -- 使用condition,这个会一直循环,只能手动退出循环
    WHILE condition LOOP -- 代码逻辑
    END LOOP;
    -- 条件不成立会退出循环
    WHILE a>2 LOOP -- 代码逻辑
    END LOOP;
    
  3. FOR循环

    -- 语法
    FOR loop_variable IN [REVERSE] lower_bound .. upper_bound LOOPstatements
    END LOOP;
    -- 案例一,不使用 REVERSE ,loop_variable初始值=下限值1
    FOR loop_variable IN 1..5 LOOPstatements
    END LOOP;
    -- 案例二,使用 REVERSE ,loop_variable初始值=上限值5
    FOR loop_variable IN REVERSE 1..5 LOOPstatements
    END LOOP;
    

跳出循环的关键词

  • CONTINUE:跳出本次循环
  • EXIT:结束循环
  • CONTINUE WHEN :条件跳出本次循环
  • EXIT WHEN :条件结束循环
  • RETURN:结束代码

GOTO跳转

可以跳到某个定义的声明标签<<gotp_here>>,这个标签可以在GOTO的前面也可以在后面

DECLAREdone  BOOLEAN;
BEGINFOR i IN 1..5 LOOPIF done THENDBMS_OUTPUT.PUT_LINE('这里是1111');GOTO gotp_here; --可以跳到某个定义的声明标签END IF;<<gotp_here>>DBMS_OUTPUT.PUT_LINE('跳到22222');END LOOP;
END;

数据类型

数据类型,就用数据库的,要多的去看官网

集合

集合的官网

创建集合table

声明一个table,可以用 declare声明局部使用,也可以直接创建这么一个类型,全局使用

全局使用的集合

CREATE OR REPLACE TYPE nt_type IS TABLE OF NUMBER;
/
CREATE OR REPLACE PROCEDURE print_nt (nt nt_type) AUTHID DEFINER ISi  NUMBER;
BEGINi := nt.FIRST;IF i IS NULL THENDBMS_OUTPUT.PUT_LINE('nt is empty');ELSEWHILE i IS NOT NULL LOOPDBMS_OUTPUT.PUT('nt.(' || i || ') = ');DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(nt(i)), 'NULL'));i := nt.NEXT(i);END LOOP;END IF;DBMS_OUTPUT.PUT_LINE('---');
END print_nt;
/
DECLAREnt nt_type := nt_type();  -- nested table variable initialized to empty
BEGINprint_nt(nt);nt := nt_type(90, 9, 29, 58);print_nt(nt);
END;

局部使用的集合

DECLARETYPE Roster IS TABLE OF VARCHAR2(15);  -- nested table type-- 使用构造函数初始化的嵌套表变量:names Roster := Roster('D Caruso', 'J Hamil', 'D Piro', 'R Singh');...

sql查询内容放入集合中

DECLARETYPE NumTab IS TABLE OF employees.employee_id%TYPE;
TYPE NameTab IS TABLE OF employees.last_name%TYPE;enums NumTab;
names NameTab;PROCEDURE print_first_n (n POSITIVE) IS
BEGINIF enums.COUNT = 0 THENDBMS_OUTPUT.PUT_LINE ('Collections are empty.');ELSEDBMS_OUTPUT.PUT_LINE ('First ' || n || ' employees:');FOR i IN 1 .. n LOOPDBMS_OUTPUT.PUT_LINE ('  Employee #' || enums(i) || ': ' || names(i));END LOOP;END IF;
END;BEGINSELECT employee_id, last_nameBULK COLLECT INTO enums, namesFROM employeesORDER BY employee_id;print_first_n(3);print_first_n(6);
END;

集合比较

可以和null比较,可以集合之间比较

DECLARETYPE dnames_tab IS TABLE OF VARCHAR2(30); -- element type is not record typedept_names1 dnames_tab :=dnames_tab('Shipping','Sales','Finance','Payroll');dept_names2 dnames_tab :=dnames_tab('Sales','Finance','Shipping','Payroll');dept_names3 dnames_tab :=dnames_tab('Sales','Finance','Payroll');BEGIN-- 判断 is nullIF dept_names1 IS NOT NULL THENDBMS_OUTPUT.PUT_LINE('dept_names1 IS NOT NULL');ELSEDBMS_OUTPUT.PUT_LINE('dept_names1 IS NULL');END IF;-- 判断集合相等IF dept_names1 = dept_names2 THENDBMS_OUTPUT.PUT_LINE('dept_names1 = dept_names2');END IF;IF dept_names2 != dept_names3 THENDBMS_OUTPUT.PUT_LINE('dept_names2 != dept_names3');END IF;
END;

其他比较

DECLARETYPE nested_typ IS TABLE OF NUMBER;nt1 nested_typ := nested_typ(1,2,3);nt2 nested_typ := nested_typ(3,2,1);nt3 nested_typ := nested_typ(2,3,1,3);nt4 nested_typ := nested_typ(1,2,4);PROCEDURE testify (truth BOOLEAN := NULL,quantity NUMBER := NULL) ISBEGINIF truth IS NOT NULL THENDBMS_OUTPUT.PUT_LINE (CASE truthWHEN TRUE THEN 'True'WHEN FALSE THEN 'False'END);END IF;IF quantity IS NOT NULL THENDBMS_OUTPUT.PUT_LINE(quantity);END IF;END;
BEGINtestify(truth => (nt1 IN (nt2,nt3,nt4)));        -- Truetestify(truth => (nt1 SUBMULTISET OF nt3));      -- Truetestify(truth => (nt1 NOT SUBMULTISET OF nt4));  -- Truetestify(truth => (4 MEMBER OF nt1));             -- Falsetestify(truth => (nt3 IS A SET));                -- Falsetestify(truth => (nt3 IS NOT A SET));            -- Truetestify(truth => (nt1 IS EMPTY));                -- Falsetestify(quantity => (CARDINALITY(nt3)));         -- 4testify(quantity => (CARDINALITY(SET(nt3))));    -- 3
END;

集合方法

collection_name.method
DELETE程序从集合中删除元素。
TRIM程序从阵列或嵌套表的末尾删除元素。
EXTEND程序将元素添加到阵列或嵌套表的末尾。
EXISTS功能当且仅当 varray 或嵌套表的指定元素存在时返回。TRUE
FIRST功能返回集合中的第一个索引。
LAST功能返回集合中的最后一个索引。
COUNT功能返回集合中的元素数。
LIMIT功能返回集合可以具有的最大元素数。
PRIOR功能返回指定索引前面的索引。
NEXT功能返回成功指定索引的索引。

删除案例

collection.DELETE-- 删除所有
collection.DELETE(2,4)-- range删除index 2到5的, 包含左右2和5,都会删除
collection.DELETE('A','C')-- range删除字符串索引,'A'到'C' 包含左右A\C,都会删除

游标CURSOR

由 PL/SQL 构造和管理的游标是隐式游标。您构造和管理的游标是显式游标

隐式游标

隐式游标是由 PL/SQL 构造和管理的会话游标。PL/SQL 每次运行 或 DML 语句时都会打开一个隐式游标。您无法控制隐式游标,但可以从其属性中获取信息

隐式游标属性包括,**注:**这个了解有即可,没啥意思。

  • SQL%ISOPEN :游标是否打开?
  • SQL%FOUND:执行上一个sql后是否有任何行受到影响?
  • SQL%NOTFOUND:执行上一个sql后没有受影响的行吗?
  • SQL%ROWCOUNT :执行上一个sql后受影响的行数是多少?
  • SQL%BULK_ROWCOUNT(请参阅“获取受 FORALL 语句影响的行数”
  • SQL%BULK_EXCEPTIONS(请参阅“在 FORALL 语句完成后处理 FORALL 异常”

遍历隐式游标的结果

直接使用sql语句结果作为遍历的对象。

BEGINFOR item IN (SELECT last_name, job_idFROM employeesWHERE job_id LIKE '%CLERK%'AND manager_id > 120ORDER BY last_name)LOOPDBMS_OUTPUT.PUT_LINE('Name = ' || item.last_name || ', Job = ' || item.job_id);END LOOP;
END;

显式游标

定义

可以先声明显式游标,然后再在同一块、子程序或包中定义它,也可以同时声明和定义它

-- 仅声明游标
CURSOR cursor_name [ parameter_list ] RETURN return_type;
-- 声明并定义
CURSOR cursor_name [ parameter_list ] [ RETURN return_type ]IS select_statement;
DECLARECURSOR c1 RETURN departments%ROWTYPE;    -- 声明 c1CURSOR c2 IS                             -- 声明 and 定义 c2SELECT employee_id, job_id, salary FROM employeesWHERE salary > 2000; CURSOR c1 RETURN departments%ROWTYPE IS  -- 定义 c1,SELECT * FROM departments              -- 重复返回类型WHERE department_id = 110;CURSOR c3 RETURN locations%ROWTYPE;      -- 声明 c3CURSOR c3 IS                             -- 定义 c3,SELECT * FROM locations                -- 省略返回类型WHERE country_id = 'JP';
BEGINNULL;
END;

调用游标CURSOR

open cursor_name;
close cursor_name;

显式游标Cursor 的属性调用

  • %ISOPEN : 是否打开
  • %FOUND : 是否提取到行内容
  • %NOTFOUND : 是否未提取到任何内容
  • %ROWCOUNT : 提取了多少行数据

使用FETCH提取游标查询的数据

/*语法*/
FETCH cursor_name INTO into_clause;
案例1
DECLARECURSOR c1 ISSELECT last_name, job_id FROM employeesWHERE ORDER BY last_name;v_lastname  employees.last_name%TYPE;  -- last_name变量v_jobid     employees.job_id%TYPE;     -- job_id变量CURSOR c2 ISSELECT * FROM employeesWHERE ORDER BY job_id;v_employees employees%ROWTYPE;  -- 表行的记录变量BEGINOPEN c1;LOOP  -- 将 2 列提取到变量中FETCH c1 INTO v_lastname, v_jobid;EXIT WHEN c1%NOTFOUND;DBMS_OUTPUT.PUT_LINE( RPAD(v_lastname, 25, ' ') || v_jobid );END LOOP;CLOSE c1;DBMS_OUTPUT.PUT_LINE( '-------------------------------------' );OPEN c2;LOOP  -- 将整行提取到v_employees记录中FETCH c2 INTO v_employees;EXIT WHEN c2%NOTFOUND;DBMS_OUTPUT.PUT_LINE( RPAD(v_employees.last_name, 25, ' ') ||v_employees.job_id );END LOOP;CLOSE c2;
END;
案例2:将相同的显式游标提取到不同的变量中
DECLARECURSOR c ISSELECT e.job_id, j.job_titleFROM employees e, jobs jWHERE e.job_id = j.job_id AND e.manager_id = 100ORDER BY last_name;-- 记录游标结果集行的变量:job1 c%ROWTYPE;job2 c%ROWTYPE;job3 c%ROWTYPE;job4 c%ROWTYPE;job5 c%ROWTYPE;BEGINOPEN c;FETCH c INTO job1;  -- fetches first rowFETCH c INTO job2;  -- fetches second rowFETCH c INTO job3;  -- fetches third rowFETCH c INTO job4;  -- fetches fourth rowFETCH c INTO job5;  -- fetches fifth rowCLOSE c;DBMS_OUTPUT.PUT_LINE(job1.job_title || ' (' || job1.job_id || ')');DBMS_OUTPUT.PUT_LINE(job2.job_title || ' (' || job2.job_id || ')');DBMS_OUTPUT.PUT_LINE(job3.job_title || ' (' || job3.job_id || ')');DBMS_OUTPUT.PUT_LINE(job4.job_title || ' (' || job4.job_id || ')');DBMS_OUTPUT.PUT_LINE(job5.job_title || ' (' || job5.job_id || ')');
END;

带参数调用游标CURSOR

使用DEFAULT修饰,可以为CURSOR设置默认值参数,就可以选择传参或者不传参数进行调用。

DECLARECURSOR c (job VARCHAR2, max_sal NUMBER 10000,hired DATE DEFAULT TO_DATE('2022-01-01', 'yyyy-mm-dd')) ISSELECT last_name, first_name, (salary - max_sal) overpaymentFROM employeesWHERE job_id = jobAND salary > max_salAND hire_date > hiredORDER BY salary;PROCEDURE print_overpaid ISlast_name_   employees.last_name%TYPE;first_name_  employees.first_name%TYPE;overpayment_      employees.salary%TYPE;BEGINLOOPFETCH c INTO last_name_, first_name_, overpayment_;EXIT WHEN c%NOTFOUND;DBMS_OUTPUT.PUT_LINE(last_name_ || ', ' || first_name_ ||' (by ' || overpayment_ || ')');END LOOP;END print_overpaid;BEGINDBMS_OUTPUT.PUT_LINE('-------------------------------');DBMS_OUTPUT.PUT_LINE('Overpaid Sales Representatives:');DBMS_OUTPUT.PUT_LINE('-------------------------------');OPEN c('22', 10000);  -- 不传参数print_overpaid;CLOSE c;DBMS_OUTPUT.PUT_LINE('------------------------------------------------');DBMS_OUTPUT.PUT_LINE('Overpaid Sales Representatives Hired After 2022-12-12:');DBMS_OUTPUT.PUT_LINE('------------------------------------------------');OPEN c('22', 10000, TO_DATE('2022-12-12', 'yyyy-mm-dd')); -- 传入参数-- new referenceprint_overpaid;CLOSE c;
END;

动态参数SQL

动态sql使用占位符的方式

使用EXECUTE IMMEDIATE调用动态sql或子程序
EXECUTE IMMEDIATE 存储过程子程序/sql  USING IN OUT[参数:params111,params222...]  INTO [结果:result] ;
 -- 动态调用sqlsql_stmt := 'INSERT INTO payroll VALUES (:a, :b, :c, :d)';EXECUTE IMMEDIATE sql_stmt USING  a,b,c,d INTO result_22333;
CREATE OR REPLACE PROCEDURE create_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);
END;
/
DECLAREplsql_block VARCHAR2(500);new_deptid  NUMBER(4);new_dname   VARCHAR2(30) := 'Advertising';new_mgrid   NUMBER(6)    := 200;new_locid   NUMBER(4)    := 1700;
BEGIN-- 动态调用sqlsql_stmt := 'INSERT INTO payroll VALUES (:a, :b, :c, :d)';EXECUTE IMMEDIATE sql_stmt USING  new_deptid, new_dname, new_mgrid, new_locid;-- 动态 PL/SQL 块调用子程序plsql_block := 'BEGIN create_dept(:a, :b, :c, :d); END;';/* 在 USING 子句中指定绑定变量。  指定第一个参数的模式。  默认情况下,其他参数的模式是正确的 */EXECUTE IMMEDIATE plsql_blockUSING IN OUT new_deptid, new_dname, new_mgrid, new_locid;
END;
使用open调用动态sql
  • 方式一:open 调用游标查询数据库数据

    DECLARETYPE EmpCurTyp  IS REF CURSOR;v_emp_cursor    EmpCurTyp;emp_record      employees%ROWTYPE;v_stmt_str      VARCHAR2(200);v_e_job         employees.job%TYPE;
    BEGIN-- 带占位符的动态 SQL 语句:v_stmt_str := 'SELECT * FROM employees WHERE job_id = :j';-- 打开光标并在 USING 子句中指定绑定变量:OPEN v_emp_cursor FOR v_stmt_str USING 'MANAGER';-- 一次从结果集中获取一行:LOOPFETCH v_emp_cursor INTO emp_record;EXIT WHEN v_emp_cursor%NOTFOUND;END LOOP;-- Close cursor:CLOSE v_emp_cursor;
    END;
    
  • 方式二:open查询集合中数据

    CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER ASTYPE rec IS RECORD(f1 NUMBER, f2 VARCHAR2(30));TYPE mytab IS TABLE OF rec INDEX BY pls_integer;
    END;
    /
    DECLAREv1 pkg.mytab;  -- collection of recordsv2 pkg.rec;c1 SYS_REFCURSOR;
    BEGINOPEN c1 FOR 'SELECT * FROM TABLE(:1)' USING v1;FETCH c1 INTO v2;CLOSE c1;DBMS_OUTPUT.PUT_LINE('Values in record are ' || v2.f1 || ' and ' || v2.f2);
    END;
    

使用拼接符生成动态sql

这种方式如果参数是外部的,那么会有安全隐患,尽量不要使用

拼接案例

CREATE OR REPLACE PROCEDURE get_recent_record (user_name     IN  VARCHAR2,service_type  IN  VARCHAR2,rec           OUT VARCHAR2
) AUTHID DEFINERISquery VARCHAR2(4000);
BEGIN/* 以下 SELECT 语句很容易被修改 因为它使用串联来构建 WHERE 子句。 */query := 'SELECT value FROM secret_records WHERE user_name='''|| user_name|| ''' AND service_type='''|| service_type|| ''' AND date_created> DATE '''|| TO_CHAR(SYSDATE - 30,'YYYY-MM-DD')|| '''';DBMS_OUTPUT.PUT_LINE('Query: ' || query);EXECUTE IMMEDIATE query INTO rec;DBMS_OUTPUT.PUT_LINE('Rec: ' || rec);
END;

事务管理

语法词

  • COMMIT;:提交事务
  • ROLLBACK;:回滚事务
  • SAVEPOINT xxxx;:设置保存点
  • ROLLBACK TO xxxxx;:回滚至保存点
  • COMMIT WRITE IMMEDIATE NOWAIT;:提交并立即写入

保存点允许您回滚部分事务而不是整个事务。每个会话的活动保存点数不受限制。

回滚到保存点时,将擦除在该保存点之后标记的任何保存点。不会擦除回滚到的保存点。简单的回滚或提交会擦除所有保存点。

事务案例

DROP TABLE emp_name;
CREATE TABLE emp_name AS
SELECT employee_id, last_name
FROM employees;CREATE UNIQUE INDEX empname_ixON emp_name (employee_id);DROP TABLE emp_sal;
CREATE TABLE emp_sal AS
SELECT employee_id, salary
FROM employees;CREATE UNIQUE INDEX empsal_ixON emp_sal (employee_id);DROP TABLE emp_job;
CREATE TABLE emp_job AS
SELECT employee_id, job_id
FROM employees;CREATE UNIQUE INDEX empjobid_ixON emp_job (employee_id);DECLAREemp_id       NUMBER(6);emp_lastname VARCHAR2(25);emp_salary   NUMBER(8, 2);emp_jobid    VARCHAR2(10);
BEGINSELECT employee_id, last_name, salary, job_idINTO emp_id, emp_lastname, emp_salary, emp_jobidFROM employeesWHERE employee_id = 120;INSERT INTO emp_name (employee_id, last_name)VALUES (emp_id, emp_lastname);-- 保存点SAVEPOINT do_insert;INSERT INTO emp_sal (employee_id, salary)VALUES (emp_id, emp_salary);IF SQL%ROWCOUNT <= 0 THEN-- 回滚到保存点ROLLBACK TO do_insert;END IF;INSERT INTO emp_job (employee_id, job_id)VALUES (emp_id, emp_jobid);-- 提交事务,提交事务,并且立即写入 COMMIT WRITE IMMEDIATE NOWAIT;
EXCEPTIONWHEN DUP_VAL_ON_INDEX THEN-- 回滚事务ROLLBACK;DBMS_OUTPUT.PUT_LINE('Inserts were rolled back');
END;

设置事务级别

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

设置私有事务

可以给函数存储过程等等设置私有事务,进入带有私有事务的函数、存储过程时,主事务将被挂起,私有事务不影响主事务。

启动后,自治事务是完全独立的。它不与主事务共享锁、资源或提交依赖项。您可以记录事件、递增重试计数器等,即使主事务回滚也是如此。

自主事务可帮助您构建模块化、可重用的软件组件。您可以将自治事务封装在存储的子程序中。调用应用程序不需要知道该存储子程序执行的操作是成功还是失败。

 PRAGMA AUTONOMOUS_TRANSACTION;

声明私有事务

-- 案例1:函数私有事务
CREATE OR REPLACE PACKAGE emp_actions AUTHID DEFINER AS  -- package specification
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER)RETURN NUMBER;
END emp_actions;
/
CREATE OR REPLACE PACKAGE BODY emp_actions AS  -- package body
-- code for function raise_salaryFUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER)RETURN NUMBER ISPRAGMA AUTONOMOUS_TRANSACTION;new_sal NUMBER(8,2);BEGINUPDATE employees SET salary =salary + sal_raise WHERE employee_id = emp_id;COMMIT;SELECT salary INTO new_sal FROM employeesWHERE employee_id = emp_id;RETURN new_sal;END raise_salary;
END emp_actions;
/
-- 案例二:存储过程私有事务
CREATE OR REPLACE PROCEDURE lower_salary
(emp_id NUMBER, amount NUMBER)AUTHID DEFINER ASPRAGMA AUTONOMOUS_TRANSACTION;
BEGINUPDATE employeesSET salary =  salary - amountWHERE employee_id = emp_id;COMMIT;
END lower_salary;
/
-- 案例3:声明私有事务
DROP TABLE emp;
CREATE TABLE emp AS SELECT * FROM employees;DECLAREPRAGMA AUTONOMOUS_TRANSACTION;emp_id NUMBER(6)   := 200;amount NUMBER(6,2) := 200;
BEGINUPDATE employeesSET salary =  salary - amountWHERE employee_id = emp_id;COMMIT;
END;

调用私有事务的测试

DROP TABLE debug_output;
CREATE TABLE debug_output (message VARCHAR2(200));CREATE OR REPLACE PACKAGE debugging AUTHID DEFINER ASFUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
END debugging;
/
CREATE OR REPLACE PACKAGE BODY debugging ASFUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 ISPRAGMA AUTONOMOUS_TRANSACTION;BEGININSERT INTO debug_output (message) VALUES (msg);COMMIT;RETURN msg;END;
END debugging;
/
-- 查询时调用包函数
DECLAREmy_emp_id    NUMBER(6);my_last_name VARCHAR2(25);my_count     NUMBER;
BEGINmy_emp_id := 120;SELECT debugging.log_msg(last_name)INTO my_last_nameFROM employeesWHERE employee_id = my_emp_id;/* 即使您在此这里回滚,插入“debug_output”的操作依然还是提交了,因为它是自主事务,不受外部事务影响。 */ROLLBACK;
END;
/

设置只读事务

您可以使用该语句开始只读或读写事务、建立隔离级别或将当前事务分配给指定的回滚段。SET``TRANSACTION

只读事务对于在其他用户更新相同表时运行多个查询非常有用。

在只读事务期间,所有查询都引用数据库的同一快照,从而提供多表、多查询、只读一致性视图。其他用户可以像往常一样继续查询或更新数据。提交或回滚将结束事务。

该语句必须是只读事务中的第一个 SQL 语句,并且在事务中只能出现一次。如果将事务设置为 ,则后续查询仅看到事务开始之前提交的更改。的使用不会影响其他用户或交易

DECLAREdaily_order_total    NUMBER(12,2);weekly_order_total   NUMBER(12,2);monthly_order_total  NUMBER(12,2);
BEGINCOMMIT; -- 提交当前事务
--     设置 READ ONLY 事务SET TRANSACTION READ ONLY NAME 'Calculate Order Totals';SELECT SUM (order_total)INTO daily_order_totalFROM ordersWHERE order_date = SYSDATE;SELECT SUM (order_total)INTO weekly_order_totalFROM ordersWHERE order_date = SYSDATE - 7;SELECT SUM (order_total)INTO monthly_order_totalFROM ordersWHERE order_date = SYSDATE - 30;
--  结束 read-only transactionCOMMIT;
END;

触发器

触发器根据触发语句及其作用的项目来指定触发事件,触发器有: DML 触发器、系统触发器、条件触发器。

触发器的作用:

  • 自动生成虚拟列值
  • 记录事件
  • 收集有关表访问的统计信息
  • 针对视图发出 DML 语句时修改表数据
  • 当子表和父表位于分布式数据库的不同节点上时强制实施参照完整性
  • 将有关数据库事件、用户事件和 SQL 语句的信息发布到订阅应用程序
  • 防止在正常工作时间之后对表执行 DML 操作
  • 防止无效交易
  • 强制实施无法使用约束定义的复杂业务或参照完整性规则

DML 触发器

一个简单的 DML 触发器正好在以下时间点之一触发:

  • 在触发语句运行之前

    (触发器称为 BEFORE 语句触发器或语句级 ``**BEFORE 触发器*。*)

  • 触发语句运行后

    (该触发器称为 AFTER 语句触发器或语句级 ``**AFTER 触发器*。*)

  • 在触发语句影响的每一行之前

    (该触发器称为每行*``*触发器之前或行级别 BEFORE 触发器。)

  • 在触发语句影响的每一行之后

    (触发器称为*触发器行级别* AFTER 触发器。)

触发器案例

大量案例在这里

/* 设置一个抛异常终止的触发器 */
CREATE OR REPLACE TRIGGER dept_restrictBEFORE DELETE OR UPDATE OF Deptno ON deptFOR EACH ROW--在从部门中删除行或更新部门的主键 (DEPTNO) 之前,-- 检查 EMP 中的从属外键值;-- 如果找到任何内容,请回滚。DECLAREDummy                  INTEGER;  -- Use for cursor fetchemployees_present      EXCEPTION;employees_not_present  EXCEPTION;PRAGMA EXCEPTION_INIT (employees_present, -4094);PRAGMA EXCEPTION_INIT (employees_not_present, -4095);-- Cursor used to check for dependent foreign key values.CURSOR Dummy_cursor (Dn NUMBER) ISSELECT Deptno FROM emp WHERE Deptno = Dn;BEGINOPEN Dummy_cursor (:OLD.Deptno);FETCH Dummy_cursor INTO Dummy;-- 如果找到依赖外键,则引发用户指定的外键 错误代码和消息,通过抛异常终止或回滚事务。如果未找到,关闭光标-- 在允许触发语句完成之前。IF Dummy_cursor%FOUND THENRAISE employees_present;     -- Dependent rows existELSERAISE employees_not_present; -- No dependent rows existEND IF;CLOSE Dummy_cursor;EXCEPTIONWHEN employees_present THENCLOSE Dummy_cursor;-- 通过抛异常终止或回滚事务Raise_application_error(-20001, 'Employees Present in'|| ' Department ' || TO_CHAR(:OLD.DEPTNO));WHEN employees_not_present THENCLOSE Dummy_cursor;
END;
/* 设置一个监听sql后插入日志的触发器 */
CREATE OR REPLACE TRIGGER log_salary_increaseAFTER UPDATE OF salary ON employeesFOR EACH ROW
BEGININSERT INTO Emp_log (Emp_id, Log_date, New_salary, Action)VALUES (:NEW.employee_id, SYSDATE, :NEW.salary, 'New Salary');
END;

异常处理

-- 代码逻辑 
...
EXCEPTIONWHEN ex_name_1 THENstatements_1                 -- Exception handlerWHEN ex_name_2 OR ex_name_3 THEN statements_2  -- Exception handlerWHEN OTHERS THENROLLBACK;RAISE;                      -- 再向外面抛出异常
END;
...   -- 如果只是处理异常,继续执行,还是可以在EXCEPTION后加代码逻辑

存储过程demo

CREATE OR REPLACE PROCEDURE P_TEST(testParams IN varchar2, -- 这个可以是多个参数,用',' 分割returnMsg IN OUT varchar2 -- 这个作为返回信息
) ISLOOP_COUNT   number DEFAULT 5; /* 获取全局锁的最大重试次数 */ID           VARCHAR2(16) DEFAULT ''; /* 存储锁的主键ID */LOCK_VERSION INTEGER DEFAULT 0; /* 存储锁的版本变量 */UP_LOCK_SQL  varchar2(512) DEFAULT ''; /* 更新锁的sql */UP_NUM       number DEFAULT 0; /* 更新锁的行数,作为是否更新成功的标志 */CURSOR VERSIONS IS SELECT ID,VERSIONSFROM TEST_LOCKWHERE ID = 'APP_SERVERS_LOCK'; /* 获取锁版本的游标sql,游标可以查询多个数据,并进行存储 */APP_COUNT    INTEGER DEFAULT 0; /* 测试查询sql */
BEGIN--     使用 WHILE 循环WHILE LOOP_COUNT > 0LOOP--  ============ 使用游标 ========OPEN VERSIONS; -- 打开游标/*游标无法打开*/IF VERSIONS%ISOPEN = FALSE THENreturnMsg := '异常原因:游标打开失败';CLOSE VERSIONS;RETURN;END IF;FETCH VERSIONS INTO ID,LOCK_VERSION;  -- 使用FETCH获取游标结果
--             EXIT WHEN VERSIONS%NOTFOUND; --  当VERSIONS是数组需要遍历时,,可以用这个判断是否遍历完成,从而退出循环-- 使用完毕后,关闭游标IF VERSIONS%ISOPEN THENCLOSE VERSIONS;END IF;
--   ========== 执行自定义sql ===========-- 为了使用变量参数,这里使用 || 进行拼接,UP_LOCK_SQL :='UPDATE TEST_LOCK SET VERSIONS = ' || LOCK_VERSION ||' + 1 WHERE ID = ''APP_SERVERS_LOCK'' AND VERSIONS =  ' || LOCK_VERSION || ' ';-- 执行sqlEXECUTE IMMEDIATE UP_LOCK_SQL;-- 获取更新结果UP_NUM := SQL%ROWCOUNT;-- 如果更新成功,跳出循环IF UP_NUM = 1 THEN--                 --  跳出本次循环
--                 CONTINUE;--   结束循环EXIT;END IF;-- 代码逻辑,查询版本,更新,重试次数5次LOOP_COUNT := LOOP_COUNT - 1;END LOOP;
-- ============ 使用for 循环FOR v_counter2 IN 1..5LOOP<<GO_BACK>> -- 定义一个返回点-- 将  COUNT(*) 结果放入变量 APP_COUNTSELECT COUNT(*) INTO APP_COUNT FROM TEST_LOCK;IF APP_COUNT > 0 THENUPDATE TEST_LOCK SET VERSIONS=VERSIONS+1 WHERE  ID='APP_SERVERS_LOCK';--                 --  跳出本次循环
--                 CONTINUE;--   结束循环EXIT;ELSEGOTO GO_BACK;END IF;END LOOP;END ;

案例所需建表语句

CREATE TABLE TEST_LOCK
(ID       VARCHAR2(16) NOT NULLCONSTRAINT "TEST_LOCK_pk"PRIMARY KEY,VERSIONS NUMBER(16)   NOT NULL
)
/COMMENT ON TABLE TEST_LOCK IS '全局锁的表'
/COMMENT ON COLUMN TEST_LOCK.ID IS '唯一id'
/COMMENT ON COLUMN TEST_LOCK.VERSIONS IS '版本号';
/INSERT INTO SUNCPS.TEST_LOCK(ID, VERSIONS) VALUES ('APP_SERVERS_LOCK', 0);
DECLARE  c PLS_INTEGER; d BINARY_FLOAT;BEGIN /p(1, 2, c, d);/dbms_output.PUT_LINE(c);/dbms_output.PUT_LINE(d);/
END;

相关文章:

oracle存储过程的使用

文章目录oracle存储过程的使用基本结构管理存储过程调用存储过程的方法存储过程参数关键词&#xff1a; IN 和outin/out测试案例调用in/out测试案例存储过程语法DECLARE声明关键词赋值使用in/out将值作为子程序的参数分配给变量&#xff0c;看上面的案例为布尔变量赋值表达式串…...

一些无线通信系统模型的概念

一些无线通信系统模型的概念 扩频通信,指的是系统的带宽WWW远大于其信息传输速率R(bits/s)R(bits/s)R(bits/s), 定义展频带因子BeWRB_e \frac{W}{R}Be​RW​, 易知在扩频通信系统中,BeB_eBe​远大于1. 在频率上产生如此大的冗余度,主要是为了减轻无线通信或卫星通信中经常产生…...

GAIDC 2023盛会迎来大模型论坛“主场”,百度飞桨护航大模型产业发展

‍‍‍‍2月25日-26日&#xff0c;2023全球人工智能开发者先锋大会&#xff08;GAIDC&#xff09;在上海临港举行&#xff0c;大会以“向光而行的AI开发者”为主题&#xff0c;汇聚了当前科技和产业革命中的开发者先锋力量。百度深度参与本次大会&#xff0c;飞桨联合上海市人工…...

Python编写GUI界面案例:实现免费下载器

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 本次网站&#xff1a; 本文所有模块\环境\源码\教程皆可点击文章下方名片获取此处跳转 开发环境: python 3.8 运行代码 pycharm 2022.3 辅助敲代码 模块使用&#xff1a; import parsel >>> pip install parsel…...

我的 System Verilog 学习记录(6)

引言 本文简单介绍 SystemVerilog 语言的 线程。 前文链接&#xff1a; 我的 System Verilog 学习记录&#xff08;1&#xff09; 我的 System Verilog 学习记录&#xff08;2&#xff09; 我的 System Verilog 学习记录&#xff08;3&#xff09; 我的 System Verilog 学…...

SAP 常见问题大全及问题解决大全

1.A:在公司代码分配折旧表时报错? 在公司代码分配折旧表时报错&#xff0c;提示是“3000 的公司代码分录不完全&#xff0d;参见长文本” 希望各位大侠帮我看看。 3000 的公司代码分录不完全&#xff0d;参见长文本 R: a.你把零进项税的代码分配给这个公司代码就可以了 …...

10.Quartz实现定时打分 热帖排行

1.Spring Quartz(1)简介核心组件scheduler 接口&#xff1a;核心调度工具&#xff0c;所有任务由这一接口调用job&#xff1a;定义任务&#xff0c;重写execute方法JobDetail接口&#xff1a;配置描述Trigger接口&#xff1a;什么时候运行&#xff0c;以什么样的频率运行(2)Spr…...

pandas 读取Excel 批量转换时间戳

一、安装 pip install pandas 如果出报错&#xff0c;不能运行&#xff0c;可以安装 pip install xlrd 二、 代码如下 import pandas as pd import time,datetimefile_path rC:\Users\Administrator\Desktop\携号转网测试\admin_log.xls df pd.read_excel(file_path, sheet_n…...

绕过检测之Executor内存马浅析(内存马系列篇五)

写在前面 前面已经从代码层面讲解了Tomcat的架构&#xff0c;这是内存马系列文章的第五篇&#xff0c;带来的是Tomcat Executor类型的内存马实现。有了前面第四篇中的了解&#xff0c;才能更好的看懂内存马的构造。 前置 什么是Executor Executor是一种可以在Tomcat组件之间…...

《C++模板进阶》

致前行的人&#xff1a; 要努力&#xff0c;但不要着急&#xff0c;繁花锦簇&#xff0c;硕果累累都需要过程&#xff01; 目录 前言&#xff1a; 1.非类型模板参数 1.1.概念&#xff1a; 1.2.使用注意事项 2.模板特化 2.1函数模板特化 2.2类模板特化 3.模板的分离编译 3.1什么…...

【项目管理】项目进度管理中的逻辑关系

项目的进度管理是项目核心管理之一&#xff0c;通过合理的进度安排&#xff0c;制定出科学可行的分项工期表&#xff0c;并条理清晰的显示出项目进度之间的逻辑关系。 1、目标是计划的灵魂 进度计划必须按照确定的项目总进度要求进行编制&#xff0c;了解项目总目标和整体安…...

ARM的汇编指令集

一、汇编指令 1.1 指令与伪指令 汇编的指令 指令是CPU机器指令的助记符&#xff0c;编译后会得到一串二进制机器码&#xff0c;由CPU执行 汇编的伪指令 伪指令本质上不是指令&#xff0c;它是编译器环境提供用来指导编译过程&#xff0c;编译后伪指令不会生成机器码 伪指令…...

@font-face用法超详细讲解

文章目录font-face是什么font-face基本语法urlTTFOTFEOTWOFFSVGformatfont-face用法示例font字体下载ttf-to-eot 字体转换器https://blog.csdn.net/qq_37417446/article/details/106728725 https://developer.mozilla.org/zh-CN/docs/Web/CSS/font-face font-face是什么 font-…...

[oeasy]python0095_乔布斯求职_雅达利_atari_breakout_打砖块_布什内尔_游戏机_Jobs

编码进化 回忆上次内容 上次 我们回顾了 电子游戏的历史 从 电子游戏鼻祖 双人网球到 视频游戏 PingPong再到 街机游戏 Pong 雅达利 公司 来了 嬉皮士 捣乱&#xff1f;&#x1f914; 布什内尔 会如何 应对 呢&#xff1f;&#x1f914; 布什内尔 布什内尔 本身就有点 …...

全景极简印度史

转自&#xff1a;印度简史 - 知乎 (zhihu.com)印度是世界上最早出现文明的地区之一&#xff0c;印度河是其文明的发源地。古印度文明的疆域曾包括今印度共和国、巴基斯坦、孟加拉国、阿富汗斯坦南部部分地区和尼泊尔。史前时代200万年前&#xff0c;巴基斯坦北部的希瓦利克遗址…...

《设计模式》模板方法

《设计模式》模板方法 模板方法是一种行为型设计模式&#xff0c;用于定义一个算法的框架&#xff0c;而将一些步骤的实现留给子类来完成。模板方法在基类中定义了一个模板方法&#xff0c;该方法确定了算法的基本结构&#xff0c;然后将一些步骤的实现交给子类去完成。这个模…...

Linux环境内存管理——链表

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Windows程序员如何学习Linux环境内存管理。由于很多程序在Windows环境下开发好后&#xff0c;还要部署到Linux服务器上去&#xff0c;所以作为Windows程序员有必要学习Linux环境的内存…...

String、StringBuffer、StringBuilder类

String类 由多个字符组成的一串数据,值一旦创建不可改变 private final char value[]; 一旦值改变,就会创建新的对象 String s "abc"; //char[] c {a,b,c}s"def"; // 并不是String的值改变,而是创建了一个新的对象s"gh";s"aaa"…...

在VScode中添加Linux中的Docker容器中的Python解释器

VScode编辑器在安装好Python插件之后会自动选择环境变量中排序最高的那一个解释器作为默认解释器&#xff0c;而想要额外添加新的Python解释器就需要自己设置。 VScode编辑器安装在本地电脑 支持Python的docker安装在远程服务器 第一步&#xff0c;在/usr/local/下新建pytho…...

无法将“django-admin”项识别为cmdlet,函数,脚本文件或可运行程序的名称问题

无法将“django admin”项识别为cmdlet&#xff0c;函数&#xff0c;脚本文件或可运行程序的名称问题 小提示&#xff1a;首先检查一下有没有拼写错误&#xff01;&#xff01;&#xff01;没有的话请继续 我们要知道django装到哪里去了 pip show django 注意&#xff1a;3.0…...

乐友商城学习笔记(十五)

无状态登陆原理 在服务器端保存session 无状态不需要session&#xff0c;把登陆状态保存在cookie中 jwtrsa token&#xff1a;登陆时&#xff0c; jwt oath2 jwt&#xff1a;头信息&#xff08;jwt&#xff09; 载荷&#xff08;用户信息&#xff0c;签发人&#xff0c;签发时…...

目标检测论文阅读:CBNet算法笔记

标题&#xff1a;CBNet: A Composite Backbone Network Architecture for Object Detection 期刊&#xff1a;TIP2022 论文地址&#xff1a;https://ieeexplore.ieee.org/document/9932281/ 官方代码&#xff1a;https://github.com/VDIGPKU/CBNetV2 作者单位&#xff1a;北京大…...

vue前端与Java后端进行跨域交互

1.后端的几种解决方法 1.在Controller上面加上CrossOrigin 2.写一个配置文件并且在Controller层加上注解CORSConfig package com.wolwo.langyage.base.util;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configurat…...

【设计模式】2.抽象工厂模式

抽象工厂模式 前面介绍的工厂方法模式中考虑的是一类产品的生产&#xff0c;如畜牧场只养动物、电视机厂只生产电视机、传智播客只培养计算机软件专业的学生等。 这些工厂只生产同种类产品&#xff0c;同种类产品称为同等级产品&#xff0c;也就是说&#xff1a;工厂方法模式…...

Telnet 基础实验1: Telnet 实验

Telnet 基础实验1&#xff1a; Telnet 实验 拓扑图 配置命令 R1 的配置 undo ter mo sys sys R1 interface g0/0/0 ip address 192.168.1.1 255.255.255.0 qR2 的配置 undo ter mo system-view sysname R2 interface g0/0/0 ip address 192.168.1.2 255.255.255.0 q两台设…...

机器学习经典算法——决策树(Decision Tree)

决策树的基本原理 决策树是⼀种分⽽治之的决策过程。⼀个困难的预测问题&#xff0c;通过树的分⽀节点&#xff0c;被划分成两个或多个较为简单的⼦集&#xff0c;从结构上划分为不同的⼦问题。将依规则分割数据集的过程不断递归下去。随着树的深度不断增加&#xff0c;分⽀节…...

MySQl总结

文章目录MySQL数据库的常见考点1、ACID事务原理事务持久性事务原子性MVCC基本概念MVCC基本原理undo logundo log版本链readviewMVCC实现原理RC读已提交RR可重复读MVCC实现原理总结2、并发事务引发的问题3、事务隔离级别4、索引索引结构BTreeHash面试题索引分类思考题语法性能分…...

【学习笔记】NOIP爆零赛7

结论专场&#xff0c;结果被踩暴了 青鱼和序列 赛时的做法是&#xff0c;维护∑aii\sum a_i\times i∑ai​i的取值&#xff0c;发现只和最后一次操作222的位置有关&#xff0c;于是递推O(n)O(n)O(n)解决。 赛后发现还有更神奇的结论 第二个结论是&#xff0c;第一次进行操作…...

一文读懂账号体系产品设计

一、账号体系的概念及价值账号体系是用户在各平台上的通行证。平台给与用户可持续的服务&#xff0c;用户在平台上获取价值&#xff0c;中间的媒介&#xff0c;便是账号体系。阿境将其理解为维系用户与平台之间的枢纽。注&#xff1a;本文中&#xff0c;账号账户&#xff0c;二…...

从“入门”到“专家”,一份3000字完整的性能测试体系的知识分享

随着科技的飞速发展&#xff0c;软件产品广泛应用于各个行业领域&#xff0c;人们对计算机和网络的依赖性越来越大&#xff0c;对新奇事物也越来越感兴趣&#xff0c;成千上万的用户活跃在庞大的网络系统中&#xff0c;这给提供服务的系统带来严重的负荷&#xff0c;"高并…...

软件技术专业专升本考试科目/免费检测网站seo

蝴蝶操作和Rader排序 蝴蝶操作的定义&#xff1a; 雷德(Rader)算法 (Gold Rader bit reversal algorithm) 按自然顺序排列的二进制数&#xff0c;其下面一个数总是比其上面一个数大1&#xff0c;即下面一个数是上面一个数在最低位加1并向高位进位而得到的。而倒位序二进制数的下…...

微网站与手机网站/口碑营销5t理论

http://www.cnblogs.com/chenergougou/p/7056557.html openstack RPC通信 OpenStack 的主要组件有 Nova、Cinder、Neutron、Glance 等&#xff0c;分别负责云平台的计算、存储、网络资源管理。openstack 各组件之间是通过 REST 接口进行相互通信&#xff0c;而各组件内部则采用…...

岐山县住房和城市建设局网站/婚恋网站排名前十名

第4章 并发编程 4.5 channel channel的传递 在Go语言中channel本身也是一个原生类型&#xff0c;与map之类的类型地位一样&#xff0c;因此channel本身在定义后也可以通过channel来传递。 利用channel的这个可传递特性&#xff0c;我们可以实现非常强大、灵活的系统架构。相比…...

长春火车站到中日联谊医院怎么走/站长之家怎么找网址

为什么80%的码农都做不了架构师&#xff1f;>>> 语法格式&#xff1a; select [level], column, expr... from table  [where condition]  start with condition  connect by [prior column1 column2 |  column1 prior column2]; 层次查询是通过start w…...

网站程序有哪些/百度站长工具seo综合查询

神经网络&#xff08;一&#xff09;神经网络模型理解1.1 模型1.2 神经网络模型&#xff08;前馈&#xff09;1.3 建立神经网络模型1.4 多元分类1.5 循环神经网络与对称连接网络&#xff08;二&#xff09;神经网络模型实现2.1 代价函数2.2 反向传播2.2.1 数学推导&#xff08;…...

公司委托建设网站合同范本/成品短视频网站源码搭建

从上一周周一学习KMP算法之后&#xff0c;每天晚上都失眠到1点过起夜&#xff0c;身体再疲倦脑子都异常清醒&#xff0c;要死了要死了。 kmp算法真的有毒。 这个题&#xff0c;我用优先队列记录最小的下标&#xff0c;用Map记录每个数字是第几天&#xff0c;然后让那个值和队列…...