postgresql-存储过程

news2024/11/24 11:58:48

postgresql-存储过程

  • 简述
  • PL/pgSQL 代码块结构
    • 示例
    • 嵌套子块
  • 声明与赋值
  • 控制结构
    • IF 语句
    • CASE 语句
      • 简单case语句
      • 搜索 CASE 语句
    • 循环语句
      • continue
      • while
      • for语句
        • 遍历查询结果
      • foreach
    • 游标
      • 游标传参
  • 错误处理
    • 报告错误和信息
    • 检查断言
  • 捕获异常
  • 自定义函数
    • 重载
    • VARIADIC
  • 存储过程
    • 示例
    • 事务管理

简述

除了标准 SQL 语句之外,PostgreSQL 还支持使用各种过程语言(例如 PL/pgSQL、C、PL/Tcl、
PL/Python、PL/Perl、PL/Java 等 )创建复杂的过程和函数,称为存储过程(Stored Procedure)
和自定义函数(User-Defined Function)。存储过程支持许多过程元素,例如控制结构、循环和
复杂的计算。

使用存储过程带来的好处包括:

  • 减少应用和数据库之间的网络传输。所有的 SQL 语句都存储在数据库服务器中,应用程
    序只需要发送函数调用并获取除了结果,避免了发送多个 SQL 语句并等待结果
  • 提高应用的性能。因为自定义函数和存储过程进行了预编译并存储在数据库服务器中。
  • 可重用性。存储过程和函数的功能可以被多个应用同时使用。
    当然,使用存储过程也可能带来一些问题:
  • 导致软件开发缓慢。因为存储过程需要单独学习,而且很多开发人员并不具备这种技能。
  • 不易进行版本管理和代码调试。
  • 不同数据库管理系统之间无法移植,语法存在较大的差异。
    本文主要介绍 PL/pgSQL 存储过程,它和 Oracle PL/SQL 非常类似,是 PostgreSQL 默认支
    持的存储过程。使用 PL/pgSQL 的原因包括:
  • PL/pgSQL 简单易学,无论是否具有编程基础都能够很快学会。
  • PL/pgSQL 是 PostgreSQL 默认支持的过程语言,PL/pgSQL 开发的自定义函数可以和内置
    函数一样使用。
  • PL/pgSQL 提高了许多强大的功能,例如游标,可以实现复杂的函数。

PL/pgSQL 代码块结构

/*
 * label 是一个可选的代码块标签,可以用于 EXIT 语句退出指定的代码块,或者限定变量的名称
 * DECLARE 是一个可选的声明部分,用于定义变量
 * BEGIN 和 END 之间是代码主体,也就是主要的功能代码;所有的语句都使用分号(;)结束
 * END 之后的分号表示代码块结束。
 * */
[ <<label>> ]
[ DECLARE
 declarations ]
BEGIN
 statements;
 ...
END [ label ];

示例

/*
 * 个匿名块,与此相对的是命名块(也就是存储过程和函数)。其中,DO 语句用于
 * 执行匿名块;我们定义了一个字符串变量 name,然后给它赋值并输出一个信息;RAISE NOTICE用于输出通知消息。
 * $$用于替换单引号(')
 * */
do $$
declare name text;
begin
	 name :='PL/pgSQL';
	 raise notice 'Hello %!',name; 
	
end $$;

在这里插入图片描述

/*
 * $$用于替换单引号('),因为 PL/pgSQL 代码主体必须是字符串文本,
 * 意味着代码中所有的单引号都必须转义(重复写两次)
*/
DO
'DECLARE
 name text;
BEGIN
 name := ''PL/pgSQL'';
 RAISE NOTICE ''Hello %!'', name;
END ';

在这里插入图片描述

嵌套子块

PL/pgSQL 支持代码块的嵌套,也就是将一个代码块嵌入其他代码块的主体中。被嵌套的代
码块被称为子块(subblock),包含子块的代码块被称为外部块(subblock)。子块可以将代码
进行逻辑上的拆分,子块中可以定义与外部块重名的变量,而且在子块内拥有更高的优先级

DO $$
<<outer_block>>
declare
 name text;
BEGIN
 name := 'outer_block';
 RAISE NOTICE 'This is %', name;
 DECLARE
 name text := 'sub_block';
 BEGIN
 RAISE NOTICE 'This is %', name;
 RAISE NOTICE 'The name FROM the outer block is %', outer_block.name;
 END;
 RAISE NOTICE 'This is %', name;

END outer_block $$;

在这里插入图片描述

声明与赋值

/*variable_name 是变量的名称,通常需要指定一个有意义的名称;data_type 是变量的
类型,可以是任何 SQL 数据类型;如果指定了 NOT NULL,必须使用后面的表达式为变量指定
初始值。赋值使用:=*/
variable_name data_type [ NOT NULL ] [ { DEFAULT | := | = } expression ];
DO $$
declare 
id integer;
-- price默认值是0
price numeric(5,2) default 0.0;
name text;
url varchar :='http://mysite.com';
--行类型的变量,可以存储查询语句返回的数据行(数据行的结构要和 employees相同)
myrow employees%rowtype;
-- myfield 的数据类型取决于 empoyees.first_name 字段的定义
myfield employees.first_name%type;
-- myprice 和 price 的类型一致。
myprice price%type;
-- 记录类型变量
-- 记录类型的变量没有预定义的结构,只有当变量被赋值时才确定,而且可以在运行时被改变。
-- 记录类型的变量可以用于任意查询语句或者 FOR 循环变量
arow RECORD;
-- 使用 ALIAS 定义一个变量别名
myprice1 ALIAS FOR myprice;
-- 在定义变量时指定了 CONSTANT 关键字,意味着定义的是常量。常量的值需要在声明时初始化,并且不能修改
PI CONSTANT NUMERIC := 3.14159265;
begin
 id := 1;
 name :='tony';
 raise notice 'id = %',id;
 raise notice 'price = %',price;
 raise notice 'name = %',name;
 raise notice 'url =%',url;
 raise notice '常量PI=%',PI;
end $$;

在这里插入图片描述

控制结构

IF 语句

  • IF … THEN … END IF
  • IF … THEN … ELSE … END IF
  • IF … THEN … ELSIF … THEN … ELSE … END IF
-- 简单的if语句
DO $$
begin
 if 2>1 then
 raise notice '2大于1';
 end if;
end $$;

在这里插入图片描述

-- if ... else
DO $$
begin
 if 2>3 then
 raise notice '2大于3';
 else
   raise notice '2不大于3';
 end if;
end $$;

在这里插入图片描述

-- if ... else 多个条件分支
DO $$
begin
 if 2>3 then
 raise notice '2大于3';
 elseif 2=3 then
 raise notice '2等于3';
 else
   raise notice '2不大于3';
 end if;
end $$;

在这里插入图片描述

CASE 语句

CASE 语句,同样可以根据不同的条件执行不同的分支语句。CASE 语句分为两种:简单 CASE 语句和搜索 CASE 语句。

简单case语句

-- 语法
CASE search-expression
 WHEN expression [, expression [ ... ]] THEN
 statements
 [ WHEN expression [, expression [ ... ]] THEN
 statements
 ... ]
 [ ELSE
 statements ]
END CASE;
-- case 简单语句
DO $$
declare 
	i integer := 1;
begin
 case i
 when 1,2 then
 	raise notice '1或者2';
 when 3 then
    raise notice '3';
 else
   raise notice '其他值';
 end case;
end $$;

在这里插入图片描述

搜索 CASE 语句

-- 语法
CASE
 WHEN boolean-expression THEN
 statements
 [ WHEN boolean-expression THEN
 statements
 ... ]
 [ ELSE
 statements ]
END CASE;
-- 搜索case 简单语句
DO $$
declare 
	i integer := 25;
begin
 case 
  when i between 1 and 10 then
     raise notice '[1-10]';
  when i between 11 and 20 then
     raise notice '[11-20]';
  else
  	raise notice '其他值';
 end case;
end $$;

在这里插入图片描述

循环语句

PostgreSQL 提供 4 种循环执行命令的语句:LOOP、WHILE、FOR 和 FOREACH 循环,以
及循环控制的 EXIT 和 CONTINUE 语句。

-- LOOP 用于定义一个无限循环语句:
-- 一般需要使用 EXIT 或者 RETURN 语句退出循环,label 可以用于 EXIT 或者 CONTINUE 语
-- 句退出或者跳到执行的嵌套循环中
[ <<label>> ]
LOOP
 statements
END LOOP [ label ];
-- loop循环
DO $$
declare 
	i integer := 1;
begin
	loop
	-- exit退出循环
		exit when i  = 5;
		raise notice '第%次执行!',i;
		i :=i+1;
	end loop;
end $$;

在这里插入图片描述

continue

-- loop循环
DO $$
declare 
	i integer := 0;
begin
	loop
	-- exit退出循环
		exit when i = 10;
		i := i+1;
	-- continue 忽略后面的语句,直接进入下一次循环
	-- mod(i,2) =0;偶数跳过执行
		continue when mod(i,2) =0;
		raise notice '第%次执行!',i;
	end loop;
end $$;

在这里插入图片描述

while

-- 语法
-- 当表达式 boolean-expression 的值为真时,循环执行其中的语句;然后重新计算表达式的值,
-- 当表达式的值假时退出循环
[ <<label>> ]
WHILE boolean-expression LOOP
 statements
END LOOP [ label ];
-- while语句
DO $$
declare 
	i integer := 0;
begin
	while i <10 loop
	 i := i+1;
	 raise notice '第%次执行',i;
	end loop;
end $$;

在这里插入图片描述

for语句

-- 语法
-- FOR 循环默认从小到大进行遍历,REVERSE 表示从大到小遍历;BY 用于指定每次的增量,
-- 默认为 1
[ <<label>> ]
FOR name IN [ REVERSE ] expression .. expression [ BY expression ] LOOP
 statements
END LOOP [ label ];
-- for语句
DO $$
begin
	-- 变量 i 不需要提前定义,可以在 FOR 循环内部使用。
	-- by 2每次增量为2
	for i  in  reverse  20..10 by 2 loop
	 raise notice '第%次循环!',i;
	end loop;
end $$;

在这里插入图片描述

-- for语句
DO $$
begin
	-- 变量 i 不需要提前定义,可以在 FOR 循环内部使用。
	-- by 2每次增量为2
	for i in  1..10 by 2 loop
	 raise notice '第%次循环!',i;
	end loop;
end $$;

在这里插入图片描述

遍历查询结果
-- 语法
-- target 可以是一个 RECORD 变量、行变量或者逗号分隔的标量列表。在循环中,target
-- 代表了每次遍历的行数据。
[ <<label>> ]
FOR target IN query LOOP
 statements
END LOOP [ label ];
-- for语句遍历查询结果
DO $$
declare 
emp record;
begin
	for emp in (select * from employees limit 5) loop
		raise notice '员工信息: %, %, %',emp.first_name,emp.last_name,emp.salary;
	end loop;
end $$;

在这里插入图片描述

foreach

-- 语法
[ <<label>> ]
FOREACH target [ SLICE number ] IN ARRAY expression LOOP
 statements
END LOOP [ label ];

如果没有指定 SLICE 或者指定 SLICE 0FOREACH 将会变量数组中的每个元素

do $$
declare
x int;
begin
	foreach x in array (array[[1,2,3],[4,5,6]]) loop
	 	raise notice 'x = %', x;
	end loop;
end $$;

在这里插入图片描述

do $$
declare
x int[];
begin
-- 如果指定了一个正整数的 SLICE,FOREACH 将会变量数组的切片;SLICE 不能大于数组的维度。
	foreach x slice 1 in array (array[[1,2,3],[4,5,6]]) loop
	 	raise notice 'x = %', x;
	end loop;
end $$;

在这里插入图片描述

游标

PL/pgSQL 游标允许我们封装一个查询,然后每次处理结果集中的一条记录。游标可以将大
结果集拆分成许多小的记录,避免内存溢出;另外,我们可以定义一个返回游标引用的函数,然
后调用程序可以基于这个引用处理返回的结果集
使用游标的步骤大体如下:

  1. 声明游标变量
  2. 打开游标
  3. 从游标中获取结果
  4. 判断是否存在更多结果。如果存在,执行第 3 步;否则,执行第 5 步;
  5. 关闭游标
do $$
declare
-- 声明变量类型为record
	emp record;
	emp_cur cursor for select * from employees limit 10;
begin
-- 打开游标
	open emp_cur;
	loop
	-- 获取 fetch
		fetch emp_cur into emp;
		-- 退出循环条件 when not found 没有找到数据
		exit when not found ;
		raise notice '员工信息:% ,%',emp.first_name,emp.last_name;
	end loop;
	-- 关闭游标
	close emp_cur;
end $$;

在这里插入图片描述

游标传参

do $$
declare
-- 声明变量类型为record
	emp record;
	emp_cur cursor(dept_id integer) for select * from employees where department_id = dept_id limit 10;
begin
-- 打开游标
	open emp_cur(90);
	loop
	-- 获取 fetch
		fetch emp_cur into emp;
		-- 退出循环条件 when not found 没有找到数据
		exit when not found ;
		raise notice '员工信息:% ,%',emp.first_name,emp.last_name;
	end loop;
	-- 关闭游标
	close emp_cur;
end $$;

声明了一个游标 emp_cur,并且绑定了一个查询语句,通过一个参数 dept_id 获取指
定部门的员工;然后使用 open 打开游标;接着在循环中使用 fetch 语句获取游标中的记录,
如果没有找到更多数据退出循环语句;变量 emp 用于存储游标中的记录;最后使用 close
语句关闭游标,释放资源
在这里插入图片描述
官网介绍

错误处理

报告错误和信息

PL/pgSQL 提供了 RAISE 语句,用于打印消息或者抛出错误:

RAISE level format;

不同的 level 代表了错误的不同严重级别,包括:

  • DEBUG
  • LOG
  • NOTICE
  • INFO
  • WARNING
  • EXCEPTION
    ,我们经常使用 NOTICE 输出一些信息。如果不指定 level,默认为 EXCEPTION,
    将会抛出异常并且终止代码运行

format 是一个用于提供信息内容的字符串,可以使用百分号(%)占位符接收参数的值, 两
个连写的百分号(%%)表示输出百分号自身

DO $$
BEGIN
 RAISE DEBUG 'This is a debug text.';
 RAISE INFO 'This is an information.';
 RAISE LOG 'This is a log.';
 RAISE WARNING 'This is a warning at %', now();
 RAISE NOTICE 'This is a notice %%';
END $$;

从结果可以看出,并非所有的消息都会打印到客户端和服务器日志中。这个可以通过配置参
数 client_min_messages和 log_min_messages 进行设置。
在这里插入图片描述
对于 EXCEPTION 级别的错误,可以支持额外的选项:

RAISE [ EXCEPTION ] format USING option = expression [, ... ];
RAISE [ EXCEPTION ] condition_name USING option = expression [, ... ];
RAISE [ EXCEPTION ] SQLSTATE 'sqlstate' USING option = expression [, ... ];
RAISE [ EXCEPTION ] USING option = expression [, ... ];

其中,option 可以是以下选项:

  • MESSAGE,设置错误消息。如果 RAISE 语句中已经包含了 format 字符串,不能再使用该选项。
  • DETAIL,指定错误详细信息。
  • HINT,设置一个提示信息
  • ERRCODE,指定一个错误码(SQLSTATE)。可以是文档中的条件名称或者五个字符组成的SQLSTATE 代码。
  • COLUMN、CONSTRAINT、DATATYPE、TABLE、SCHEMA,返回相关对象的名称。
do $$
begin
	raise info 'This s an info.';
	raise debug 'This s an debug.';
	raise warning 'This s an warning.';
end $$;

在这里插入图片描述

检查断言

PL/pgSQL 提供了 ASSERT 语句,用于调试存储过程和函数:

ASSERT condition [ , message ];

其中,condition 是一个布尔表达式;如果它的结果为真,ASSERT 通过;如果结果为假或者
NULL,将会抛出 ASSERT_FAILURE 异常。message 用于提供额外的错误信息,默认为“assertion
failed”。例如

DO $$
DECLARE
 i integer := 1;
BEGIN
 ASSERT i = 0, 'i 的初始值应该为 0!';
END $$;

在这里插入图片描述
ASSERT 只适用于代码调试;输出错误信息使用 RAISE 语句。

捕获异常

默认情况下,PL/pgSQL 遇到错误时会终止代码执行,同时撤销事务。我们也可以在代码块
中使用 EXCEPTION 捕获错误并继续事务

[ <<label>> ]
[ DECLARE
 declarations ]
BEGIN
 statements
EXCEPTION
 WHEN condition [ OR condition ... ] THEN
 handler_statements
 [ WHEN condition [ OR condition ... ] THEN
 handler_statements
 ... ]
END;

如果代码执行出错,程序将会进入 EXCEPTION 模块;依次匹配 condition,找到第一个匹
配的分支并执行相应的 handler_statements;如果没有找到任何匹配的分支,继续抛出错误

DO $$
DECLARE
 i integer := 1;
BEGIN
 i := i / 0;
EXCEPTION
 WHEN division_by_zero THEN
 RAISE NOTICE '除零错误!';
 WHEN OTHERS THEN
 RAISE NOTICE '其他错误!';
END $$;

在这里插入图片描述
OTHERS 用于捕获未指定的错误类型。
PL/pgSQL 还提供了捕获详细错误信息的 GET STACKED DIAGNOSTICS 语句,具体可以参
考官方文档

自定义函数

创建一个自定义的 PL/pgSQL 函数,可以使用 CREATE FUNCTION 语句

CREATE [ OR REPLACE ] FUNCTION
 name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ]
[, ...] ] )
 RETURNS rettype
AS $$
DECLARE
 declarations
BEGIN
 statements;
 ...
END; $$
LANGUAGE plpgsql;

CREATE 表示创建函数,
OR REPLACE 表示替换函数定义;
name 是函数名;括号内是参数,多个参数使用逗号分隔;
argmode 可以是 IN(输入)、OUT(输出)、
INOUT(输入输出)或者 VARIADIC(数量可变),默认为 IN;
argname 是参数名称;argtype 是参数的类型;
default_expr是参数的默认值;rettype 是返回数据的类型;
AS 后面是函数的定义,和上文中的匿名块相同;
最后,LANGUAGE 指定函数实现的语言,也可以是其他过程语言

-- 函数创建
create or replace function get_emp_count(p_deptid integer)
returns integer
as $$
declare 
	ln_count integer;
begin 
	if p_deptid <= 0 then
		raise exception '部门编号不能小于等于0!p_deptid:%',p_deptid;
	end if;
	select count(*) into ln_count
	from employees
	where department_id  = p_deptid;	
	return ln_count;
end $$
language plpgsql;
-- 函数使用
select get_emp_count(90) as total;

在这里插入图片描述

select get_emp_count(-1) as total;

在这里插入图片描述

重载

PL/pgSQL 函数支持重载(Overloading),也就是相同的函数名具有不同的函数参数

CREATE OR REPLACE FUNCTION public.get_emp_count(p_deptid integer,p_hire_date varchar)
 RETURNS integer
 LANGUAGE plpgsql
AS $function$
declare 
	ln_count integer;
begin 
	if p_deptid <= 0 then
		raise exception '部门编号不能小于等于0!p_deptid:%',p_deptid;
	end if;
	select count(*) into ln_count
	from employees
	where department_id  = p_deptid
	and hire_date > p_hire_date;
	return ln_count;
end $function$
;

在这里插入图片描述

VARIADIC

VARIADIC:参数的数量是多个,可变的

-- 数组 nums的下标索引的产生,1维数组
-- generate_subscripts(nums,1)
create or replace function sum_num(variadic nums numeric[])
returns numeric
as $$
declare 
	total numeric;
begin 
	select sum(nums[i]) into total
	-- t(i)返回的下标索引变量为i
	from generate_subscripts(nums,1) t(i);
	return total;
end $$
language plpgsql;

-- 数组内元素为1和2的和
-- 参数 nums 是一个数组,可以传入任意多个参数;然后计算它们的和值
select sum_num(1,2);

在这里插入图片描述

存储过程

PostgreSQL 11 增加了存储过程,使用 CREATE PROCEDURE 语句创建:

CREATE [ OR REPLACE ] PROCEDURE
 name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ]
[, ...] ] )
AS $$
DECLARE
 declarations
BEGIN
 statements;
 ...
END; $$
LANGUAGE plpgsql;
-- 调用存储过程
call 过程名(参数1,参数2...);

示例

create or replace procedure transfer(p_from integer,p_to integer,p_amount numeric)
as $$
declare 
	l_count integer;
begin 
	select count(*) into l_count
	from accounts
	where id = p_from;
	if l_count = 0 then
		raise exception '原账户不存在:%',p_from;
	end if;

	select count(*) into l_count
	from accounts
	where id = p_to;
	if l_count = 0 then
		raise exception '目标账户不存在:%',p_to;
	end if;

	if p_amount < 0 then
		raise exception '转账金额错误:%',p_amount;
	end if;
	-- 1.扣款
	update accounts 
	set balance = balance - p_amount
	where id = p_from;

	-- 2.存款
	update accounts 
	set balance = balance + p_amount
	where id = p_to;
	
	-- 3.记录流水
end $$
language plpgsql;

-- 调用存储过程
call public.transfer(1,2,3000);

select * from public.accounts a ;

在这里插入图片描述

事务管理

在存储过程内部,可以使用 COMMIT 或者 ROLLBACK 语句提交或者回滚事务

create table test2(col integer);
-- 创建存储过程
create or replace procedure transaction_test()
as $$ 
begin 
	for i in 0..10 loop
		insert into test2 values(i);
		--mod 求余
		-- 偶数提交
		if mod(i,2) = 0 then
			commit;
		 else
		 -- 奇数回滚
		 	rollback;
		end if;
	end loop;
	
end $$
language plpgsql;

-- 调用存储过程
call transaction_test();
select * from test2;

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1034696.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Opencv-python去图标与水印方案实践

RGB色彩模式是工业界的一种颜色标准&#xff0c;是通过对红&#xff08;R&#xff09;、绿&#xff08;G&#xff09;、蓝&#xff08;B&#xff09;三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的&#xff0c;RGB即是代表红、绿、蓝三个通道的颜色&#xff…

【虚拟化】虚拟机vcpu绑核物理机

文章目录 一、NUMA二、虚拟机xml配置解析 参考文章 第一篇&#xff1a;KVM虚拟化CPU技术总结 第二篇&#xff1a;虚机cpu和mem的配置&#xff08;cputune和numatune&#xff09; 第三篇&#xff1a;libvirt 中cpu, numa 的配置 第四篇&#xff1a;如何提高虚拟机性能&#xff1…

最新研究综述——探索基础模型中的“幻觉”现象

深度学习自然语言处理 原创作者&#xff1a;Winnie “幻觉”问题即模型生成的内容可能包含虚构的信息。它不仅在大语言模型(LLMs)中存在&#xff0c;也存在于图像、视频和音频等其他一系列基础模型中。 针对这一问题&#xff0c;一篇最近的综述论文对目前所有基础模型的“幻觉”…

树、二叉树、堆及其应用(堆排序、top-k问题)

目录 树的概念与结构 概念&#xff1a; 与树相关的概念: 树的表示&#xff1a; 二叉树 概念&#xff1a; 特殊的二叉树&#xff1a; 二叉树性质&#xff1a; 二叉树的存储结构&#xff1a; 堆 堆的概念: 堆的实现&#xff1a; 堆的创建&#xff1a; 堆的插入&#xff1a; 堆的删…

linux、windows的pip一键永久换源[清华源、中科大、豆瓣、阿里云]

前言 本文概述&#xff1a;linux、windows操作系统一键将pip下载源永久设置为国内下载源&#xff0c;避免了使用临时源需要到处找镜像地址的麻烦。 作者介绍&#xff1a;作者本人是一名人工智能炼丹师&#xff0c;目前在实验室主要研究的方向为生成式模型&#xff0c;对其它方向…

stm32_标准库_中断_按键点灯|蜂鸣器

配置流程 需要对AFIO、EXTI、NVIC、GPIOB进行配置形成通路将中断连接至CPU APB2总线连接的寄存器 LED灯代码 #include "stm32f10x.h" // Device header #include "Delay.h"GPIO_InitTypeDef GIPO_InitStruct;//结构体配置GPIO EXTI_InitTypeDef EXTI_…

海普纯化产品-多肽固相合成载体

#海普纯化产品-多肽固相合成载体 多肽固相合成法被广泛应用于多肽和蛋白质的研究领域&#xff0c;特别是短多肽的合成&#xff0c;随着全新化学结构的新药开发难度加大&#xff0c;投入费用逐年增高&#xff0c;多肽类药物的开发逐渐成为医药领域的新热点。 多肽类药物合成技术…

【Redis】专栏合集,从入门到高级业务场景实战

作者简介 目录 1.概述 2.下载安装 3.基础操作 4.集群 5.实战场景 1.概述 诸如数mysql、Oracle之类的关系型数据库或者NTFS、HDFS之类的文件存储系统&#xff0c;其本质上数据都是存在磁盘上的。这是现代计算机体系架构的架构所决定的&#xff0c;要持久化存储的数据都会落…

一文带你实现从PDF到Word文件的相互转换

一文带你实现从PDF到Word文件的相互转换 01. 前期准备 模块安装 pip install pdf2docx or使用国内镜像源进行安装&#xff08;清华的镜像源&#xff09; pip install pdf2docx -i https://pypi.tuna.tsinghua.edu.cn/simple 02. 模块介绍 pdf2docx是一个Python模块&#xff0…

SpringBoot源码解析: 从手写一个简易版SpringBoot开始

IDE&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 Maven版本&#xff1a;apache-maven-3.6.3 文章目录 真正的SpringBoot手写一个简易版的springboot一. 准备1.1 准备自定义的springboot模块1.2 准备用户模块User 二. 运行测试2.1 第一次运…

如何快速上传批量剪辑的素材?附素材水印、字幕去除教程

想要快速上传网络素材&#xff0c;大家可以使用超级编导批量剪辑软件。 首先进入超级编导官网&#xff0c;免费下载超级编导超级编导软件&#xff0c;可以在官网中添加产品顾问&#xff0c;获取试用账号&#xff0c;登录即可开始使用。 超级编导支持批量上传URL链接到后台&…

Manifest merger failed

编译报错&#xff1a;Manifest merger failed with multiple errors 定位编译错误&#xff1a;java.lang.RuntimeException: Manifest merger failed with multiple errors 近日&#xff0c;项目中需要引入一个module。在成功导入后&#xff0c;添加依赖到主模块上&#xff0c…

【RocketMQ】(六)顺序消息实现原理

全局有序 在RocketMQ中&#xff0c;如果使消息全局有序&#xff0c;可以为Topic设置一个消息队列&#xff0c;使用一个生产者单线程发送数据&#xff0c;消费者端也使用单线程进行消费&#xff0c;从而保证消息的全局有序&#xff0c;但是这种方式效率低&#xff0c;一般不使用…

955. 删列造序 II;1838. 最高频元素的频数;1392. 最长快乐前缀

955. 删列造序 II 核心思想&#xff1a;我们可以按照一行一行排列strs&#xff0c;删除索引序列就代表删除某一列&#xff0c;那么我们如何判断一列是否应该删除呢&#xff0c;我们可以从反方向思考&#xff0c;应该保留那些列呢&#xff1f;从第一列开始&#xff0c;如果它不…

WebGIS面试题(浙江中海达)

1、Cesium中有几种拾取坐标的方式&#xff0c;分别介绍 Cesium是一个用于创建3D地球和地理空间应用的JavaScript库。在Cesium中&#xff0c;你可以使用不同的方式来拾取坐标&#xff0c;以便与地球或地图上的对象进行交互。以下是Cesium中几种常见的拾取坐标的方式&#xff1a…

jdk21(最新版) download 配置(linux window mac)

download 直达链接 jdk21,17 # wget https://download.oracle.com/java/20/latest/jdk-21_linux-x64_bin.deb # 选择你需要的包类似格式替换包的名称就可以实现终端下载jdk下载登录/oracle账号 下载jdk有可能存在要求登录帐号的情况 # 好心人的帐号 账号&#xff1a; 599…

C语言内存函数的使用、剖析及模拟实现

目录 一、内存拷贝函数——memcpy 1.函数声明&#xff1a; 注意&#xff1a; 2.函数使用用例&#xff1a; 3.memcpy函数的模拟实现&#xff1a; 二、内存拷贝函数2——memmove 1.函数声明&#xff1a; 2.memmove函数的模拟实现 三、内存比较函数——memcmp 1.函数声明…

01_docker镜像管理:80分钟一口气学完docker+k8s!带你掌握docker+k8s所有核心知识点,全程干货,无废话!

docker镜像的实际使用学习 开发过程中&#xff0c;需要安装很多三方工具&#xff0c;比如etcd、kafka、mysql、nginx等等 1、下载安装Docker工具。 2、获取该软件的Docker镜像&#xff08;基本上&#xff0c;都能搜索到核实的镜像&#xff09;&#xff0c;下载镜像nginx镜像…

浏览器基本原理

1、浏览器内部组成 我们看到浏览器主要包括&#xff1a; 1个浏览器主进程&#xff1a; 主要负责界面显示&#xff0c;用户交互&#xff0c;子进程管理多个渲染进程&#xff1a;一般浏览器会为每个Tab标签窗口创建一个渲染进程&#xff0c;主要负责将html&#xff0c;css&#…

经典网络(一) AlexNet逐层解析 | 代码、可视化、参数查看!

文章目录 1 回顾2 AlexNet的重要性3 AlexNet解析3.1 结构3.1.1 CONV13.1.2 Max Pool13.1.3 NORM13.1.4 CONV23.1.5 Max Pool23.1.6 CONV3 CONV43.1.7 CONV53.1.8 Max Pool33.1.9 FC1 FC2 FC3 3.2 AlexNet使用到的技巧3.3 可视化3.4 代码实现模拟3.4.1 查看每一层输入输出3.4.2 …