数据库系统概念:关系数据库的设计

CH8 Relational Database Design

关系数据库设计目标:

生成一组关系模式,存储信息时避免不必要的冗余,可以方便的获取信息。
本 章 概 览 { 基 于 函 数 依 赖 关 系 数 据 库 设 计 的 规 范 方 法 函 数 依 赖 + 数 据 依 赖 − > 定 义 范 式 本章概览\begin{cases} 基于函数依赖关系数据库设计的规范方法\\ 函数依赖+数据依赖->定义范式 \end{cases} {+>

8.1 好的关系设计的特点

image-20211007105837688

8.1.1 设计选择:更大的模式

用下面这个关系模式替代instructordepartment 模式

inst_dept(ID, name, salary, dept_name, building, budget);

表示instructordepartment进行自然连接。

造成问题:

  • 信息冗余
  • 数据不一致风险
  • 新增信息

image-20211007110511266

8.1.2 设计选择:更小的模式

在模式inst_dept中,我们要能发现dept_name--->budget这样的规则,才能分解这个模式。

这条规则被定义为:函数依赖

employee模式:

employee(ID, name, street, city, salary);

分解成下面的两个模式:

employee1(ID, name);
employee2(name, street, city, salary);

假如有两个同名的员工,那么将两张表做笛卡尔乘积将会出现问题。

这样分解称为有损分解lossy decommposition

8.2 原子域和第一范式

8.2.1.原子域

某些属性具有某种程度上的子结构

创建表时对于多值属性组合属性的处理:
多 值 属 性 : 一 个 实 体 可 能 有 多 个 值 — — 一 个 人 的 兴 趣 爱 好 组 合 属 性 : 家 庭 地 址 { s t r e e t c i t y s t a t e . . . 多值属性:一个实体可能有多个值——一个人的兴趣爱好\\ 组合属性:家庭地址\begin{cases}street\\city\\state\\... \end{cases} streetcitystate...

  • 组合属性:我们要消除这种子结构,让每个子属性称为一个属性。
  • 多值属性:为多值属性中的每个项创建一个元组。

关系模型中,将:属性不具有任何子结构这个思想形式化。

域是原子的:一个域是原子的,如果该域的元素被认为是不可分的单元。

非原子的例子:

  • 一个属性是名字的集合。
  • 组合属性的地址也具有非原子域。
8.2.2 第一范式

关系属于第一范式的定义:如果关系R的所有属性的域都是原子的,那么关系模式R属于第一范式。

两个例子:

(1)一个机构给雇员分配标识号,前两个字母表示系,剩下的四个数字是雇员在该系的唯一号码。比如CS0012
这样的标识号可以分解为更小的单元,因此不是原子的

(2)大学数据库使用课程’cs-101’,CS表示计算机系。但是一个原则:只要数据库应用没有将标识号拆开,并且将标识号的一部分解析为系的缩写,那么他仍然视为原子的

8.3 使用函数依赖进行分解

表示法概述:

  • 希腊字母表示属性集,如 α \alpha α
  • 关系模式: r ( R ) r(R) r(R)。r表示关系名,R是属性集。不关心关系的名字时,常简化表示法只用R。
  • 属性集是一个超码,使用K。
8.3.1 码和函数依赖

数据存在各种约束,比如学生和教师通过一个唯一的ID标识。

满足所有约束的实例,称为关系的合法实例

约束可以形式化的表示为码——超码,候选码,主码,或者定义的函数依赖。

1.超码

超码是可以唯一标识关系中一条元组的一个或者多个属性的集合。

K是r®的超码:在关系r®的任意合法实例中,对于r的实例中的所有元组对t1和t2,如果t1≠t2,那么t1[K]≠t2[K]。

没有两条元组在属性集K上可以具有相同的值

2.函数依赖

考虑一个关系模式 r ( R ) r(R) r(R),令 α ⊆ R \alpha\subseteq R αR且, β ⊆ R \beta\subseteq R βR

给定r®的一个实例,满足函数依赖 α → β \alpha\rightarrow \beta αβ的条件是:

  • 对实例中的所有元组对 t 1 t_1 t1 t 2 t_2 t2,若 t 1 [ α ] = t 2 [ α ] t_1[\alpha] = t_2[\alpha] t1[α]=t2[α],那么 t 1 [ β ] = t 2 [ β ] t_1[\beta] = t_2[\beta] t1[β]=t2[β]
  • 如果所有合法实例都满足函数依赖 α → β \alpha\rightarrow \beta αβ,那么该函数依赖在模式 r ( R ) r(R) r(R)上成立。

使用函数依赖表示超码

如果函数依赖 K → R K\rightarrow R KR,那么K是关系r®的一个超码。

属性对(ID, dept_name)构成超码的记录:
I D , d e p t _ n a m e → n a m e , s a l a r y , b u i l d i n g , b u d g e t ID, dept\_name \rightarrow name, salary, building, budget ID,dept_namename,salary,building,budget
image-20211007153832950
A → C 但 是 C 不 决 定 A A\rightarrow C\\但是C不决定A ACCA
使用函数依赖的方式

  • 判定关系的实例是否满足给定函数依赖集
  • 说明合法关系集上的约束
3.平凡的trivial

平凡的:有些函数依赖在所有关系中都满足,则称之为平凡的。

例:
A → A A B → A A\rightarrow A\\ AB\rightarrow A AAABA
一般的,如果 β ⊆ α \beta\subseteq\alpha βα,那么 α → β \alpha\rightarrow \beta αβ的函数依赖是平凡的。

4.函数依赖的闭包

给定关系r®上成立的函数依赖集F,有可能隐含了某些函数依赖也在该关系上成立:
{ A → B B → C ⇒ A → C \begin{cases}A\rightarrow B\\ B\rightarrow C\\\end{cases} \Rightarrow A\rightarrow C {ABBCAC
使用 F + F^+ F+来表示F集合的闭包,也就是能从给定的F集合推导出来的所有函数依赖。

F + F^+ F+包含了F中的所有函数依赖。

8.3.2 第二范式

这里插入书上未作说明的第二范式

第二范式要满足的条件:

  • 不含有不属于非主属性对码的部分依赖

部分函数范式:
α , β ∈ R , 若 γ 是 关 系 的 主 码 , 且 有 α ⊆ γ , 那 么 α → β 就 是 非 主 属 性 的 函 数 依 赖 。 \alpha,\beta\in R,若\gamma是关系的主码,且有\alpha\subseteq \gamma,那么\alpha\rightarrow\beta就是非主属性的函数依赖。 α,βRγαγαβ
没有没有这种依赖即是满足第二范式。

所以说第二范式消除了部分的函数依赖。

8.3.3 Boyce-Codd范式
1.BCNF范式

Boyce-Codd范式即Boyee-Codd Normol Form, BCNF范式

BCNF范式消除了所有能由函数依赖发现的冗余。

具有函数依赖集F的关系模式R属于BCNF范式的条件是,对于 F + F^+ F+中所有形如 α → β \alpha\rightarrow\beta αβ的函数依赖(其中 α ⊆ R \alpha\subseteq R αR β ⊆ R \beta\subseteq R βR),下面至少有一项成立:

  • α → β \alpha\rightarrow\beta αβ是一个平凡的函数依赖
  • α \alpha α是模式R的一个超码

一个数据库属于BCNF范式的条件是:构成该设计的关系模式集中的每个模式都属于BCNF。

不属于BCNF范式的例子:
i n s t _ d e p t ( I D , n a m e , s a l a r y , d e p t _ n a m e , b u i l d i n g , b u d g e t ) inst\_dept(ID, name, salary, dept\_name, building, budget) inst_dept(ID,name,salary,dept_name,building,budget)
函数依赖 d e p t _ n a m e → b u d g e t dept\_name\rightarrow budget dept_namebudget在inst_dept上成立,但是dept_name不是超码。

2.BCNF模式规则

设R为不属于BCNF范式的一个模式,则至少存在一个非平凡的函数依赖 α → β \alpha\rightarrow\beta αβ,其中 α \alpha α不是R的超码。我们在设计中用一下两个模式取代R:

  • ( α ⋃ β ) (\alpha \bigcup \beta) (αβ)
  • ( R − ( β − α ) ) (R-(\beta-\alpha)) (R(βα))

在inst_dept的例子中, α = d e p t _ n a m e , β = { b u i l d i n g , b u d g e t } \alpha = dept\_name,\beta = \{building, budget\} α=dept_name,β={building,budget},且inst_dept被取代为:

  • KaTeX parse error: Expected '}', got '_' at position 37: …) = (\text{dept_̲name,building,b…
  • KaTeX parse error: Expected '}', got '_' at position 39: …xt{ID,name,dept_̲name,salary})

当我们进行分解的时候,可能分解的结果中还会有一个或者多个不属于BCNF。这种情况下需要进一步分解。

8.3.4 BCNF和保持依赖

数据库一致性约束的方式很多:主码约束,函数约束,check约束,断言和触发器。

每次数据库检查这些约束的开销很大。

BCNF的分解会妨碍对某些函数依赖项的检查

例:

假定将学生和导师的关系修改为:教师只能和单个系关联,一个学生可以有多个老师,但是一个给定的系中最多一个。

我们将advisor,student和department结合成一个三元联系集合:dept_advisor。它是从{instructor,student}到department是唯一的。关系模式如下:

dept_advisor(s_ID, i_ID, dept_name)

下面的函数依赖在上面的关系模式中成立:
{ i _ I D → d e p t _ n a m e : 一 个 教 师 只 能 在 一 个 系 担 任 导 师 s _ I D , d e p t _ n a m e → i _ I D : 对 于 一 个 指 定 系 , 一 个 学 生 可 以 由 至 多 一 个 导 师 \begin{cases}i\_ID\rightarrow dept\_name:一个教师只能在一个系担任导师\\ s\_ID,dept\_name\rightarrow i\_ID:对于一个指定系,一个学生可以由至多一个导师\end{cases} {i_IDdept_names_ID,dept_namei_ID
因为存在函数依赖 i _ I D → d e p t _ n a m e i\_ID\rightarrow dept\_name i_IDdept_name,其中 i _ I D i\_ID i_ID不是超码,所以需要根据BCNF原则进行分解。结果如下:
KaTeX parse error: Expected '}', got '_' at position 10: \text{(s_̲ID,i_ID)}\\ \te…
这两个关系都满足BCNF范式,但是以来的检查计算变得很困难。

因此称我们的设计不是保持依赖的(dependency preserving)。我们希望保持依赖,所以常常使用一种比BCNF弱的范式,它允许我们保持以来,该范式称为第三范式

8.3.5 第三范式
1.第三范式和BCNF的区别
  • BCNF要求所有非平凡函数依赖都形如 α → β \alpha\rightarrow\beta αβ,其中 α \alpha α是一个超码。
  • 第三范式(3NF)允许左侧不是超码的某些非平凡函数依赖
2.第三范式定义

对于 F + F^+ F+中的所有形如 α → β \alpha\rightarrow\beta αβ的函数依赖(其中 α ⊆ R \alpha\subseteq R αR β ⊆ R \beta\subseteq R βR),以下至少一项成立:

  • α → β \alpha\rightarrow\beta αβ是一个平凡的函数依赖
  • α \alpha α是R的一个超码
  • β − α \beta-\alpha βα中的每一个属性A都包含于R的一个候选码

前两个条件与BCNF相同。

第三个条件中,由于候选码不止一个,所以可以不是全包含于一个候选码。 β − α \beta-\alpha βα中的每个属性A可以包含于不同的候选码中。它意味着BCNF的最小放宽,确保每个模式都有保持依赖的3NF分解。

任何满足BCNF范式的模式也满足与3NF,反之不一定。BCNF比3NF更严格

再次考虑关系dept_advisor:
函 数 依 赖 { i _ I D → d e p t _ n a m e s _ I D , d e p t _ n a m e → i _ I D 函数依赖\begin{cases} i\_ID\rightarrow dept\_name\\ s\_ID,dept\_name\rightarrow i\_ID \end{cases} {i_IDdept_names_ID,dept_namei_ID
函数依赖 i _ I D → d e p t _ n a m e i\_ID\rightarrow dept\_name i_IDdept_name导致模式不属于BCNF,这里 α = i _ I D \alpha=i\_ID α=i_ID, β = d e p t _ n a m e \beta=dept\_name β=dept_name

所以 β − α = d e p t _ n a m e \beta-\alpha = dept\_name βα=dept_name。又由于有第二个函数依赖存在,所以有 s _ I D , d e p t _ n a m e s\_ID,dept\_name s_ID,dept_name是一个候选码。于是dept_name包含于一个候选码中。所以 d e p t _ a d v i s o r dept\_advisor dept_advisor属于3NF。

8.3.6 更高的范式

BCNF范式有多好?

多值属性仍满足BCNF范式。但是会造成会多的冗余。

8.4 函数依赖理论

判定是否属于BCNF范式或者第三范式的首要任务:找到所有的函数依赖

image-20211011153423750

8.4.1 函数依赖集的闭包
1.逻辑蕴含

给定模式上的函数依赖集F,我们可以证明某些其他的函数依赖在该模式上也成立。我们称这些函数依赖被F逻辑蕴涵

给定关系模式 r ( R ) r(R) r(R),如果 r ( R ) r(R) r(R)上的每一个满足F的实例也满足f,那么R上的函数依赖f被r上的函数依赖集F逻辑蕴涵

e.g.
A → B A → C C G → H C G → I B → H A\rightarrow B\\ A\rightarrow C\\ CG\rightarrow H\\ CG\rightarrow I\\ B\rightarrow H\\ ABACCGHCGIBH
那么函数依赖:
A → H A\rightarrow H AH
被逻辑蕴涵。也就是说,一个关系只要满足给定的函数依赖集,那么这个关系一定满足 A → H A\rightarrow H AH

2.函数依赖的闭包-Armstrong’s Axioms

F是一个函数依赖集,F的闭包是被F逻辑蕴涵的所有函数依赖的集合,记作 F + F^+ F+。给定F,可以由函数依赖的形式化定义计算出 F + F^+ F+

阿姆斯特朗定理:

由阿姆斯特朗定理不断应用,可以找到 F + F^+ F+
自 反 律 : i f β ⊆ α ,   t h e n α → β 增 补 律 : i f   α → β , t h e n   γ α → γ β 传 递 律 : i f   α → β , a n d   β → γ , t h e n   α → γ 自反律:if\quad \beta\subseteq\alpha,\,then\quad\alpha\rightarrow\beta\\ 增补律:if\,\alpha\rightarrow\beta,then\,\gamma\alpha\rightarrow\gamma\beta\\ 传递律:if\,\alpha\rightarrow\beta,and\,\beta\rightarrow\gamma,then\,\alpha\rightarrow\gamma ifβα,thenαβifαβ,thenγαγβifαβ,andβγ,thenαγ

  • 自反律:一个集合可以决定他的所有子集。
  • 增补率:增加一项

Armstrong定理特点:

  • 正确有效的sound
  • 完备的complete

Example:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GO2oTdyB-1635593884006)(https://gitee.com/sun-yunqi/img/raw/master/pictureStore/image-20211011213859885.png)]

Armstrong定理的引申:

  • union右侧可合并: i f   α → β   a n d   α → γ , t h e n   α → β γ if\,\alpha\rightarrow\beta\, and\, \alpha\rightarrow \gamma,then\,\alpha\rightarrow\beta\gamma ifαβandαγ,thenαβγ
  • decomposition右侧可拆分: i f   α → β γ , t h e n   α → β   a n d   α → γ if\,\alpha\rightarrow\beta\gamma,then\,\alpha\rightarrow\beta\, and\, \alpha\rightarrow \gamma ifαβγ,thenαβandαγ
  • pseudotransitivity伪传递律: i f   α → β   h o l d s   a n d   γ β → δ ,   t h e n   γ α → δ if\,\alpha\rightarrow\beta\, holds\,and\,\gamma\beta\rightarrow\delta,\,then\, \gamma\alpha\rightarrow\delta ifαβholdsandγβδ,thenγαδ
3.Armstrong定理求解函数依赖闭包
F+ = F
	repeat
		for each F+中的函数依赖f
			在f上应用自反律和增补律
			将结果加到F+for each F+中的一对函数依赖f1和f2
         	if f1和f2可以使用传递律结合起来
         		将结果加到F+中
   	until F+不再发生变化

这种算法最终会收敛。由于包含n个元素的集合有 2 n 2^n 2n个子集,因此共有 2 n × 2 n 2^n\times 2^n 2n×2n个可能的函数依赖。

8.4.2 属性集的闭包

如果 α → B \alpha\rightarrow B αB,那么称属性B被 α \alpha α函数确定

情景:判断 α \alpha α是不是超码?

  • 所有属性都被 α \alpha α函数确定
  • 依照union,那么 α \alpha α就是超码

这样就有一个需求:计算被 α \alpha α函数确定的属性集。

1.函数确定的属性集

概念:如果 α → B \alpha\rightarrow B αB,那么称属性B被 α \alpha α函数确定

函数确定的属性集的作用如下:

  • 判定是否是超码
  • 判定函数依赖
  • 计算F的函数闭包
2.函数确定属性集的计算方法

α \alpha α为一个属性集,我们将函数依赖F下被 α \alpha α函数确定的所有属性的集合称为F下 α \alpha α的闭包,记作 α + \alpha^+ α+

计算函数确定的属性集有两种方法:

  • 计算 F + F^+ F+,找出所有左半部分为 α \alpha α的函数依赖,合并右半部分——开销大,F+可能很大

  • 如下的伪代码算法:

    result:= α;
    	repeat
    		for each 函数依赖β→r in F do
    			begin
    				if β 蕴涵于 result then result := result ∪ r;
    			end
           	until (result 不变)
    

    即:对函数依赖集F下的每一个函数依赖,如果依赖的左边 β \beta β在结果属性集中,那么依赖的右边 γ \gamma γ加入到结果集中。

    e.g.
    R = ( A , B , C , G , H , I ) F = { A → B A → C C G → H C G → I B → H } R = (A,B,C,G,H,I)\\ F = \{A\rightarrow B\\ A\rightarrow C\\ CG\rightarrow H\\ CG\rightarrow I\\ B\rightarrow H\}\\ R=(A,B,C,G,H,I)F={ABACCGHCGIBH}
    ( A G ) + (AG)^+ (AG)+
    1. r e s u l t = A G / / 初 始 化 结 果 2. r e s u l t = A B C G / / A → B   , A → C 3. r e s u l t = A B C G H I / / C G → H C G → I 1.result = AG\quad//初始化结果\\ 2.result = ABCG\quad//A\rightarrow B\,,A\rightarrow C\\ 3.result = ABCGHI\quad//CG\rightarrow H\quad CG\rightarrow I\\ 1.result=AG//2.result=ABCG//AB,AC3.result=ABCGHI//CGHCGI
    问:AG是一个候选码吗?

    step1.AG是一个超码吗?

    所有的属性都在 ( A G ) + (AG)^+ (AG)+中,是一个超码。

    step2.判断是否是候选码:是否有他的真子集是超码;依次判断A和G在F下的闭包 A + A^+ A+ B + B^+ B+
    A → R ? G → R ? A\rightarrow R?\\ G\rightarrow R? AR?GR?

8.4.3 正则覆盖

需求分析:数据库进行更新操作,数据库必须保证此更新不破坏任何函数依赖,也就是说,F中的所有函数依赖在新的数据库状态下仍然满足。但是由于函数依赖过多,所以检测每个函数依赖都满足的代价较高。我们可以通过检测与给定函数依赖集相同闭包的简化集来减小检测冲突的开销

1.无关属性

无关属性:如果去除函数依赖中的一个属性不改变该函数依赖的闭包,则称该属性是无关的。

注意这里说明的:去除掉函数依赖的(属性),不改变函数依赖的(闭包

无关属性的判定,考虑函数依赖集F以及F中的函数依赖 α → β \alpha\rightarrow\beta αβ

  • 如果 A ∈ α A\in\alpha Aα并且F逻辑蕴含 ( F − { α → β } ) ⋃ { ( α − A ) → β } (F-\{\alpha\rightarrow\beta\})\bigcup\{(\alpha-A)\rightarrow\beta\} (F{αβ}){(αA)β},那么属性A在 α \alpha α中是无关的。
  • 如果 A ∈ β A\in\beta Aβ并且函数依赖集 ( F − { α − β } ) ⋃ { α → ( β − A ) } (F - \{\alpha-\beta\})\bigcup\{\alpha\rightarrow(\beta-A)\} (F{αβ}){α(βA)}逻辑蕴含F,则属性A在 β \beta β中是无关的。

由于去掉属性后不改变函数依赖的闭包才是无关属性,所以其实蕴涵关系的两个式子必然是有相同的闭包的。

2.无关属性的检验

令R为一个关系模式,且F是在R上成立的给定函数依赖集合。考虑 α → β \alpha\rightarrow\beta αβ中的一个属性A。

  • 如果 A ∈ α A\in\alpha Aα,判断A是否无关,令 γ = α − { A } \gamma = \alpha-\{A\} γ=α{A},检查 γ → β \gamma\rightarrow\beta γβ是否可以由F推出。

    做法:计算F下的 γ \gamma γ的闭包 γ + ( γ \gamma^+(\gamma γ+(γ的闭包 ) ) );如果 γ + \gamma^+ γ+包含 β \beta β的所有属性,那么A在 α \alpha α中是无关的。

    属性集合的闭包求法见8.4.2

  • 如果 A ∈ β A\in\beta Aβ,为检验A是否是无关的,考虑集合
    F ′ = ( F − { α − β } ) ⋃ { α → ( β − A ) } F'=(F - \{\alpha-\beta\})\bigcup\{\alpha\rightarrow(\beta-A)\} F=(F{αβ}){α(βA)}
    并且检验 α → A \alpha\rightarrow A αA能否由F’推出。计算F下的 α \alpha α的闭包 α + \alpha^+ α+如果包含A,那么A在 β \beta β中是无关属性,否则不是

Example:
F = { A B → C D , A → E , E → C } F = \{AB\rightarrow CD,A\rightarrow E,E\rightarrow C\} F={ABCD,AE,EC}
要求检验C在 A B → C D AB\rightarrow CD ABCD中是否是无关的。
∵ C ∈ C D ∴ 考 虑 集 合 F ′ = { A B → D , A → E , E → C } , 求 A B → c 能 否 在 F ′ 下 推 导 出 来 。 为 此 我 们 求 出 A B 在 F ′ 下 的 属 性 集 合 闭 包 。 求 得 r e s u l t = A B C D E , 包 含 C , 所 以 C 在 C D 中 是 无 关 的 。 ∵C\in CD\\ ∴考虑集合F'=\{AB\rightarrow D,A\rightarrow E,E\rightarrow C\},求AB\rightarrow c能否在F'下推导出来。\\ 为此我们求出AB在F'下的属性集合闭包。\\ 求得result = ABCDE,包含C,所以C在CD中是无关的。 CCDF={ABD,AE,EC},ABcFABFresult=ABCDE,CCCD

3.正则覆盖

F的正则覆盖Fc是一个依赖集,使得F逻辑蕴含Fc中的所有函数依赖,并且Fc逻辑蕴含F中的所有依赖。

此外,Fc具有以下的性质:

  • Fc中的任何函数依赖都不含无关属性
  • Fc中的函数依赖的左半部分是唯一的。即Fc中不存在两个依赖: α 1 → β 1 \alpha_1\rightarrow\beta_1 α1β1 α 2 → β 2 \alpha_2\rightarrow\beta_2 α2β2,满足 α 1 = α 2 \alpha_1=\alpha_2 α1=α2

函数依赖集的正则覆盖算法如下:

image-20211012195227267

注意点:

  • 当检验一个属性是否无关时,使用的是Fc中的函数依赖,而不是F中的函数依赖。
  • 如果出现了去掉某个属性后,函数依赖的左边或者右边为空,那么这样的依赖应该删除
4.正则覆盖的作用与计算

F与Fc有相同的闭包 ⇒ \Rightarrow 验证是否满足Fc等价于验证是否满足F.

Fc是最小的,不含无关属性。验证Fc比验证F更容易。

Example

考虑到模式 ( A , B , C ) (A,B,C) (A,B,C)上的函数依赖集F:
A → B C B → C A → B A B → C A\rightarrow BC\\ B\rightarrow C\\ A\rightarrow B\\ AB\rightarrow C\\ ABCBCABABC

  • A → B C A\rightarrow BC ABC A → B A\rightarrow B AB合并成 A → B C A\rightarrow BC ABC

  • 去除掉无关属性

    image-20211012222757503

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blanche117

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值