PostgreSQL学习笔记(上)

PostgreSQL学习笔记(上)

1、基础知识

SQL语言包含4个部分:

数据定义语言(DDL):DROPCREATEALTER等语句。

数据操作语言(DML):INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。

数据查询语言(DQL):SELECT语句。

数据控制语言(DCL):GRANTREVOKECOMMITROLLBACK等语句。

2、数据库的基本操作

2.1 创建数据库

# 创建数据库
create database sample_db;

2.2 修改数据库

# 语法
ALTER DATABASE name [ [WITH] option [...] ]
# 修改拥有者
ALTER DATABASE sample_db OWNER TO pg_database_owner;
# 修改名字
ALTER DATABASE sample_db RENAME TO sample_db_alter;
# 修改数据库的连接最大值为10
ALTER DATABASE sample_db WITH CONNECTION LIMIT=10;

2.3 删除数据库

# 语法
DROP DATABASE database_name[,...n];
# 删除数据库
DROP DATABASE sample_db;

并不是所有数据库在任何时候都可以被删除,只有处于正常状态下的数据库,才能使用DROP语句删除。当数据库

处于以下状态时不能被删除:数据库正在使用;数据库正在恢复;数据库包含用于复制的对象。

2.4 关闭数据库

先找到指定数据库的pid:

SELECT datname,pid FROM pg_stat_activity;

关闭数据库连接:

SELECT pg_terminate_backend(14788);

其实可以一步完成:

SELECT CAST(pg_terminate_backend(pid) AS VARCHAR(10)) FROM pg_stat_activity WHERE datname='sample_db';

3、数据表的基本操作

3.1 创建数据表

# 语法
CREATE TABLE <表名>
(
字段名1 数据类型 [列级别约束条件] [默认值],
字段名2 数据类型 [列级别约束条件] [默认值],
...
[表级别约束条件]
);

使用CREATE TABLE创建表时,必须指定以下信息:

  • 要创建的表的名称不区分大小写,不能使用SQL语言中的关键字,如DROP、ALTER、INSERT等。

  • 数据表中如果创建多个列,每一个列(字段)的名称和数据类型都要用逗号隔开。

# 创建表
CREATE TABLE tb_emp1
(
id INT,
name VARCHAR(25),
deptId INT,
salary FLOAT
);
3.1.1 使用主键约束
1、单字段主键

定义列的同时使用主键:

# 语法
字段名 数据类型 PRIMARY KEY
CREATE TABLE tb_emp2
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT
);

在定义完所有列之后使用主键:

# 语法
[CONSTRAINT<约束名>] PRIMARY KEY [字段名]
CREATE TABLE tb_emp3
(
id INT,
name VARCHAR(25),
deptId INT,
salary FLOAT,
PRIMARY KEY(id)
);
2、多字段联合主键
# 语法
PRIMARY KEY[字段1,字段2,···,字段n]
CREATE TABLE tb_emp4
(
name VARCHAR(25),
deptId INT,
salary FLOAT,
PRIMARY KEY(name,deptId)
);
3.1.2 使用外键约束
# 语法
[CONSTRAINT <外键名>] FOREIN KEY 字段名1 [,字段名2,···]
REFERENCES <主表名> 主键列1 [,主键列2,···】
CREATE TABLE tb_dept1
(
id INT PRIMARY KEY,
name VARCHAR(22) NOT NULL,
location VARCHAR(50)
);

CREATE TABLE tb_emp5
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_deptl FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
3.1.3 使用非空约束
# 语法
字段名 数据类型 NOT NULL
CREATE TABLE tb_emp6
(
id INT PRIMARY KEY,
name VARCHAR(25) NOT NULL,
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_dept2 FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
3.1.4 使用唯一性约束
1、在定义完列之后使用
# 语法
字段名 数据类型 UNIQUE
CREATE TABLE tb_dept2
(
id INT PRIMARY KEY,
name VARCHAR(22) UNIQUE,
location VARCHAR(50)
);
2、在定义完所有列之后指定唯一约束
# 语法
[CONSTRAINT<约束名>]UNIQUE(<字段名>)
CREATE TABLE tb_dept3
(
id INT PRIMARY KEY,
name VARCHAR(22),
location VARCHAR(50),
CONSTRAINT STH UNIQUE(name)
);

UNIQUEPRIMARY KEY的区别:一个表中可以有多个字段声明为UNIQUE,但只能有一个PRIMARY KEY 声明;

声明为PRIMAY KEY 的列不允许有空值,但是声明为UNIQUE 的字段允许空值(NULL)的存在。

3.1.5 使用默认约束
# 语法
字段名 数据类型 DEFAULT 默认值
CREATE TABLE tb_emp7
(
id INT PRIMARY KEY,
name VARCHAR(25)NOT NULL,
deptId INT DEFAULT 1111,
salary FLOAT,
CONSTRAINT fk_emp_dept3 FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);

3.2 修改表数据

3.2.1 修改表名
# 语法
ALTER TABLE<旧表名>RENAME TO<新表名>;
ALTER TABLE tb_dept3 RENAME TO tbdepartment3;
3.2.2 修改字段的数据类型
# 语法
ALTER TABLE<表名> ALTER COLUMN <字段名> TYPE <数据类型>
ALTER TABLE tb_dept1 ALTER COLUMN name TYPE VARCHAR(30);
3.2.3 修改字段名
# 语法
ALTER TABLE <表名> RENAME <旧字段名> TO <新字段名> <新数据类型>;
ALTER TABLE tb_dept1 RENAME location TO loc;
3.2.4 添加字段
# 语法
ALTER TABLE <表名> ADD COLUMN <新字段名> <数据类型>
1、添加无完整约束条件的字段
ALTER TABLE tb_dept1 ADD COLUMN managerId INT;
2、添加有完整约束条件的字段
ALTER TABLE tb_dept1 ADD COLUMN column1 VARCHAR(12) NOT NULL;
3.2.5 删除字段
# 语法
ALTER TABLE<表名>DROP<字段名>;
ALTER TABLE tb_dept1 DROP column1;
3.2.6 删除表的外键约束
# 语法
ALTER TABLE<表名> DROP CONSTRAINT <外键约束名>
CREATE TABLE tb_emp9
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_dept FOREIGN KEY(deptId) REFERENCES tb_dept1(id)
);
ALTER TABLE tb_emp9 DROP CONSTRAINT fk_emp_dept;
3.2.7 修改约束
ALTER TABLE tb_emp9 ALTER COLUMN name SET NOT NULL;

4.3 删除数据表

4.3.1 删除没有被关联的表
# 语法
DROP TABLE[IF EXISTS]1,2,表n;
DROP TABLE IF EXISTS tb_dept2;
4.3.2 删除被其它表关联的主表
CREATE TABLE tb_dept2
(
id INT PRIMARY KEY,
name VARCHAR(22),
location VARCHAR(50)
);

CREATE TABLE tb_emp
(
id INT PRIMARY KEY,
name VARCHAR(25),
deptId INT,
salary FLOAT,
CONSTRAINT fk_emp_dept FOREIGN KEY(deptId) REFERENCES tb_dept2(id)
);
# 有关联无法删除
DROP TABLE IF EXISTS tb_dept2;
ALTER TABLE tb_emp DROP CONSTRAINT fk_emp_dept;
DROP TABLE tb_dept2;

4、数据类型和运算符

4.1 数据类型介绍

4.1.1 整数类型

PostgreSQL 主要提供的整数类型有 SMALLINTINT(INTEGER)BIGINT

类型名称 说明 存储需求 存储范围
SMALLINT 小范围的整数 2个字节 -2^15~2^15-1
INT(INTEGER) 普通大小的整数 4个字节 -2^31~2^31-1
BIGINT 大整数 8个字节 -2^63~2^63-1
CREATE TABLE tmp1(X SMALLINT,y INT,z BIGINT );
4.1.2 浮点数类型

PostgreSQL 中使用浮点数来表示小数。浮点类型有两种:REALDOUBLE PRECISION

类型名称 说明 存储需求 存储范围 精度
REAL 6位十进制数字精度 4 个字节 1E-37~1E+37 至少6位
DOUBLE PRECISION 15 位十进制数字精度 8个字节 1E-307~1E+308 至少15位

PostgreSQL 也支持SQL 标准表示法,floatfloat(p)用于声明非精确的数值类型。其中,p声明以二进制位

表示的最低可接受精度。在选取 REAL 类型的时候,PostgreSQL 接受 float(1)float(24),在选取

DOUBLE PRECISION 的时候,接受float(25)float(53)。在允许范围之外的p值将导致一个错误,没有声明精

度的 float 将被当作 DOUBLE PRECISION

CREATE TABLE tmp2(x FLOAT(5),y REAL,z DOUBLE PRECISION);

在 PostgreSQL中,浮点类型有几个特殊值。其中,Infinity表示正无穷大,-Infinity表示负无穷大,NaN

表示不是一个数字。

4.1.3 任意精度类型

在PostgreSQL中,NUMERIC表示数值是任意精度的类型,使用 NUMERIC (M,N)来表示。其中,M称为精度,表

示总的位数;N称为标度,表示小数的位数。例如563.186中,精度为6,标度为3。

NUMERIC的有效的取值范围由M和N的值决定。如果改变M而固定N,则其取值范围将随M的变大而变大。另外如

果用户数据的精度超出指定精度,则会四舍五入进行处理。

CREATE TABLE tmp3(x NUMERIC(5,1),y NUMERIC(5,2));
INSERT INTO tmp3 VALUES(9.12,9.15);
SELECT * FROM tmp3;
x  |y   |
---+----+
9.1|9.15|
4.1.4 日期与时间类型

PostgreSQL 中有多种表示日期的数据类型,主要有:TIMEDATETIMESTAMPINTERVAL。每一个类型都有

合法的取值范围,当指定确实不合法的值时,系统将“零”值插入到数据库中。

类型名称 含义 存储需求
TIME 只用于一日内时间 8字节
DATE 只用于日期 4字节
TIMESTAMP 日期和时间 8字节

另外,对于TIMETIMESTAMP类型,默认情况下为without time zone(不带时区),如果

需要,可以设置为带时区(with time zone)。

1、TIME

TIME 类型用于只需要时间信息的值,在存储时需要8个字节。格式为:HH:MM:SS。HH 表示小时;MM 表示分

钟;SS表示秒。TIME类型的取值范围为00:00:00~24:00:00

CREATE TABLE tmp4(t TIME);
INSERT INTO tmp4 values('10:05:05'),('23:23');
SELECT * FROM tmp4;
t       |
--------+
10:05:05|
23:23:00|
INSERT INTO tmp4 values('101112');
SELECT*FROM tmp4;
t       |
--------+
10:05:05|
23:23:00|
10:11:12|
ALTER TABLE tmp4 ALTER COLUMN t TYPE time without time zone;
DELETE FROM tmp4;
INSERT INTO tmp4 values(CURRENT_TIME),(NOW());
SELECT * FROM tmp4;
t       |
--------+
15:39:11|
15:39:11|
2、Date

DATE 类型用在仅需要日期值时,没有时间部分,在存储时需要4 个字节,日期格式为YYYY-MM-DD。其中,YYYY

表示年;MM 表示月;DD表示日。在给 DATE 类型的字段赋值时,可以使用字符串类型或者数字类型的数据插

入,只要符合DATE 的日期格式即可,具体如下:

  • YYYY-MM-DD或者YYYYMMDD字符串格式表示的日期。例如输入2012-12-31或者20121231,插入数据库的

    日期都为2012-12-31

  • YY-MM-DD或者YYMMDD字符串格式表示的日期,在这里,YY表示两位的年值。包含两位年值的日期会令人

    模糊,因为不知道世纪。PostgreSQL 使用以下规则解释两位年值:00~69范围的年值转换为

    2000~206970~99范围的年值转换为1970~1999。例如输入12-12-31,插入数据库的日期为

    2012-12-31;输入981231,插入数据的日期为1998-12-31

  • 使用 CURRENT DATE或者 NOWO插入当前系统日期。

CREATE TABLE tmp5(d DATE);
INSERT INTO tmp5 values('1998-08-08'),('19980808'),('20101010');
SELECT * FROM tmp5;
d         |
----------+
1998-08-08|
1998-08-08|
2010-10-10|
DELETE FROM tmp5;
INSERT INTO tmp5 values('99-09-09'),('990909'),('000101'),('121212');
SELECT * FROM tmp5;
d         |
----------+
1999-09-09|
1999-09-09|
2000-01-01|
2012-12-12|
DELETE FROM tmp5;
INSERT INTO tmp5 values(NOW());
SELECT * FROM tmp5;
d         |
----------+
2022-09-11|

NOWO函数返回日期和时间值,在保存到数据库时,只保留了其日期部分。

3、TIMESTAMP

TIMESTAMP的日期格式为YYYY-MM-DD HH:MM:SS。在存储时需要8个字节,因此在插入数据时,要保证在合法的

取值范围内。

CREATE TABLE tmp7(ts TIMESTAMP);
INSERT INTO tmp7 values('1996-02-02 02:02:02'),(NOW());
SELECT * FROM tmp7;
ts                     |
-----------------------+
1996-02-02 02:02:02.000|
2022-09-11 15:53:41.421|
4、创建带时区的日期和时间类型
CREATE TABLE tmp7h(th TIME with time zone);
INSERT INTO tmp7h values('10:05:05 PST'),('10:05:05');
SELECT * FROM tmp7h;
th            |
--------------+
02:05:05 +0800|
10:05:05 +0800|
4.1.5 字符串类型

字符串类型用来存储字符串数据,除了可以存储字符串数据之外,还可以存储其他数据,比如图片和声音的二进制

数据。字符串可以进行区分或者不区分大小写的串比较,另外,还可以进行模式匹配查找。PostgreSQL中字符串

类型指CHARVARCHARTEXT

类型名称 说明
CHAR(n)/CHARACTER(n) 固定长度非二进制字符串,不足补空白
VARCHAR(n)/CHARACTER VARYING(n) 变长非二进制字符串,有长度限制
TEXT 变长非二进制字符串,无长度限制
1、CHARACTER(n)和 CHARACTER VARYING(n)

其中,n是一个正整数。CHARACTER(n)CHARACTER VARYING(n)都可以存储最多n个字符的字符串。试图存储

更长的字符串到这些类型的字段里会产生一个错误,除非超出长度的字符都是空白,这种情况下该字符串将被截断

为最大长度。如果要存储的字符串比声明的长度短,类型为CHARACTER的数值将会用空白填满;而类型为

CHARACTER VARYING的数值将只是存储较短的字符串。

CREATE TABLE tmp8(
ch CHARACTER(4),vch CHARACTER VARYING(4)
);
INSERT INTO tmp8 VALUES('ab','ab'),('abcd','abcd'),('ab','ab');
SELECT concat('(',ch,')'),concat('(',vch,')') FROM tmp8;
concat|concat|
------+------+
(ab  )|(ab)  |
(abcd)|(abcd)|
(ab  )|(ab)  |

CHARACTER类型中填充的空白是无意义的。例如在比较两个CHARACTER值时,填充的空白都会被忽略,在转换

成其他字符串类型的时候,CHARACTER 值里面的空白会被删除。请注意,在CHARACTER VARYING和TEXT数值

里,结尾的空白是有意义的。

# 会报错,长度超出限制
INSERT INTO tmp8 VALUES('abcde','abcde');
2、TEXT 类型

在PostgreSQL中,TEXT 类型可以存储任何长度的字符串。尽管TEXT 不是SQL 标准类型,但是其他许多SQL 数据

库系统中也包括它。

CREATE TABLE tmp9(te TEXT);
INSERT INTO tmp9 VALUES('ab'),('abcd'),('ab');
SELECT concat('(',te,')') FROM tmp9;
concat|
------+
(ab)  |
(abcd)|
(ab)  |
4.1.6 二进制类型

PostgreSQL 支持两类字符型数据:文本字符串和二进制字符串,前面讲解了存储文本的字符串类型,这一节将讲

解 PostgreSQL 中存储二进制数据的数据类型。PostgreSQL 提供了 BYTEA 类型,用于存储二进制字符串。BYTEA

类型存储空间为4字节加上实际的二进制字符串。

CREATE TABLE tmp10(b BYTEA);
INSERT INTO tmp10 VALUES(E'\\000');
SELECT * FROM tmp10;
b|
-+
 |
4.1.7 布尔类型

PostgreSQL 提供了 BOOLEAN 布尔数据类型。BOOLEAN用一个字节来存储,提供了 TRUE(真)和FALSE(假)两个

值。另外,用户可以使用其他有效文本值替代TRUE和FALSE。替代 TRUE的文本值为:‘t’、‘true’、‘y’、‘yes’和1’;

替代FALSE的文本值为:'f、‘false’、‘n’、‘no’和’0’。

CREATE TABLE tmp11(b BOOLEAN);
INSERT INTO tmp11 VALUES(TRUE),
(FALSE),
('y'),
('no'),
('0');
SELECT * FROM tmp11;
b    |
-----+
true |
false|
true |
false|
false|
4.1.8 数组类型

PostgreSQL 允许将字段定义成定长或变长的一维或多维数组。数组类型可以是任何基本类型或用户定义类型。

1、声明数组

在PostgreSQL中,一个数组类型是通过在数组元素类型名后面附加中括号来命名的。

numb INT[];
xuehao TEXT[][];
zuoye TEXT[4][4];

其中,numb字段为一维INT数组;xuehao字段为二维TEXT数组;zuoye字段为二维TEXT数组,并且声明了数组

的长度。不过,目前 PostgreSQL 并不强制数组的长度,所以声明长度和不声明长度是一样的。

另外对于一维数组,也可以使用SQL 标准声明,SQL 语句如下:

PAY_BY_QUARTER INT ARRAY[5];

此种声明方式,仍然不强制数组的长度。

2、插入数组数值

插入数组元素时,用大括号把数组元素括起来并且用逗号将它们分开。

CREATE TABLE tmp12(bt int[]);
INSERT INTO tmp12 VALUES('{
   {1,1,1},{2,2,2},{3,3,3}}');
SELECT * FROM tmp12;
bt                       |
-------------------------+
{
  {1,1,1},{2,2,2},{3,3,3}}|

4.2 如何选择数据类型

PostgreSQL 提供了大量的数据类型,为了优化存储,提高数据库性能,在任何情况下均应使用最精确的类型。即

在所有可以表示该列值的类型中,该类型使用的存储空间最少。

4.2.1 整数和浮点数

如果不需要小数部分,则使用整数来保存数据;如果需要表示小数,则使用浮点数类型。对于浮点数据列,存入的

数值会被该列定义的小数位进行四舍五入。例如,如果列的值的范围为1~99999,若使用整数,则INT是最好的类

型;若需要存储小数,则使用浮点数类型。

4.2.2 日期与时间类型

PostgreSQL 对于不同种类的日期和时间有很多的数据类型,比如 TIME 和DATE。如果只记录时间,则使用 TIME

类型即可;如果只记录日期,只需使用DATE 类型。如果同时需要记录日期和时间,则可以使用 TIMESTAMP 类

型。默认情况下,当插入一条记录但并没有指定 TIMESTAMP 这个列值时,PostgreSQL 会把TIMESTAMP 列设为

当前的时间,因此当需要插入记录时、同时插入当前时间,使用 TIMESTAMP是方便的。

4.2.3 CHAR与VARCHAR 之间的特点与选择

CHAR 和VARCHAR的区别:CHAR是固定长度字符,VARCHAR是可变长度字符。对于插入数据长度不够时,CHAR

会自动填充插入数据的尾部空格,VARCHAR则不会。

由于CHAR是固定长度,所以它的处理速度比 VARCHAR 要快,但缺点就是浪费存储空间。所以对于存储量不大,

但在速度上有要求的数据可以使用CHAR 类型,反之可以使用 VARCHAR类型来实现。

4.3 常见运算符

运算符是用来告诉 PostgreSQL 执行特定算术或逻辑操作的符号。PostgreSQL的内部运算符很丰富,主要有四大

类,具体如下。

4.3.1 算术运算符

用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)。

CREATE TABLE tmp14(num INT);
INSERT INTO tmp14 VALUES(64);
SELECT num, num+10, num-10,num+5-3,num+36.5 FROM tmp14;
num|?column?|?column?|?column?|?column?|
---+--------+--------+--------+--------+
 64|      74|      54|      66|   100.5|
SELECT num,num *2,num/2,num/3,num%3 FROM tmp14;
num|?column?|?column?|?column?|?column?|
---+--------+--------+--------+--------+
 64|     128|      32|      21|       1|
# 报错
SELECT num, num /0, num %0 FROM tmp14;
4.3.2 比较运算符

用于比较运算。包括大于(>)、小于(<)、等于(=)、大于等于(>=)、小于等于(<=)、不等于(<> 或者!=)、以及

INBETWEEN ANDGREATESTLEASTLIKE等。

1、等于运算符=
SELECT 1=0,'2'=2,2=2,'b'='b',(1+3)=(2+1),NULL=NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
false   |true    |true    |true    |false   |        |

等于运算符在进行数值比较时有如下规则:

  • 若有一个或两个参数为 NULL,则比较运算的结果为空。

  • 若同一个比较运算中的两个参数都是字符串,则按照字符串进行比较。

  • 若两个参数均为整数,则按照整数进行比较。

  • 若一个字符串和数字进行相等判断,则 PostgreSQL可以自动将字符串转换为数字。

2、不等于运算符<>或者!=
SELECT 'good'<>'god',1<>2,4!=4,5.5!=5,(1+3)!=(2+1),NULL<>NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
true    |true    |false   |true    |true    |        |
3、小于等于运算符<=
SELECT 'good'<='god',1<=2,4<=4,5.5<=5,(1+3)<=(2+1),NULL<=NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
false   |true    |true    |false   |false   |        |
4、小于运算符<
SELECT 'good'<'god',1<2,4<4,5.5<5,(1+3)<(2+1),NULL<NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
false   |true    |false   |false   |false   |        |
5、大于等于运算符>=
SELECT 'good'>='god',1>=2,4>=4,5.5>=5,(1+3)>=(2+1),NULL>=NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
true    |false   |true    |true    |true    |        |
6、大于运算符>
SELECT 'good'>'god',1>2,4>4,5.5>5,(1+3)>(2+1),NULL>NULL;
?column?|?column?|?column?|?column?|?column?|?column?|
--------+--------+--------+--------+--------+--------+
true    |false   |false   |true    |true    |        |
7、BETWEEN AND运算符

BETWEEN AND:判断一个值是否落在两个值之间。

SELECT 4 BETWEEN 2 AND 5,4 BETWEEN 4 AND 6,12 BETWEEN 9 AND 10;
?column?|?column?|?column?|
--------+--------+--------+
true    |true    |false   |
SELECT 'x' BETWEEN 'f' AND 'g','b' BETWEEN 'a' AND 'c';
?column?|?column?|
--------+--------+
false   |true    |
8、Last运算符

LEAST:在有两个或多个参数时,返回最小值。

SELECT least(2,0),least(20.0,3.0,100.5),least('a','c','b'),least(10,NULL);
least|least|least|least|
-----+-----+-----+-----+
    0|  3.0|a    |   10|
9、GREATEST运算符

GREATEST:当有两个或多个参数时,返回最大值。

SELECT greatest(2,0),greatest(20.0,3.0,100.5),greatest('a','c','b'),
greatest(10,NULL);
greatest|greatest|greatest|greatest|
--------+--------+--------+--------+
       2|   100.5|c       |      10|
10、IN、NOT IN运算符

IN:判断一个值是否是IN列表中的任意一个值。

SELECT 2 IN(1,2,5,8),
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值