目录

存储过程概述

存储过程参数

存储过程变量

流程控制语句

select into 查询并赋值

存储函数 VS 存储过程

自定义函数实现递归查询

递归查询·数据准备

自定义函数·向下递归查询

自定义函数实现·向上递归查询


数据准备:

DROP TABLE IF EXISTS `book_2`;
CREATE TABLE `book_2` (`id` int(11) PRIMARY KEY auto_increment,`title` varchar(128) NOT NULL,`price` float(8,2) DEFAULT NULL COMMENT '价格',`publish` date DEFAULT NULL COMMENT '发布时间',`info` varchar(128) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of book_2
-- ----------------------------
INSERT INTO `book_2`(title,price,publish,info) VALUES ('三国演义', '88.68', '2019-09-08', '三国混战');
INSERT INTO `book_2`(title,price,publish,info) VALUES ('红楼梦', '48.35', '2019-03-08', '一个家族的兴衰');

存储过程概述

1、MySQL 5.0 版本开始支持存储过程,存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。

2、存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。

3、存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。

存储过程创建

1、创建的存储过程会保存在数据库的数据字典中。

-- 创建存储过程基本语法,没有参数也必须有括号

delimiter $$
create procedure 存储过程名(in | out | inout 参数1 数据类型,in | out | inout 参数2 数据类型,…)
begin
   declare 变量名  类型;
   执行语句;
end $$

delimiter ;  #将语句的结束符号恢复为分号

call 存储过程名称[(传参)]; -- 调用存储过程

DROP PROCEDURE 存储过程名称;  -- MySQL 删除存储过程:

drop procedure if exists 存储过程名称; # 如果存在存储过程,则删除,否则不做处理
select * from information_schema.routines; #查看所有数据库下的所有存储过程以及函数,可以根据 routine_schema 字段(数据库名称)过虑
select * from mysql.proc ; # 查看所有数据库下的所有存储过程以及函数,可以根据 db 字段(数据库名称)过虑
SHOW PROCEDURE STATUS; #查询所有数据库下的所有存储过程,可以根据 db 字段(数据库名称)过虑
SHOW FUNCTION STATUS; #查询所有数据库下的所有存储函数,可以根据 db 字段(数据库名称)过虑

查询存储过程创建 sql:SHOW CREATE PROCEDURE 数据库名.存储过程名; #数据库名可以省略

SHOW CREATE PROCEDURE test.param1; #查询 test 数据库下的 param1 存储过程的创建 sql
SHOW CREATE PROCEDURE param2; # 直接查询某个存储过程的创建 sql

查询存储函数创建 sql:SHOW CREATE FUNCTION 函数名称;

2、MYSQL 存储过程中的关键语法与入门示例:

用途 语法格式
声明语句结束符(可以自定义) DELIMITER $$ 或 DELIMITER //
声明存储过程 create procedure 存储过程名(参数),即使没有参数,也必须有括号
声明存储函数 create function 存储函数名(参数)
存储过程开始和结束符号 BEGIN .... END
变量定义 DECLARE l_int int unsigned default 4000000;
变量赋值 SET @p_in=1
drop procedure if exists hello_world; -- 如果存在指定的存储过程,则删除
#将sql语句的结束符由默认的分号";"临时改为"$$"(可以自定义符号),这样里面才能正常使用分号";",否则会被当做结束符处理
delimiter $$
create procedure hello_world(in id int) # 声明存储过程
begin  # 开始SELECT id from dual; -- SELECT 语句会把结果查询出来
end $$ # 结束
delimiter ;  #将语句的结束符号恢复为分号call hello_world(1112); -- 调用存储过程

3、存储过程体:存储过程体包含了在过程调用时必须执行的语句,例如:dml、ddl 语句,if-then-else 和 while-do 语句、声明变量的 declare 语句等。过程体格式:以 begin 开始,以 end 结束(可嵌套)

beginbeginbeginstatements; endend
end

每个嵌套块及其中的每条语句,必须以分号结束,表示过程体结束的 begin-end 块(又叫做复合语句compound statement),则不需要分号。

存储过程参数

1、MySQL存储过程的参数共有三种参数类型 IN,OUT,INOUT,形式如:CREATE PROCEDURE 存储过程名([[IN |OUT |INOUT ] 参数名 数据类形...])

IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)

IN 输入参数举例

# 如果存在存储过程 param1 则删除
drop procedure if exists param1;#创建一个存储过程设置不同类型的传入参数。将语句结束符临时修改为 //
delimiter //
create procedure param1(in id int,in name varchar(16),in birthday date,in price float(6,2))
begin  # 开始
set id = 33; # 可以设置传入变量的值
select id,name,birthday,price from dual;
end // #结束
delimiter ;call param1(1010,'张三','2019/08/08',88.98); # 调用存储过程,传入参数

OUT 输出参数举例

# 如果存在存储过程 param2 则删除
drop procedure if exists param2;# 创建一个存储过程定义输入、输出参数,将语句结束符临时修改为 //
delimiter //
create procedure param2(in sal float(11,2),out yearly_salary float(11,2))
begin  # 开始
set yearly_salary = sal * 12; #改变了变量的值
select yearly_salary from dual;
end // #结束
delimiter ;# 调用存储过程:输出参数也需要传值,且必须是变量,不能是常量
set @yearly_salary = 0; #定义一个全局变量
call param2(8500,@yearly_salary); # 调用存储过程,输出参数使用变量传入select @yearly_salary as '年薪'; # 也可以直接获取全局变量的值

inout 输入输出参数举例

# 如果存在存储过程 param3 则删除
drop procedure if exists param3;#创建一个存储过程,定义输入输出参数,既能当输入参数,也能当输出参数。将语句结束符临时修改为 //
delimiter //
create procedure param3(inout sal float(11,2))
begin  # 开始
set sal = sal * 12; #改变了变量的值
select sal as '年薪' from dual;
end // #结束
delimiter ;# 调用存储过程,同理参数也必须是变量,不能是常量
set @sal = 8500; #定义一个全局变量 @sal
call param3(@sal); # 调用存储过程

注意事项

1)即使存储过程没有参数,也必须在过程名后面写上小括号,否则会报错
2)确保参数的名字不等于列的名字,否则在过程体中,参数名被当做列名来处理
3)输入值使用 in 参数;返回值使用 out 参数;inout 参数尽量少用

存储过程变量

1、局部变量声明一定要放在存储过程体的开始:

格式:DECLARE variable_name [,variable_name...] datatype [DEFAULT value];

datatype 为 MySQL 的数据类型,如: int, float, date,varchar(length) 等

declare v_int int unsigned default 4000000; # 变量名称建议以 'v_' 开头
declare v_numeric number(8,2) default 9.95;
declare v_date date default '1999-12-31';
declare v_datetime datetime default '1999-12-31 23:59:59';
declare v_varchar varchar(255) default 'this will not be padded';

2、变量赋值:SET 变量名 = 表达式值 [,variable_name = expression ...]

4、局部变量在其作用域范围内享有更高的优先权,当执行到 end 时,内部变量消失,此时已经在其作用域外,变量不再可见了。可以通过 out 参数或者将其值指派给会话变量来保存其值。

drop procedure if exists variableAccess; -- 如果已经存在此存储过程,则删除-- 临时改变语句接收符
delimiter //
create procedure variableAccess()   -- 创建存储过程,即使没有参数,也必须有括号
begindeclare x varchar(8) default 'outer'; -- 定义局部变量,设置默认值begin -- begin-end 可以嵌套,变量有作用访问,类似 jsdeclare x varchar(8) default 'inner';set x = '里面';select x from dual;end;select x from dual;
end //
delimiter ;call variableAccess(); #调用存储过程,第一个结果为:'里面'、第二个结果为:'outer'

5、用户变量:在 MySQL 客户端使用用户变量,如:

-- 如下所示都是用户变量
set @x = '中华';
select '名族' into @y;
set @z = 3.14159;
set @m = null;
set @n = '';-- 会话结束后,这些变量也就不存在了。比如关掉客户端工具,重连之后再取值就没有了
select @x as x,@y as y,@z as z,@m as m,@n as n from dual;

用户变量举例

set @name = '张无忌'; # 定义用户变量
drop procedure if exists  userVariables; -- 如果已经存在此存储过程,则删除delimiter //
create procedure userVariables(in id int)
begin
set @name = concat(concat(id,'_'),@name); #为变量赋值,存储过程中可以直接调用用户变量
select id,@name as '姓名' from dual;
end //
delimiter ;call userVariables(1001); # 调用存储过程

6、注意事项:

1、用户变量名虽然可以自定义,但是推荐以 @ 开头
2、滥用用户变量会导致程序难以理解及管理,需要慎用

流程控制语句

 if-then-else 条件语句

简单的条件判断: if – then
二重条件分支: if—then—else
多重条件分支:if—then—elsif—else
drop procedure if exists param6;delimiter //
create procedure param6(in flag int)
beginif flag < 18 then
select '未成年' as result from dual;
else
select '已成年' as result from dual;
end if;if flag < 20 then
select '少年' as result from dual;
elseif flag < 50 then
select '壮年' as result from dual;
else
select '老年' as result from dual;
end if;end //
delimiter ;call param6(17); # 输出 '未成年'、'少年'
call param6(48);  # 输出 '已成年'、'壮年'

when - case 流程语句

drop procedure if exists param7;delimiter //
create procedure param7(in flag varchar(16))
begincase flag
when 'add' thenselect '新增' as flag from dual;
when 'update' thenselect '修改' as flag from dual;
when 'delete' thenselect '删除' as flag from dual;
elseselect '查询'  as flag from dual;
end case;
end //
delimiter ;call param7('add');
call param7('delete');
call param7('xx');

while - do 循环语句:格式:while 条件 do 循环体 end while;

drop procedure if exists param8;delimiter //
create procedure param8()
begin
declare v_count int default 10;
while v_count > 0 doinsert into book_2(title,price,publish,info) values(concat('仙剑奇侠传',v_count),88.45,'2018/08/08','新书上市');set v_count = v_count -1;
end while;
end //
delimiter ;call param8(); -- 调用存储过程

loop 循环语句:loop 循环不需要初始条件,使用 leave 关键字离开循环。

drop procedure if exists param9;delimiter //
create procedure param9()
begin
declare v_count int;
set v_count = 5;
loop_label:loopinsert into book_2(title,price,publish,info) values(concat('速度与激情',v_count),108.42,'2019/08/08','新书上市');set v_count = v_count -1;if v_count <=0 thenleave loop_label;end if;
end loop;
end //
delimiter ;call param9(); -- 调用存储过程

select into 查询并赋值

1、select . into . 查询并赋值数据只能对单个查询结果进行处理,如果 select 查询的结果是多条,则可以借助游标进行遍历。

2、如下所示就是最简单的将单个查询结果,赋值给变量。

drop procedure if exists hello_world2; -- 如果存在指定的存储过程,则删除
#将sql语句的结束符由默认的分号";"临时改为"$$"(可以自定义符号),这样里面才能正常使用分号";",否则会被当做结束符处理
delimiter $$
create procedure hello_world2(in p_deptno int) # 声明存储过程
begin  # 开始DECLARE v_names text DEFAULT '-1'; -- 定义局部变量DECLARE v_sal text DEFAULT '-1'; -- 定义局部变量SELECT ename,sal INTO v_names,v_sal from emp t where t.deptno = p_deptno ORDER BY sal DESC LIMIT 1; -- 查询并赋值SELECT v_names,v_sal from dual; -- SELECT 语句会把结果查询出来
end $$ # 结束
delimiter ;  #将语句的结束符号恢复为分号call hello_world2(2); -- 调用存储过程

2、特别注意:select c1,c2... into v1,v2... where ... 为变量赋值时,如果 where 条件没有查询到值,则变量仍然是自己的默认值或者是上一次的被赋的旧值,而并不会 为null,所以千万不能用这里赋值的变量来充当循环的条件,否则很容易死循环。

存储函数 VS 存储过程

1、存储函数也可以叫自定义函数,比如 mysql 会自带一些函数,如 sun、abs、concat 等等,同时用户也可以自定义函数。

-- 创建存储函数基本语法,没有参数也必须有括号

delimiter $$
create function 存储函数名(参数1 数据类型,参数2 数据类型,…)  returns type
begin
   declare 变量名  类型;
   执行语句;
end $$

delimiter ;  #将语句的结束符号恢复为分号

drop function if exists fun_v1; -- 如果已经存储此函数,则删除delimiter $$ -- 临时改变 sql 语句结束符
create function fun_v1(p_title VARCHAR(56)) returns VARCHAR(56) -- 创建存储函数,必须指定返回值
beginDECLARE v_titles VARCHAR(56) DEFAULT ''; -- 定义局部变量-- 查询赋值,因为只是演示,所以只做简单的查询,结果不能多余条,所以用 limit 1 限制最多取一条SELECT title into v_titles FROM book_2 where title = p_title LIMIT 1;return v_titles; -- 必须返回结果,且只能是变量,不能是常量,比如 return '111',则报错
end $$ -- 结束
delimiter ;  #将语句的结束符号恢复为分号SELECT fun_v1('三国演义'),count(1) from dual; -- 调出存储函数,就如同调用 mysql 自身的函数一样

2、整体来说存储过程与存储函数使用起来基本差不多,其不同的主要如下:

1、名称关键字不同:存储过程是 procedure 关键字存储函数是 function 关键字;
2、参数定义不同:存储过程可以通过 in、out、inout 关键字指定输入输出参数;存储函数的参数默认为输入参数,不用且不能用 in 关键字。

3、返回值不同:存储函数必须有返回值,开头使用 returns type 指明返回的数据类型,函数体中用 return 返回具体的值;存储过程可以没有返回值,也可以通过输出参数返回结果(out,inout)。

4、调用方式不同:存储函数可以在 sql 语句中直接调用;存储过程中无法在 sql 中直接调用,需要通过 call 调用。

5、存储过程中可以调用存储函数,存储函数中无法调用存储过程。


自定义函数实现递归查询

1、递归查询·需求分析

2、Oracle 有自带的函数 start with 可以轻松实现递归查询,而  Mysql 则需要特殊处理才能实现相同的效果,比如借助存储过程或者存储函数,本文使用存储函数,因为 存储函数可以在 sql 语句中直接调用,而且 存储函数可以使用 return 指定返回值。

递归查询·数据准备

递归查询 region 数据准备.sql

自定义函数·向下递归查询

1、这里需要用到 Mysql 的几个函数:find_in_set 查询函数、CONCAT & CONCAT_WS 连接函数、group_concat 分组排序连接

2、存储函数可以在 sql 语句中直接调用,而且可以使用 return 指定返回值,所以如下所示新建一个 存储函数:通过传入根节点id,查询它本身及其下的的所有子孙节点。

-- 将sql语句的结束符由默认的分号";"临时改为"$$"(可以自定义符号),这样里面才能正常使用分号";",否则会被当做结束符处理
delimiter $$
-- 如果已经存在,则先删除掉
-- 注意这里需要用 当前自定义的结束符 $$ 来结束并执行语句,因为本句需要和下边的函数体区分开来执行
drop function if exists recursionDown $$
-- 创建存储函数,声明参数,同时指定 返回值参数类型
create function recursionDown(in_id INT) returns text
-- begin 和 end 中间包围的是函数体,用来写具体的逻辑
begin -- declare 用于声明变量,可以用 default 设置默认值-- 为防止数据量大,拼接的字符串太长,所以使用 text 大文本数据类型declare return_ids text default '';    -- 最终返回的字符串declare temp_ids text; -- 每次循环临时遍历的结果字符串declare total INT DEFAULT 1; -- 每次查询到数据个数set temp_ids = in_id;  -- set 用于为变量赋值 while total > 0  do  -- -- 查询有结果时,才继续循环-- 用 CONCAT_WS 函数把最终结果 和 临时生成的值 用逗号拼接起来-- 设置拼接的 id 列表字符串,因为第一次时 return_ids 值为空,所以开头会有一个 ",",后期去掉即可set return_ids = CONCAT_WS(',', return_ids, temp_ids);-- 查询数据库并赋值-- 以 FIND_IN_SET(pid,tempids)>0 为条件,遍历在 temp_ids 中的所有 pid ,寻找以此为父节点的所有子节点 id-- 通过 GROUP_CONCAT(id) into tempids 把这些子节点 id 都用逗号拼接起来,并覆盖更新 temp_ids select GROUP_CONCAT(id),count(*) into temp_ids,total from region where FIND_IN_SET(pId, temp_ids);  end while;
-- 对返回的id字符串从第2位开始截取,舍弃开头的 "," 符号, LENGTH 函数的索引从 1 开始
set return_ids = SUBSTR(return_ids, 2);
-- 返回最终的数据return return_ids;
end
$$
delimiter ; 

2、调用存储函数,查询指定节点及其下面所有子孙节点数据:

-- 可以简单的测试一下存储函数是否正常,输出值:4,12,13,14,15,16,23,24,25,26
SELECT recursionDown(4) FROM DUAL;
-- 查询 id 为 4 的区域及其所有子孙节点
SELECT * from region t where FIND_IN_SET(id,recursionDown(4));

自定义函数实现·向上递归查询

1、相对于向下递归来说,向上递归比较简单,因为向下递归时,每一层递归一个父节点都对应多个子节点,而向上递归时,每一层递归一个子节点只对应一个父节点,关系比较单一。

2、自定义存储函数如下,实现向上递归查询,通过传入节点id,查询它本身及其上面的所有父节点。:

-- 将sql语句的结束符由默认的分号";"临时改为"$$"(可以自定义符号),这样里面才能正常使用分号";",否则会被当做结束符处理
delimiter $$
-- 如果已经存在,则先删除掉
-- 注意这里需要用 当前自定义的结束符 $$ 来结束并执行语句,因为本句需要和下边的函数体区分开来执行
drop function if exists recursionUp $$
-- 创建存储函数,声明参数,同时指定 返回值参数类型
create function recursionUp(in_id INT) returns text
-- begin 和 end 中间包围的是函数体,用来写具体的逻辑
begin
-- declare 用于声明变量,可以用 default 设置默认值
-- 为防止数据量大,拼接的字符串太长,所以使用 text 大文本数据类型declare return_ids text default ''; -- 最终返回的字符串declare temp_id VARCHAR(56);  -- 每次循环临时遍历的结果字符串declare total INT DEFAULT 1; -- 每次查询到数据个数set temp_id = in_id;  -- set 用于为变量赋值 while total > 0 do  -- 查询有结果时,才继续循环-- 用 CONCAT_WS 函数把最终结果 和 临时生成的值 用逗号拼接起来-- 设置拼接的 id 列表字符串,因为第一次时 return_ids 值为空,所以末尾会有一个 ",",后期去掉即可set return_ids = CONCAT_WS(',', temp_id, return_ids);-- 查询数据库并赋值,因为每个节点都只有一个父节点,所以就说普通的 SELECT INTO 即可select pId,count(*) into temp_id,total from region where id = temp_id ;  end while;
-- 对返回的id字符串从第1位开始截取,舍弃末尾的 "," 符号, LENGTH 函数的索引从 1 开始set return_ids = SUBSTR(return_ids, 1, LENGTH(return_ids) - 1);
-- 返回最终的数据return return_ids;
end
$$
delimiter ;

2、调用存储函数,查询指定节点及其上面所有父节点数据:

SELECT recursionUp(26) from dual; -- 0,1,4,16,26
SELECT * from region t where FIND_IN_SET(id,recursionUp(26));

Mysql 存储过程、存储函数 与 递归查询相关推荐

  1. WebDay18 MySQL存储过程 存储函数 触发器 事务

    MySQL存储过程 存储函数 触发器 事务 一.MySQL存储过程和函数 1.存储过程和函数的概念 2.存储过程和函数的好处 3.存储过程和函数的区别 4.创建存储过程 5.调用存储过程 6.查看存储 ...

  2. Mysql 存储过程 / 存储函数

    目录 0 课程视频 1 基本语法 1.0 作用 ->在数据库中 封装sql语句 -> 复用 -> 减少网络交互 ->可接收参数返回数据 1.1 创建 1.2 调用 1.3 查看 ...

  3. [mysql]存储过程/存储函数

    [Stored Procedure /Stored Function] 存储过程 定义 语法分析: 调试 效果比较 存储函数 应用 语法分析: 两者对比 存储过程和函数的查看.修改.删除 查看 修改 ...

  4. Day463.视图存储过程存储函数 -mysql

    视图 1. 常见的数据库对象 对象 描述 表(TABLE) 表是存储数据的逻辑单元,以行和列的形式存在,列就是字段,行就是记录 数据字典 就是系统表,存放数据库相关信息的表.系统表的数据通常由数据库系 ...

  5. MySQL 案例实战--MySQL数据库 存储过程 存储函数

    MySQL数据库 存储过程 & 存储函数 前言 一.什么是存储过程 & 存储函数 二.存储过程的创建和调用 三.存储函数的创建和调用 前言 本环境是基于 Centos 7.8 系统构建 ...

  6. 视图存储过程存储函数

    文章目录 视图 常见数据库对象 视图概述 为什么使用视图? 视图的理解 创建视图 创建单表视图 创建多表联合视图 基于视图创建视图 查看视图 更新视图的数据 一般情况 不可更新的视图 修改.删除视图 ...

  7. mysql存储过程与函数、触发器、游标、变量等知识点详解

    引言:该文章仅供自己学习整理 mysql执行顺序 语法顺序 写sql的关键字顺序 select [distinct] from join(如left join) on where group by h ...

  8. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表.---查询语句创建表 create table emp as ...

  9. mysql 函数 局部变量_MySQL 存储过程 存储函数 局部变量 游标 概念示例

    一个存储过程是一个可编程的函数,它可以在MySQL中创建并保存.它是由一些SQL语句和一些特殊的控制结构语句组成. 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定的功能时,存储过程是一个非 ...

  10. Mysql学习总结(11)——MySql存储过程与函数

    2019独角兽企业重金招聘Python工程师标准>>> 摘要:存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程 ...

最新文章

  1. 如何基于RocketMQ设计一套全链路消息不丢失方案?
  2. SAP MM 按采购订单查询付款信息的报表?
  3. android wifi定位服务,如何在Android中使用Wifi获取位置?
  4. UNIX(多线程):24---哪些STL容器是线程安全的
  5. 不好意思,00后黑客CEO登场了!
  6. php点击按钮查询,管理界面点击按钮打开查询功能
  7. MapReduce单机提交(待稿)
  8. 数据结构(二)之二叉树
  9. python创建一个字典、其中值为1_从2个列表创建一个字典,其中一个作为键,另一个作为python中的值...
  10. CV领域的实验室及研究组
  11. 【数据可视化应用】绘制风玫瑰图(附Python代码)
  12. l10n i18n vue_带有Vue的更多i18n:格式和后备
  13. 软件测试类型——集成测试
  14. ebs查看服务状态_监控您的卷状态 - Amazon Elastic Compute Cloud
  15. iOS开发 - 中文 iOS/Mac 开发博客列表
  16. 一般服务器监控什么项目,服务器中需要监控的项目
  17. 【Altium designer】快捷键小技巧
  18. C#基础代码笔记(五)
  19. ACM-ICPC 2018 南京赛区网络预赛 I.Skr(Manacher马拉车+Hash哈希/回文树)
  20. 社保卡(深圳)在线激活

热门文章

  1. MyEclipse 10.5与ExtJS 4.1.1自动代码提示
  2. Cheatsheet: 2013 04.01 ~ 04.16
  3. OLAP -- ODS 项目总结 -- BI 中的关键
  4. 山西省计算机商务学校地址,山西计算机等级考试报名地点
  5. 拓端tecdat|R语言MCMC的rstan贝叶斯回归模型和标准线性回归模型比较
  6. 拓端tecdat|R语言解决最优化问题-线性规划(LP)问题
  7. 服务器获取用户信息失败是什么原因,花粉俱乐部获取用户信息失败怎么解决?花粉俱乐部登录失败是什么原因?[多图]...
  8. c语言作业模块化设计具体,C语言程序模块化设计.doc
  9. opencv ret, binary = cv2.threshold(src, 180, 255, )二值化的类型
  10. python使用相对路径创建文件夹