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

Oracle数据库数据编程SQL<3.1 PL/SQL 匿名块 及 流程控制中的条件判断、循环、异常处理和随机函数应用>

PL/SQL部分

在SQL的基础上增加了一些过程化的控制语句。

过程化控制语句包括:类型定义、判断、循环、游标、异常处理(例外处理)

目录

PL/SQL匿名块

一、匿名块基本结构

1、匿名块由三个部分组成:

2、注意事项:

二、不带声明的匿名块示例

1. 简单示例:打印

(1)点击【执行】,然后查看【结果】

三、declare带声明部分的匿名块

1、变量的声明

2、变量的类型

(1)字符类型 char varchar/varchar2

(2)数值类型 number int

(3)日期类型 date

(4)布尔类型 boolean --值返回对错空

(5)表名.列名%type--和表中的某一列类型相同

(6)表名%rowtype--和表的结构一致

(7)record--自定义列的类型

4、变量的赋值

(1):=直接赋值

(2)变量的值可以赋给另一个变量

(3)变量可以二次赋值

(4)变量赋值可以用函数

(5)变量可以运算

(6)用键盘可以直接输入赋值&

(7)用 select … into语句给变量赋值,值只返回一行,可以多列

(8)type 变量 is record();自定义变量

(9)returning…into 查询DML的上一次操作赋值给变量

(10)变量声明时可以声明多个,只用其中的某几个;

(11)变量声明了,可以不用,但是使用的变量一定要声明。

四、 带异常处理的匿名块

五、匿名块中begin部分的流程控制(条件判断)

1. IF-THEN-ELSE 语句

(1)单分支

(2)双分支

(3)多分支

(4)举例

2、CASE-WHEN-THEN-ELSE语句

六、PL/SQL里的case when和SQL里的case when 的区别?

七、匿名块中begin部分的循环(也属于流程控制)

1、简单循环(基本循环)

2、while循环

3、for循环

八、匿名块中的异常处理

1. 预定义异常

2. 自定义异常

九、随机函数的应用

1、dbms_random.value(小值,大值)

2、dbms_random.string(参数,长度)

3、在匿名块中的应用


PL/SQL匿名块

匿名块是 Oracle PL/SQL 中最基本的代码执行单元,它没有名称,不能被存储或重复调用,通常用于一次性执行的任务或测试代码片段。

一、匿名块基本结构

1、匿名块由三个部分组成:

[DECLARE
    -- 声明部分(可选)
    变量、常量、游标、异常等的声明]
BEGIN
    -- 执行部分(必需)
    PL/SQL 和 SQL 语句
[EXCEPTION
    -- 异常处理部分(可选)
    异常处理程序]
END;
/   命令窗口需要加 / 以示结束

2、注意事项:

(1)每一部分的语句都需要以;结尾,end后也必须加;

(2)习惯的加注释

(3)赋值的时候加“:=”,判断相等的时候“=”。

(4)命令窗口需要修改时,输入ed或edit

(5)命令窗口开启打印服务时输入set serveroutput on

                       关闭打印服务 set serveroutput off

declare
  v1 number;
  v2 number;
begin
  v1 := 1000;
  v2 := 2000;
  dbms_output.put_line(v1 || '+' || v2 || '=' || (v1 + v2));
end;

这里注意加号和等号的执行顺序,加号是有执行优先级的,只有(v1+v2),这个语句才能正确执行

二、不带声明的匿名块示例

1. 简单示例:打印

BEGIN
    DBMS_OUTPUT.PUT_LINE('Hello, 你是不是学废了');--打印
END;
/

dbms_output.put --不换行打印必须搭配换行打印使用***
dbms_output.put_line --换行打印

(1)点击【执行】,然后查看【结果】

三、declare带声明部分的匿名块

1、变量的声明

变量名 变量的类型长度 v_name varchar2(20);

2、变量的类型

(1)字符类型 char varchar/varchar2

(2)数值类型 number int

(3)日期类型 date

DECLARE
    v_count     NUMBER := 0;
    v_name      VARCHAR2(100) := '张三';
    v_hiredate  DATE := SYSDATE;
    v_flag      BOOLEAN := TRUE;
    c_pi CONSTANT NUMBER := 3.14159;
BEGIN
    -- 执行代码
END;
/

(4)布尔类型 boolean --值返回对错空

(5)表名.列名%type--和表中的某一列类型相同

  • 所引用的数据库列的数据类型可以不必知道。
  • 索引用的数据库列的数据类型可以实时改变,即原表改变他会自动改变。
  • 定义变量不能与表中列的名字相同
  • 同一时间只能接受一个值
    DECLARE
        v_emp_name employees.last_name%TYPE;
        v_emp_sal  employees.salary%TYPE;
    BEGIN
        SELECT last_name, salary INTO v_emp_name, v_emp_sal
        FROM employees
        WHERE employee_id = 100;
        
        DBMS_OUTPUT.PUT_LINE(v_emp_name || '的薪资是: ' || v_emp_sal);
    END;
    /

(6)表名%rowtype--和表的结构一致

DECLARE
    v_emp_record employees%ROWTYPE;
BEGIN
    SELECT * INTO v_emp_record
    FROM employees
    WHERE employee_id = 100;
    
    DBMS_OUTPUT.PUT_LINE('员工信息: ' || 
                         v_emp_record.employee_id || ', ' ||
                         v_emp_record.last_name || ', ' ||
                         v_emp_record.salary);
END;
/

(7)record--自定义列的类型

4、变量的赋值

(1):=直接赋值

declare
v_number number(4);
begin
v_number:=7788;
end;

(2)变量的值可以赋给另一个变量

declare
v_1 number(4):=7788;
v_2 number(4);
begin
v_2:=v_1;
end;

(3)变量可以二次赋值

declare
v1 number:=1;
begin
dbms_output.put_line('v1='||v1);--打印
v1:=2;
dbms_output.put_line('v1='||v1);
end;

(4)变量赋值可以用函数

declare
v1 varchar2(20):='SMITH';
begin
v1:=lower(v1);
dbms_output.put_line(v1);
end;

(5)变量可以运算

(6)用键盘可以直接输入赋值&

declare
v1 number:=&abcd;
begin
dbms_output.put_line('v1='||v1);
end;

(7)用 select … into语句给变量赋值,值只返回一行,可以多列

declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp where ename='SMITH';
dbms_output.put_line(v_sal);
end;

(8)type 变量 is record();自定义变量

declare
type t_emp is record(v_e emp.empno%type,
                     v_h emp.hiredate%type,
                     v_d emp.deptno%type);
b t_emp;
begin
select empno,hiredate,deptno into b
from emp where ename='KING';
dbms_output.put_line(b.v_e||chr(13)||
                     b.v_h||chr(13)||
                     b.v_d);
end;

(9)returning…into 查询DML的上一次操作赋值给变量

declare
v_n emp1.ename%type;
v_sal emp1.sal%type;
begin
insert into emp1 (ename,sal) values('Eddie',10000)
returning ename,sal into v_n,v_sal;
dbms_output.put_line(v_n||','||v_sal);
end;

(10)变量声明时可以声明多个,只用其中的某几个;

(11)变量声明了,可以不用,但是使用的变量一定要声明。

--注意切换到Hr用户
DECLARE
    v_employee_name VARCHAR2(100);
    v_salary       NUMBER;
BEGIN
    SELECT last_name, salary INTO v_employee_name, v_salary
    FROM employees
    WHERE employee_id = 100;
    
    DBMS_OUTPUT.PUT_LINE('员工姓名: ' || v_employee_name);
    DBMS_OUTPUT.PUT_LINE('员工薪资: ' || v_salary);
END;
/

--注意切换到scott用户
--删除emp1的员工编号是 7782的员工,输入【删除】的ename和mgr
--更新emp1的名字是KING的员工,
--名字改成首字母大写,输入【更新】后的名字和工作
create table emp6 as select * from emp;
declare
  v_e   emp6.ename%type;
  v_mgr emp6.mgr%type;
  v_n   emp6.ename%type;
  v_job emp6.job%type;
begin
  delete from emp6 where empno = 7902; 
  returning ename, mgr into v_e, v_mgr;
  update emp6
     set ename = lower(ename), job = initcap(job)
   where ename = 'KING'
  returning ename, job into v_n, v_job;
  dbms_output.put_line(v_e || '' || v_mgr || chr(13) || v_n || '' || v_job);
end;
/
select * from emp6

四、 带异常处理的匿名块

DECLARE
    v_dept_name VARCHAR2(100);
BEGIN
    SELECT department_name INTO v_dept_name
    FROM departments
    WHERE department_id = 999;  -- 假设这个部门不存在
    
    DBMS_OUTPUT.PUT_LINE('部门名称: ' || v_dept_name);
EXCEPTION --异常处理
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('错误: 未找到部门信息');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('错误代码: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('错误信息: ' || SQLERRM);
END;
/

五、匿名块中begin部分的流程控制(条件判断)

1. IF-THEN-ELSE 语句

(1)单分支

if 条件 then 要执行的语句 end if;

(2)双分支

if 条件 then 要执行的语句 else 要执行的语句 end if;

(3)多分支

if 条件1 then 要执行的语句
elsif 条件2 then 要执行的语句
elsif 条件3 then 要执行的语句
...
else 要执行的语句
end if;

(4)举例

DECLARE
    v_score NUMBER := 85;
BEGIN
    IF v_score >= 90 THEN
        DBMS_OUTPUT.PUT_LINE('优秀');
    ELSIF v_score >= 80 THEN
        DBMS_OUTPUT.PUT_LINE('良好');
    ELSIF v_score >= 60 THEN
        DBMS_OUTPUT.PUT_LINE('及格');
    ELSE
        DBMS_OUTPUT.PUT_LINE('不及格');
    END IF;
END;
/


--从键盘输入一个员工编号,如果他的工作是MANAGER打印'他是经理';
--如果他的工作是CLERK打印'他是职员';
--如果他的工作是SALESMAN打印'他是销售';
--如果他的工作是ANALYST打印'他是分析员';
--否则打印'他是老板'。
declare
  v_job emp.job%type;
begin
  select job into v_job from emp where empno = &empno;
  if v_job = 'MANAGER' then
    dbms_output.put_line('他是经理');
  elsif v_job = 'CLERK' then
    dbms_output.put_line('他是职员');
  elsif v_job = 'SALESMAN' then
    dbms_output.put_line('他是销售');
  elsif v_job = 'ANALYST' then
    dbms_output.put_line('他是分析员');
  else
    dbms_output.put_line('他是老板');
  end if;
end;
/

2、CASE-WHEN-THEN-ELSE语句

--语法
case when 条件1 then 要执行的语句;
         when 条件2 then 要执行的语句;
         ……
        else 要执行的语句;
end case;

--举例
DECLARE
    v_grade CHAR(1) := 'B';
BEGIN
    CASE v_grade
        WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('优秀');
        WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('良好');
        WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('及格');
        ELSE DBMS_OUTPUT.PUT_LINE('未知等级');
    END CASE;
END;
/

--练习
--从键盘上输入一个员工编号,如果他的名字的首字母是A、B、C则打印1
--如果他的名字的首字母是D、E、F则打印2
--如果他的名字的首字母是G、H、I则打印3
--否则打印4;
declare
  v_e char;
begin
  select substr(ename, 1, 1) into v_e from emp where empno = &empno;
  case
    when v_e in ('A', 'B', 'C') then--首字母是A、B、C
      dbms_output.put_line(1);--打印1
    when v_e in ('D', 'E', 'F') then--首字母是D、E、F
      dbms_output.put_line(2);--打印2
    when v_e in ('G', 'H', 'I') then--首字母是G、H、I
      dbms_output.put_line(3);--打印3
    else
      dbms_output.put_line(4);--打印4
  end case;
end;

六、PL/SQL里的case when和SQL里的case when 的区别?

(1)sql里的case when 是一个值,pl/sql 里相当于if的作用;

(2)sql里case when 内部不能加分号,pl/sql里每一个条件后都要加分号;

(3)pl/sql里case when 后可以加DML;

(4)sql里case when 以end结尾,pl/sql里以end case 结尾;

七、匿名块中begin部分的循环(也属于流程控制)

循环:简单循环、while循环、for循环

1、简单循环(基本循环)

【1】语法:
     loop
     要执行的语句;
     exit when 退出的条件;
     end loop;
     进入循环不需要条件。
     注意:必须设置自增变量来控制循环以免出现死循环。

【2】举例
     DECLARE
         v_counter NUMBER := 1;
     BEGIN
         LOOP
             DBMS_OUTPUT.PUT_LINE('当前计数: ' || v_counter);
             v_counter := v_counter + 1;
             EXIT WHEN v_counter > 5;
         END LOOP;
     END;
     /
    ----------------------------------------------------------
     declare
       i number := 1;
     begin
       loop
         dbms_output.put_line(i);
         i := i + 1;
         exit when i > 10;
       end loop;
     end;
     /

【3】练习
(1)用循环打印 A、B、C、D、E、F……Z。
     declare
       i number := ascii('A') - 1;
     begin
       loop
         i := i + 1;
         dbms_output.put(chr(i)||' ');--不换行打印
         exit when i > ascii('M') - 1;
       end loop;
       dbms_output.put_line('');--和一个换行打印搭配才能打印出东西
       i:=ascii('M');
       loop
         i := i + 1;
         dbms_output.put(chr(i));--不换行打印
         exit when i > ascii('Z') - 1;
       end loop;
       dbms_output.put_line('');--和一个换行打印搭配才能打印出东西
     end;
     /

(2)123 456 789 
     declare
       i1 number := 1;
       i2 number := 1;
       j  varchar(2) := ' ';
       k  number := 0;
     begin
       loop
         k := k + 1;
         loop
           dbms_output.put(i1);
           i1 := i1 + 1;
           i2 := 3 * k;
           exit when i1 > i2;
         end loop;
         dbms_output.put(j);
         exit when k > 9;
       end loop;
       dbms_output.put_line('');
     end;
     /
     输出-----------
     1 2 3  
     4 5 6  
     7 8 9  
     ---------------
(3)循环打印1-10的和,显示1+2+3+4+5+6+7+8+9+10=
     declare
       v_sum number := 0;
       v_num number := 1;
     begin
       loop
         dbms_output.put(v_num || '+');
         v_sum := v_num + v_sum;
         v_num := v_num + 1;
         exit when v_num > 9;
       end loop;
       dbms_output.put_line(10 || '=' || (v_sum + v_num));
     end;
     /
(4)只打印1-10的和
     declare
       v_sum number := 0;
       v_num number := 1;
     begin
       loop
         v_sum := v_num + v_sum;
         v_num := v_num + 1;
         exit when v_num > 9;
       end loop;
       dbms_output.put_line(v_sum + v_num);
     end;
     /

2、while循环

【1】语法
while 条件 
loop 要执行的语句
{exit when 条件}
end loop;
满足while后的条件才进入循环,不满足不进入循环
注意:必须要设置自增变量控制循环,以免出现死循环。

/*###################################################*/
【2】举例
DECLARE
    v_counter NUMBER := 1;
BEGIN
    WHILE v_counter <= 5 LOOP
        DBMS_OUTPUT.PUT_LINE('当前计数: ' || v_counter);
        v_counter := v_counter + 1;
    END LOOP;
END;
/
---------------------------------------------------------
declare
  i number := 0;
begin
  while i < 10
  loop
    i := i + 1;
    dbms_output.put_line(i);
    exit when i=5;--中途退出
  end loop;
end;

/*###################################################*/
【3】练习
(1)用while循环打印A、B、C、D、E、F
declare
  i number := ascii('A') - 1;
begin
  while i < ascii('Z') loop
    dbms_output.put_line(chr(i + 1));
    i := i + 1;
  end loop;
end;
/

(2)循环打印1-10的和
declare
  v_sum number := 0;
  v_num number := 1;
begin
  while v_num <=10 loop
    v_sum := v_num + v_sum;
    dbms_output.put_line(v_sum);
    v_num := v_num + 1;
  end loop;
end;
/

(3)循环打印10-1
declare
  v1 number := 10;
begin
  while v1 > 0 loop
    dbms_output.put_line(v1);
    v1 := v1 - 1;
  end loop;
end;
/
===================================
declare
  v1 number := 10;
begin
  while v1 > 0 loop
    dbms_output.put(v1||' ');
    v1 := v1 - 1;
  end loop;
  dbms_output.put_line('');
end;
/

(4)用while循环写九九乘法表*******
DECLARE
    x INT := 1;
    y INT;
BEGIN
    WHILE x <= 9 LOOP
        y := 1;
        WHILE y <= x LOOP
            dbms_output.put(y || ' * '|| x || ' = ' || x*y || ' ');
            y := y + 1;
        END LOOP;
        x := x + 1;
        dbms_output.put_line(''); 
    END LOOP;
END;
/

3、for循环

【1】语法
for 变量 in {reverse}小值..大值
  loop
  要执行的语句;
  {exit when 条件;
  end loop;
每循环一次,循环变量自动+1;
使用关键字 reverse 循环变量自动-1;
跟在in reverse 后面的数字必须是从小到大的顺序,而且必须是整数

/*###################################################*/
【2】举例
BEGIN
    FOR i IN 1..5 LOOP
        DBMS_OUTPUT.PUT_LINE('当前计数: ' || i);
    END LOOP;
    
    -- 反向循环
    FOR i IN REVERSE 1..5 LOOP
        DBMS_OUTPUT.PUT_LINE('反向计数: ' || i);
    END LOOP;
END;
/
-----------------------------------------------------
begin
  for i in reverse 1 .. 10 loop
    dbms_output.put_line(i);
  end loop;
end;
/

/*###################################################*/
【3】练习
(1)打印A-Z
begin
  for i in ascii('A') .. ascii('Z') loop
    dbms_output.put(chr(i));
  end loop;
  dbms_output.put_line('');
end;
/
-----------------------------------------------------
(2)打印20以内的奇数
方法1:
declare
 j number;
begin
  for i in 1..10 loop
    j:=2*i-1;
    dbms_output.put_line(j);
    end loop;
end;
方法2:
begin
  for i in 1 .. 20 loop
    if mod(i, 2) = 1 then
      dbms_output.put_line(i);
    end if;
  end loop;
end;
/
-----------------------------------------------------
(3)打印1-20的和
declare
  n number := 0;
begin
  for i in 1 .. 20 loop
    n := n + i;
  end loop;
  dbms_output.put_line(n);
end;
/
-----------------------------------------------------
(4)打印1-20以内奇数的乘积
declare
  n number := 1;
  j number;
begin
  for i in 1 .. 10 loop
    j := 2 * i - 1;
    n := n * j;
  end loop;
  dbms_output.put_line(n);
end;
/
-----------------------------------------------------
(5)打印九九乘法表
begin
  for i in 1 .. 9 loop--行数
    for j in 1 .. i loop--列数
      dbms_output.put(j || '×' || i || '=' || i * j || ' ');
    end loop;
  dbms_output.put_line('');
  end loop;
end;
/
---------------------------------
begin
  for i in 1..9 loop
    for j in 1..i loop----第一次循环是 1----1
                      ----第二次循环是 1----2
                      ----第三次循环是 1----3
      dbms_output.put(j||'*'||i||'='||i*j||' ');
      end loop;
  dbms_output.put_line('');
  end loop;
end;
/
-----------------------------------------------------
(6)打印金字塔
begin
  for i in 1 .. 9 loop
    for j in  1 .. (9-i) loop
      dbms_output.put(' ');
    end loop;
    for  k in 1..(2*i-1) loop
    dbms_output.put('*');
    end loop;
    dbms_output.put_line('');
  end loop;
end;
/
-----------------------------------------------------
(7)打印直角
begin
  for i in  reverse 1 .. 9 loop
    for j in  1 .. i loop
      dbms_output.put('*');
    end loop;
    dbms_output.put_line('');
  end loop;
end;

八、匿名块中的异常处理

1. 预定义异常

BEGIN
    -- 可能出错的代码
    UPDATE employees SET salary = salary * 1.1 WHERE employee_id = 9999;
    
    IF SQL%NOTFOUND THEN
        DBMS_OUTPUT.PUT_LINE('未更新任何行');
    END IF;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('未找到数据');
    WHEN TOO_MANY_ROWS THEN
        DBMS_OUTPUT.PUT_LINE('返回多行数据');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('错误代码: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('错误信息: ' || SQLERRM);
END;
/

2. 自定义异常

DECLARE
    e_invalid_dept EXCEPTION;
    v_dept_id NUMBER := 99;
BEGIN
    -- 检查部门是否存在
    IF v_dept_id NOT BETWEEN 10 AND 100 THEN
        RAISE e_invalid_dept;
    END IF;
    
    -- 正常处理
    DBMS_OUTPUT.PUT_LINE('部门ID有效');
EXCEPTION
    WHEN e_invalid_dept THEN
        DBMS_OUTPUT.PUT_LINE('错误: 无效的部门ID ' || v_dept_id);
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('其他错误');
END;
/

九、随机函数的应用

1、dbms_random.value(小值,大值)

dbms_random.value(小值,大值)
返回的是小数(小值到大值之间的)
在-2^31-2^31之间
select dbms_random.value(-1,10) from dual

2、dbms_random.string(参数,长度)

dbms_random.string(参数,长度)
u/U 大写字母
l/L 小写字母
a/A 字母
x/X 大写字母和数字
p/P 任意可打印字符
select dbms_random.string('p',5) from dual

3、在匿名块中的应用

【1】
--生成一个0-10的随机整数,如果大于5则输出‘大’,
--如果小于5则输出‘小’,如果等于5输出‘巧了’。
declare
  n number;
begin
  n := trunc(dbms_random.value(0, 10));
  if n > 5 then
    dbms_output.put_line(n || '大');
  elsif n < 5 then
    dbms_output.put_line(n || '小');
  else
    dbms_output.put_line(n || '巧了');
  end if;
end;
/

【2】
--连选十次
declare
  n number;
begin
  for i in 1 .. 10 loop
    n := trunc(dbms_random.value(0, 100));
    if n > 5 then
      dbms_output.put(n || '普通' || ' ');
    elsif n < 5 then
      dbms_output.put(n || '稀有' || ' ');
    else
      dbms_output.put(n || '传说' || ' ');
    end if;
  end loop;
  dbms_output.put_line('');
end;
/

【3】
--声明一个变量要求和hr 用户的employees的hire_date的类型一致
--把2003年入职,员工编号是141的first_name,last_name 输出。
declare
v_h hr.employees.hire_date%type;
v_f hr.employees.first_name%type;
v_l hr.employees.last_name%type;
begin
  select first_name,last_name into v_f,v_l
  from hr.employees e where e.employee_id=141 
  and to_char(e.hire_date,'yyyy')=2003;
  dbms_output.put_line(v_f||' '||v_l);
  end;
/

【4】
--打印1*2*3*...*20的式子和结果
declare
  n number := 1;
begin
  for i in 1 .. 20 loop
    n := n * i;
    if i < 20 then
      dbms_output.put(i || '×');
    else
      dbms_output.put(i);
    end if;
  end loop;
  dbms_output.put_line('=' || n);
end;


http://www.kler.cn/a/614352.html

相关文章:

  • 知能行每日综测
  • C# .net ai Agent AI视觉应用 写代码 改作业 识别屏幕 标注等
  • 全球化2.0 | ZStack举办香港Partner Day,推动AIOS智塔+DeepSeek海外实践
  • 【云原生】docker 搭建单机PostgreSQL操作详解
  • 【Prometheus】Prometheus的特点、数据采集方式、架构、数据模型详解
  • 【Linux指南】Linux内核:操作系统的核心引擎
  • 前端快速系统学习Rust的路径
  • 【CSS】相对位置小练习
  • 基于springboot+vue的农产品电商平台
  • C++ STL 序列式容器之(三)-- List
  • 全包圆玛奇朵样板间亮相,极简咖啡风引领家装新潮流
  • 365打卡第J7周:对于ResNeXt-50算法的思考
  • 【MySQL数据库】MySQL 主从复制检查方式
  • es6 fetch
  • 【商城实战(100)】商城败局启示录:探寻成功的反方向
  • 算法刷题记录——题解目录汇总(持续更新)
  • 拦截器和过滤器详解
  • Centos与Ubuntu系统的对比分析
  • 《K230 从熟悉到...》矩形检测
  • [GXYCTF2019]禁止套娃1 [GitHack] [无参数RCE]