阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

PL/SQL编程基础简介及实践

435次阅读
没有评论

共计 11395 个字符,预计需要花费 29 分钟才能阅读完成。

PL/SQL 编程基础简介及实践

1、开始(p1~p2)
2、背景介绍(p3)
3、特性优点(p4~p5)
4、使用说明(p6)
5、语法结构(p7)
6、命名参考(p8~p9)
7、复合类型(p10~p16)
8、运算符(p17)
9、流程控制语句(p18~p28)
10、异常和错误处理(p29~32)
11、函数与存储过程(p33~p41)
12、结束(p42)

1、背景介绍
1、PL/SQL 是一种程序语言,叫做过程化 SQL 语言(Procedural Language/SQL)。PL/SQL 是 Oracle 数据库对 SQL 语句的扩展。在普通 SQL 语句的使用上增加了编程语言的特点,所以 PL/SQL 就是把数据操作和查询语句组织在 PL/SQL 代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能或者计算程序语言。
2、PL/SQL 类别:数据库引擎、工具引擎(嵌入到其他语言如:C、JAVA)。
3、PL/SQL 包括:编程结构、语法和逻辑机制,工具引擎还增加了支持(如 ORACLE Forms)的句法。

3、特性优点
1、提高运行效率
 可以将大量数据的处理放在服务端,减少数据在网络上的传输时间。
2、客户端
 可以在客服端执行本地的 PL/SQL,或通过向服务器发送 SQL 命令或激活服务器端来运行 PL/SQL 程序。
3、支持过程化
 可嵌入 SQL 语句,及使用各种类型的条件分支语句和循环语句。
4、支持模块化
 可通过使用程序包、过程、函数、触发器等将各类处理逻辑分开,方便管理。
5、支持处理异常
 可通过使用自定义异常或使用内置的异常,来处理代码中可能发生的异常,提高代码的健壮性。
6、提供大量内置程序包
 可使用 Oralce 内置程序包,从而更加方便的处理数据及业务流程。
7、其他:更好的性能、可移植性和兼容性、可维护性、易用性等。

4、使用说明
1、允许的语句:
 可使用 INSERT、UPDATE、DELETE、SELECT INTO、COMMIT、ROLLBACK、SAVEPOINT 语句,在 PL/SQL 中需要以动态的方式使用 DDL(CREATE、ALTER、DROP、TRUNCATE) 语句。
2、运行的方式:
PL/SQL 可在 SQL*PLUS、高级语言、ORACLE 开发工具中使用(如:SQL Developer 或 Procedure Builder 等。
3、运行的过程:
PL/SQL 程序的运行是通过 Oracle 中的一个引擎来进行的。这个引擎可能在 Oracle 服务器端,也可能在 Oracle 客户端。引擎执行 PL/SQL 中的过程性语句,然后将 SQL 语句发送给数据库服务器来执行,再将结果返回给执行端。

5、语法结构
1、PL/SQL 组成:由 3 部分组成:声明部分、执行部分、异常处理部分。
2、结构说明:
– 声明部分:声明用到的常量、类型、游标、局部的存储过程、函数
declare

– 执行部分:具体的 SQL 语句,包含处理的流程。
begin

– 异常部分:针对异常处理的 SQL 语句。
exception

end;

6、命名参考
1) 标识符:
 不区分大小写、不能包含减号 (-)、首字符必须为字母,不能是 SQL 保留字、不能超过 30 个字符。
2) 命名参考:
程序变量:v_name v_orderId 程序常量:c_name c_cityId 游标变量:cursor_name cursor_storeId 异常标示符:e_name e_agentId 记录类型:name_record test_city_record 绑定变量:g_name g_userId 错误:e_error
3)数据类型:(5 大类)
1 字符类型(CHAR、NCHAR、VARCHAR、VARCHAR2、NVARCHAR2)、2 数字类型(NUMBER、INTEGER、BINARY_FLOAT、BINARY_DOUBLE)、3 时间类型(DATE、TIMESTAMP、INTERVAL YEAR、INTERVAL DAY)、4 大对象类型(BLOB、CLOB、BFILE、NCLOB)、5 其他类型(LONG、RAW LONG RAW、ROWID、UROWID)。

bfile(moive):存放大的二进制数据对象,表中只存放文件的目录。大小 <=4GB
blob(photo):存放大的二进制数据对象的位置,位置指向二进制对象的数据块。大小 <=4GB
clob(book):存放大的字符数据对象的位置,位置指向字符的数据块。大小 <=4GB
nclob(ncahr 字符数据):存放大的 nchar 字符数据对象的位置,位置指向 nchar 字符的数据块。大小 <=4GB
4)变量声明
v_flag boolean not null default false;
identifier [constant] datetype [not null] [:=value|default value |expression]
identifier:变量名称
datetype:变量类型
:=value 变量或常量的初始值
default value:默认值
expression 为函数 其他变量、文本值等
5) 注释
– 单行注释 /* 多行注释 */

7、复合类型介绍
1、复合类型:(记录类型、数组类型、一维表类型、二维表类型)
1) 记录类型:记录类型类似于 c 语言中的结构数据类型,它把逻辑相关的、分离的、基本数据类型的变量组成一个整体存储起来,它必须包括至少一个标量型或 record 数据类型的成员,称作 pl/sql record 的域 (field),其作用是存放互不相同但逻辑相关的信息。在使用记录数据类型变量时,需要先在声明部分先定义记录的组成、记录的变量,然后在执行部分引用该记录变量本身或其中的成员。
type record_name is record(
 v1 data_type1 [not null] [:= default_value],
 …
 vn data_typen [not null] [:= default_value] );
2) 说明:%type:表示变量的数据类型与表对应的列的类型一致
%rowtype:表示变量的数据类型与表对应的所有列的类型一致
可以不用知道列的数据类型、当列的数据类型改变后,修改 pl/sql 代码
被赋值的变量与 select 中的列名要一一对应。

declare
 id varchar2(32); – 证件号码
province varchar2(10); - 省份编号
city varchar2(10); – 城市编号
district varchar2(10); – 区域编号

– 定义省份、城市、区域编号记录表对象
type base_info_type is record(
 province base_info.province%type,
 city base_info.city%type,
 district base_info.district%type);

sp_record base_info_type;

begin
 id := sys_guid();
– 查询出关联的省份编号、城市编号、区域编号信息
select province, city, district
 into sp_record
 from base_info bi
 where bi.store_id = ‘storeId ′ ;−−更新省份编号、城市编号、区域编号信息 updatetest h ousefohsetfoh.province=sp r ecord.province,foh.city=sp r ecord.city,foh.region=sp r ecord.district,foh.address= ′ 商务路 ′ ||lpad(abs(dbms r andom.random),4,dbms r andom.string(′ x ′ ,2))wherefoh.order i d= ′  storeId′;−−更新省份编号、城市编号、区域编号信息 updatetesthousefohsetfoh.province=sprecord.province,foh.city=sprecord.city,foh.region=sprecord.district,foh.address=′商务路′||lpad(abs(dbmsrandom.random),4,dbmsrandom.string(′x′,2))wherefoh.orderid=′{orderId}’;
 commit;
end;

2)数组类型:具有相同数据类型的记录的集合。
type array_name is varray(size) of elementType [not null];
array_name:数组类型名称 size:元素的大小 elementType:数据类型
– 位置从 1 开始
declare
 type city_array is varray(3) of varchar2(10);
 v_city_array city_array;
begin
 v_city_array := city_array(‘ 北京市 ’, ‘ 上海市 ’, ‘ 深圳市 ’);
dbms_output.put_line(‘ 第 3 个城市名称 =’ || v_city_array(3));
end;

1、绑定变量:使用 variable 来定义
variable return_cityId number;

SQL> variable returnValue number;
SQL> begin
 2 select 3*6 into :returnValue from dual;
 3 end;
 4 /
PL/SQL procedure successfully completed
returnValue
———
18
SQL> print returnValue;
returnValue
———

3)表类型:定义记录表(或索引表)数据类型。它与记录类型相似,但它是对记录类型的扩展。它可以处理多行记录,类似于高级中的二维数组,使得可以在 pl/sql 中模仿其他数据库中的表。
type table is table of elementType [not null]
index by [binary_integer | pls_integer |varray2]
关键字 index by 表示创建一个主键索引,以便引用记录表变量中的特定行
– 按一维数组使用记录表的示例
declare
 type city_table is table of varchar2(20) index by binary_integer;
 v_city_table city_table;
begin
 v_city_table(1) := ‘ 北京市 ‘;
v_city_table(2) := ‘ 深圳市 ‘;
dbms_output.put_line(‘ 第 2 个城市名称 = ‘ || v_city_table(2));
end;

– 按二维数组使用记录表的示例
declare
type bse_city_table is table of test_city%rowtype index by binary_integer;
v_bse_city_table bse_city_table;
begin
 select city_id, city_name
 into v_bse_city_table(1).city_id,v_bse_city_table(1).city_name
 from test_city bc
 where bc.p_city_id = ‘020’
 and rownum = 1;
 select city_id, city_name
 into v_bse_city_table(2).city_id,v_bse_city_table(2).city_name
 from test_city bc
 where bc.p_city_id = ‘0755’
 and rownum = 1;
 dbms_output.put_line(‘ 记录 1 中区域编号 =’ || v_bse_city_table(1).city_id ||
 ‘_记录 1 中区域名称 =’ || v_bse_city_table(1).city_name);
 dbms_output.put_line(‘ 记录 1 中区域编号 =’ || v_bse_city_table(2).city_id ||
 ‘_记录 1 中区域名称 =’ || v_bse_city_table(2).city_name);
end;

8、运算符
1、关系运算符:
=、<> ~= != ^=、>、>=、<、<=
2、一般运算符:
+、-、*、/、:=(赋值号)、..(范围运算符)、||、=>(关系号)
3、逻辑运算符:
is null、in、and、or、not、between and
4、注意事项:
1) 变量赋值:先声明再赋值。
v_storePhone varchar2(11); – 手机号码
v_storePhone := ‘158’ || lpad(abs(dbms_random.random), 8, 0);
2)null+ 数字 为 null,null|| 字符串 为字符串
3)boolean 类型的值只能取 true false null3 个值

9、流程控制语句
1) 语句分类:控制语句 (IF)、循环语句(LOOP、EXIT) 顺序语句(GOTO、NULL)
2) 结构说明
a)
IF < 布尔表达式 > THEN
 PL/SQL 语句和 SQL 语句
END IF;
b)
IF < 布尔表达式 > THEN
 PL/SQL 语句和 SQL 语句
ELSE
其他语句
END IF;

IF < 布尔表达式 1 > THEN
 PL/SQL 语句和 SQL 语句 1
ELSIF < 布尔表达式 2 > THEN
其他语句 1
ELSIF < 布尔表达式 3 > THEN
其他语句 2
ELSE
其他语句 3
END IF;

IF 语句示例
declare
 v_roleId varchar2(20); – 角色编号
v_result varchar2(60);
begin
 for vv in (select distinct su.role_id
 from test_ur su
 where su.role_id in (‘project_sz’,
 ‘project_bj’,
 ‘project_gz’,
 ‘project_sh’)) loop
 if (vv.role_id = ‘project_sz’) then
 v_result := vv.role_id || ‘_表示的是_角色 1 ’;
 dbms_output.put_line(v_result);
 elsif (vv.role_id = ‘project_sh’) then
 v_result := vv.role_id || ‘_表示的是_角色 2 ’;
 dbms_output.put_line(v_result);

elsif (vv.role_id = ‘project_gz’) then
 v_result := vv.role_id || ‘_表示的是_角色 3 ’;
 dbms_output.put_line(v_result);
elsif (vv.role_id = ‘project_bj’) then
 v_result := vv.role_id || ‘_表示的是_角色 4 ’;
 dbms_output.put_line(v_result);
else
 v_result := vv.role_id || ‘_表示的是_未知角色 ’;
dbms_output.put_line(v_result);
 end if;
end loop;
 dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) || ‘ 处理成功 ’);
end;

loop 语句示例
loop
执行的语句
exit when < 条件语句 >; – 当条件为满足时,退出循环
end loop;
–loop 示例
declare
 v_count number;
 v_time number;
begin
 v_count := 0;
 loop
 v_count := v_count + 1;
 dbms_output.put_line(‘ 第 ’ || v_count || ‘ 次循环 ’);
exit when(v_count > 3);
 end loop;
end;

while 语句示例
while < 布尔表达式 > loop
执行的语句
end loop;
–while 示例
declare
 v_count number;
 v_time number;
begin
 v_count := 0;
 while (v_count < 3) loop
 v_count := v_count + 1;
 dbms_output.put_line(‘ 第 ’ || v_count || ‘ 次循环 ’);
end loop;
end;

for 循环语句示例
for 循环计数器 in [reverse] 下限 .. 上限 loop
执行的语句
end loop;
每循环 1 次,计数器自动加 1,加上 reverse 关键字则自动减 1,必须为从小到大的整数,可以使用 exit when 退出循环
declare
 v_count number;
begin
 v_count := 8;
 for i in 1 .. v_count loop
 dbms_output.put_line(‘ 第 ’ || i || ‘ 次循环 ’);
exit when(i > 3);
 end loop;
end;

case when 循环语法
– 语法 1
case 条件表达式
when 表达式结果 1 then
语句 1
 …
 when 表达式结果 n then
语句 n
 [else 表达式结果]
end case;

– 语法 2
case 条件表达式
when 表达式结果 1 then
语句 1
 …
 when 表达式结果 n then
语句 n
 [else 语句]
end case;

case when 语句示例
select trunc(tur.created_date, ‘dd’),
 count(case
 when tur.role_id = ‘project_sh’ then
 1
 else
 null
 end) as 角色 1,
 count(case
 when tur.role_id = ‘project_gz’ then
 1
 else
 null
 end) as 角色 2,

count(case
 when tur.role_id = ‘project_sz’ then
 1
 else
 null
 end) as 角色 3,
 from test_ur tur
 group by trunc(tur.created_date, ‘dd’)
 order by trunc(tur.created_date, ‘dd’) desc;

5)goto 无条件跳转到指定标签所在部分
goto lable

<<lable>>
6)null 不执行任何操作的语句

10、异常和错误处理
1、Oracle 提供异常情况(exception) 和异常处理 (exception handler) 来实现对错误的处理。
2、异常情况 (exception) 指在正常执行过程中未预料的事件,程序块的异常处理预定义错误和自定义错误,运行 PL/SQL 块时一旦产生异常而没有指出如何处理时,就会自动终止整个 PL/SQL 块的运行。
3、异常错误分为 3 类 (预定义错误、非预定义错误、自定义错误)
预定义错误:无需在程序中定义,由 Oracle 自动引发,共 24 个,直接在异常中使用。
非预定义错误:需在程序中定义,由 Oracle 自动引发
自定义错误:需在程序中定义,且需在程序中引发。

1)预定义错误
exception
 when No_data_found then
dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) ||’execute failure’);
2) 非预定义错误
– 定义错误
< 异常情况 > exception;
– 与标准的 Oracle 错误关联
pragma exception_init(< 异常情况 >,< 异常代码 >);
– 处理错误
exception
 when foundError then
dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) ||’execute failure’);

3)自定义错误
– 定义错误
< 异常情况 > exception;
– 通过 raise 引发错误
raise 异常情况
– 处理错误
exception
 when raiseError then
dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) ||’execute failure’);

4)修改自定义错误消息
dbms_standard.raise_application_error(errorNumber,errorCode,errorsMsg);
errorNumber:错误编号:-20000~-20999
errorMsg:提示的错误消息(<2014KB)
errorFlag:true 将错误添加到错误列表,false 替换当前的错误列表,缺省为 false
dbms_standard.raise_application_error(-20001,’ 错误的消息 ’);
记录错误关键字:
sqlcode:错误编号 如:6502
sqlerrm:错误消息 如:ORA-06502: PL/SQL: 数字或值错误 : character string buffer too small (<500KB)
dbms_output.put_line(‘ 错误编号_’ || sqlcode || ‘_错误信息_’ || sqlerrm);
when others exception 必须放在异常处理部分的最后面,以作为缺省异常的处理,when … exception 没有数量限制,没被处理的异常将检测调用异常的程序,并将异常传播到外面,异常被处理并被解决或达到最外层循环后停止,在声明部分的抛出的异常将控制转到上一层部分。

11、函数和存储过程
1) 函数:
create [or replace] function functionName
(arg1 [{in out in out}] type1 default value1,

argn [{in out in out}] typen default valuen)
[authid definer|current_user]– 权限控制
return resultType
{is | as}
变量的声明部分
begin
执行语句部分
return expression
exception
异常处理部分
end functionName;
in out in out– 表示参数的模式,有入参、出参,不写的话默认为入参,其中只能为入参设置默认值,当调用函数后,不指定入参的值时,就使用入参的默认值。
create or replace function funTranslateRole(v_roleId in varchar2,
 v_result out varchar2)
 return varchar2
 is
 role_id varchar2(20); – 角色编号
begin
 role_id := v_roleId;
 if (role_id = ‘project_sz’) then
 v_result := role_id || ‘_表示的是_客服 ’;
else
 v_result := role_id || ‘_表示的是_未知 ’;
end if;
 return v_result;
 dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) || ‘ 处理成功 ’);
exception
 when others then
 dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) || ‘ 处理失败 ’);
end funTranslateRole;

1)位置表示法
–argvalue1,argvalue2,..argvaluen
funTranslateRole(v_roleId,v_result)

2)名称表示法
– 这种方式与参数的顺序没关系,v_result、v_roleId 与函数中的参数名称需一致
declare
 roleId varchar2(20); – 角色编号
vresult varchar2(60); – 角色的结果
begin
 roleId := ‘project_bj’;
 vresult := funTranslateRole(v_result => vresult, v_roleId => roleId);
 dbms_output.put_line(vresult);
end;

3)组合 (名称表示 + 位置表示法)
如果前一个参数用名称表示法,则后面的所有参数都要用名称表示法。
– 调用方式
declare
 v_roleId varchar2(20); – 角色编号
v_result varchar2(60); – 角色的结果
begin
 v_roleId := ‘project_bj’;
 v_result := funTranslateRole(v_roleId,v_result);
 dbms_output.put_line(v_result);
end;

2)存储过程:
create [or replace] procedure procedure Name
(arg1 [{in out in out}] type1 default value1,

argn [{in out in out}] typen default valuen)
[authid definer|current_user]– 权限控制
{is |as}
变量的声明部分
begin
执行语句部分
exception
异常处理部分
end procedureName;
in out in out—表示参数的模式,有入参、出参,不写的话默认为入参,其中只能为入参设置默认值,当调用函数后,不指定入参的值时,就使用入参的默认值。
create or replace procedure proTranslateRole(v_roleId in varchar2,
 v_result out varchar2)
is
 role_id varchar2(20); – 角色编号
begin
 role_id := v_roleId;
 if (role_id = ‘project_sz’) then
 v_result := role_id || ‘_表示的是_客服 ’;
else
 v_result := role_id || ‘_表示的是_未知 ’;
end if;
dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) || ‘ 处理成功 ’);
exception
 when others then
 dbms_output.put_line(to_char(sysdate, ‘hh24:mi:ss’) || ‘ 处理失败 ’);
end proTranslateRole;

1)位置表示法
–argvalue1,argvalue2,..argvaluen
proTranslateRole(v_roleId,v_result)
2) 名称表示法
– 这种方式与参数的顺序没关系,v_result、v_roleId 与函数中的参数名称需一致
declare
 roleId varchar2(20); – 角色编号
vresult varchar2(60); – 角色的结果
begin
 roleId := ‘project_bj’;
 vresult := proTranslateRole (v_result => vresult, v_roleId => roleId);
 dbms_output.put_line(vresult);
end;
3) 组合 (名称表示 + 位置表示法)
如果前一个参数用名称表示法,则后面的所有参数都要用名称表示法。
– 调用方式 1
declare
 v_roleId varchar2(20); – 角色编号
v_result varchar2(60); – 角色的结果
begin
 v_roleId := ‘project_bj’;
 v_result := proTranslateRole (v_roleId,v_result);
 dbms_output.put_line(v_result);
end;

– 调用方式 2
exec[ute] 存储过程名称(参数 1,.. 参数 n);
– 可以在 PL/SQL 块中建立本地函数和过程,但不能使用 create or replace 关键字

1)函数与过程的差异
1、如果要返回多个值或不返回值,可以使用过程;如果只返回 1 个值,可以使用函数。
2、过程用于执行一系列的动作,而函数用于计算和返回 1 个值。
3、可以在 SQL 语句内部通过调用函数来完成复杂的计算,而过程则做不到。

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计11395字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19352
评论数
4
阅读量
8032855
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
从“纸堆”到“电子化”文档:用这个开源系统打造你的智能文档管理系统

从“纸堆”到“电子化”文档:用这个开源系统打造你的智能文档管理系统

从“纸堆”到“电子化”文档:用这个开源系统打造你的智能文档管理系统 大家好,我是星哥。公司的项目文档存了一堆 ...
星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛 NAS-12:开源笔记的进化之路,效率玩家的新选择 前言 如何高效管理知识与笔记,已经成为技术...
星哥带你玩飞牛NAS-14:解锁公网自由!Lucky功能工具安装使用保姆级教程

星哥带你玩飞牛NAS-14:解锁公网自由!Lucky功能工具安装使用保姆级教程

星哥带你玩飞牛 NAS-14:解锁公网自由!Lucky 功能工具安装使用保姆级教程 作为 NAS 玩家,咱们最...
安装并使用谷歌AI编程工具Antigravity(亲测有效)

安装并使用谷歌AI编程工具Antigravity(亲测有效)

  安装并使用谷歌 AI 编程工具 Antigravity(亲测有效) 引言 Antigravity...
免费无广告!这款跨平台AI RSS阅读器,拯救你的信息焦虑

免费无广告!这款跨平台AI RSS阅读器,拯救你的信息焦虑

  免费无广告!这款跨平台 AI RSS 阅读器,拯救你的信息焦虑 在算法推荐主导信息流的时代,我们...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛 NAS-12:开源笔记的进化之路,效率玩家的新选择 前言 如何高效管理知识与笔记,已经成为技术...
300元就能买到的”小钢炮”?惠普7L四盘位小主机解析

300元就能买到的”小钢炮”?惠普7L四盘位小主机解析

  300 元就能买到的 ” 小钢炮 ”?惠普 7L 四盘位小主机解析 最近...
Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集 在云原生体系中,Prometheus 已成为最主流的监控与报警...
安装并使用谷歌AI编程工具Antigravity(亲测有效)

安装并使用谷歌AI编程工具Antigravity(亲测有效)

  安装并使用谷歌 AI 编程工具 Antigravity(亲测有效) 引言 Antigravity...
让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级

让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级

让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级 大家好,我是星哥,之前写了一篇文章 自己手撸一...