热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

掌握MySQL数据库的基础语法与核心操作

本文详细介绍了MySQL数据库的基础语法与核心操作,涵盖从基础概念到具体应用的多个方面。首先,文章从基础知识入手,逐步深入到创建和修改数据表的操作。接着,详细讲解了如何进行数据的插入、更新与删除。在查询部分,不仅介绍了DISTINCT和LIMIT的使用方法,还探讨了排序、过滤和通配符的应用。此外,文章还涵盖了计算字段以及多种函数的使用,包括文本处理、日期和时间处理及数值处理等。通过这些内容,读者可以全面掌握MySQL数据库的核心操作技巧。

文章目录

    • 一、基础
    • 二、创建表
    • 三、修改表
    • 四、插入
    • 五、更新
    • 六、删除
    • 七、查询
      • DISTINCT
      • LIMIT
    • 八、排序
    • 九、过滤
    • 十、通配符
    • 十一、计算字段
    • 十二、函数
      • 汇总
      • 文本处理
      • 日期和时间处理
      • 数值处理
    • 十三、分组
    • 十四、子查询
    • 十五、连接
      • 内连接
      • 自连接
      • 自然连接
      • 外连接
    • 十六、组合查询
    • 十七、视图
    • 十八、存储过程
    • 十九、游标
    • 二十、触发器
    • 二十一、事务管理
    • 二十二、字符集
    • 二十三、权限管理
    • 参考资料


一、基础

模式定义了数据如何存储、存储什么样的数据以及数据如何分解等信息,数据库和表都有模式。

主键的值不允许修改,也不允许复用(不能将已经删除的主键值赋给新数据行的主键)。

SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL。各个 DBMS 都有自己的实现,如 PL/SQL、Transact-SQL 等。

SQL 语句不区分大小写,但是数据库表名、列名和值是否区分依赖于具体的 DBMS 以及配置。

SQL 支持以下三种注释:

## 注释
SELECT *
FROM mytable; -- 注释
/* 注释1注释2 */

数据库创建与使用:

CREATE DATABASE test;
USE test;

二、创建表

CREATE TABLE mytable (# int 类型,不为空,自增id INT NOT NULL AUTO_INCREMENT,# int 类型,不可为空,默认值为 1,不为空col1 INT NOT NULL DEFAULT 1,# 变长字符串类型,最长为 45 个字符,可以为空col2 VARCHAR(45) NULL,# 日期类型,可为空col3 DATE NULL,# 设置主键为 idPRIMARY KEY (`id`));

三、修改表

添加列

ALTER TABLE mytable
ADD col CHAR(20);

删除列

ALTER TABLE mytable
DROP COLUMN col;

删除表

DROP TABLE mytable;

四、插入

普通插入

INSERT INTO mytable(col1, col2)
VALUES(val1, val2);

插入检索出来的数据

INSERT INTO mytable1(col1, col2)
SELECT col1, col2
FROM mytable2;

将一个表的内容插入到一个新表

CREATE TABLE newtable AS
SELECT * FROM mytable;

五、更新

UPDATE mytable
SET col = val
WHERE id = 1;

六、删除

DELETE FROM mytable
WHERE id = 1;

TRUNCATE TABLE 可以清空表,也就是删除所有行。

TRUNCATE TABLE mytable;

使用更新和删除操作时一定要用 WHERE 子句,不然会把整张表的数据都破坏。可以先用 SELECT 语句进行测试,防止错误删除。

七、查询


DISTINCT

相同值只会出现一次。它作用于所有列,也就是说所有列的值都相同才算相同。

SELECT DISTINCT col1, col2
FROM mytable;

LIMIT

限制返回的行数。可以有两个参数,第一个参数为起始行,从 0 开始;第二个参数为返回的总行数。

返回前 5 行:

SELECT *
FROM mytable
LIMIT 5;

SELECT *
FROM mytable
LIMIT 0, 5;

返回第 3 ~ 5 行:

SELECT *
FROM mytable
LIMIT 2, 3;

八、排序


  • ASC :升序(默认)
  • DESC :降序

可以按多个列进行排序,并且为每个列指定不同的排序方式:

SELECT *
FROM mytable
ORDER BY col1 DESC, col2 ASC;

九、过滤

不进行过滤的数据非常大,导致通过网络传输了多余的数据,从而浪费了网络带宽。因此尽量使用 SQL 语句来过滤不必要的数据,而不是传输所有的数据到客户端中然后由客户端进行过滤。

SELECT *
FROM mytable
WHERE col IS NULL;

下表显示了 WHERE 子句可用的操作符

操作符说明
=等于
<小于
>大于
<> !&#61;不等于
<&#61; !>小于等于
>&#61; !<大于等于
BETWEEN在两个值之间
IS NULL为 NULL 值

应该注意到&#xff0c;NULL 与 0、空字符串都不同。

AND 和 OR 用于连接多个过滤条件。优先处理 AND&#xff0c;当一个过滤表达式涉及到多个 AND 和 OR 时&#xff0c;可以使用 () 来决定优先级&#xff0c;使得优先级关系更清晰。

IN 操作符用于匹配一组值&#xff0c;其后也可以接一个 SELECT 子句&#xff0c;从而匹配子查询得到的一组值。

NOT 操作符用于否定一个条件。

十、通配符

通配符也是用在过滤语句中&#xff0c;但它只能用于文本字段。

  • % 匹配 >&#61;0 个任意字符&#xff1b;

  • _ 匹配 &#61;&#61;1 个任意字符&#xff1b;

  • [ ] 可以匹配集合内的字符&#xff0c;例如 [ab] 将匹配字符 a 或者 b。用脱字符 ^ 可以对其进行否定&#xff0c;也就是不匹配集合内的字符。

使用 Like 来进行通配符匹配。

SELECT *
FROM mytable
WHERE col LIKE &#39;[^AB]%&#39;; -- 不以 A 和 B 开头的任意文本

不要滥用通配符&#xff0c;通配符位于开头处匹配会非常慢。

十一、计算字段

在数据库服务器上完成数据的转换和格式化的工作往往比客户端上快得多&#xff0c;并且转换和格式化后的数据量更少的话可以减少网络通信量。

计算字段通常需要使用 AS 来取别名&#xff0c;否则输出的时候字段名为计算表达式。

SELECT col1 * col2 AS alias
FROM mytable;

CONCAT() 用于连接两个字段。许多数据库会使用空格把一个值填充为列宽&#xff0c;因此连接的结果会出现一些不必要的空格&#xff0c;使用 TRIM() 可以去除首尾空格。

SELECT CONCAT(TRIM(col1), &#39;(&#39;, TRIM(col2), &#39;)&#39;) AS concat_col
FROM mytable;

十二、函数

各个 DBMS 的函数都是不相同的&#xff0c;因此不可移植&#xff0c;以下主要是 MySQL 的函数。

汇总


函 数说 明
AVG()返回某列的平均值
COUNT()返回某列的行数
MAX()返回某列的最大值
MIN()返回某列的最小值
SUM()返回某列值之和

AVG() 会忽略 NULL 行。

使用 DISTINCT 可以汇总不同的值。

SELECT AVG(DISTINCT col1) AS avg_col
FROM mytable;

文本处理


函数说明
LEFT()左边的字符
RIGHT()右边的字符
LOWER()转换为小写字符
UPPER()转换为大写字符
LTRIM()去除左边的空格
RTRIM()去除右边的空格
LENGTH()长度
SOUNDEX()转换为语音值

其中&#xff0c; SOUNDEX() 可以将一个字符串转换为描述其语音表示的字母数字模式。

SELECT *
FROM mytable
WHERE SOUNDEX(col1) &#61; SOUNDEX(&#39;apple&#39;)

日期和时间处理


  • 日期格式&#xff1a;YYYY-MM-DD
  • 时间格式&#xff1a;HH:MM:SS

函 数说 明
ADDDATE()增加一个日期&#xff08;天、周等&#xff09;
ADDTIME()增加一个时间&#xff08;时、分等&#xff09;
CURDATE()返回当前日期
CURTIME()返回当前时间
DATE()返回日期时间的日期部分
DATEDIFF()计算两个日期之差
DATE_ADD()高度灵活的日期运算函数
DATE_FORMAT()返回一个格式化的日期或时间串
DAY()返回一个日期的天数部分
DAYOFWEEK()对于一个日期&#xff0c;返回对应的星期几
HOUR()返回一个时间的小时部分
MINUTE()返回一个时间的分钟部分
MONTH()返回一个日期的月份部分
NOW()返回当前日期和时间
SECOND()返回一个时间的秒部分
TIME()返回一个日期时间的时间部分
YEAR()返回一个日期的年份部分

mysql> SELECT NOW();

2018-4-14 20:25:11

数值处理


函数说明
SIN()正弦
COS()余弦
TAN()正切
ABS()绝对值
SQRT()平方根
MOD()余数
EXP()指数
PI()圆周率
RAND()随机数

十三、分组

把具有相同的数据值的行放在同一组中。

可以对同一分组数据使用汇总函数进行处理&#xff0c;例如求分组数据的平均值等。

指定的分组字段除了能按该字段进行分组&#xff0c;也会自动按该字段进行排序。

SELECT col, COUNT(*) AS num
FROM mytable
GROUP BY col;

GROUP BY 自动按分组字段进行排序&#xff0c;ORDER BY 也可以按汇总字段来进行排序。

SELECT col, COUNT(*) AS num
FROM mytable
GROUP BY col
ORDER BY num;

WHERE 过滤行&#xff0c;HAVING 过滤分组&#xff0c;行过滤应当先于分组过滤。

SELECT col, COUNT(*) AS num
FROM mytable
WHERE col > 2
GROUP BY col
HAVING num >&#61; 2;

分组规定&#xff1a;

  • GROUP BY 子句出现在 WHERE 子句之后&#xff0c;ORDER BY 子句之前&#xff1b;
  • 除了汇总字段外&#xff0c;SELECT 语句中的每一字段都必须在 GROUP BY 子句中给出&#xff1b;
  • NULL 的行会单独分为一组&#xff1b;
  • 大多数 SQL 实现不支持 GROUP BY 列具有可变长度的数据类型。

十四、子查询

子查询中只能返回一个字段的数据。

可以将子查询的结果作为 WHRER 语句的过滤条件&#xff1a;

SELECT *
FROM mytable1
WHERE col1 IN (SELECT col2FROM mytable2);

下面的语句可以检索出客户的订单数量&#xff0c;子查询语句会对第一个查询检索出的每个客户执行一次&#xff1a;

SELECT cust_name, (SELECT COUNT(*)FROM OrdersWHERE Orders.cust_id &#61; Customers.cust_id)AS orders_num
FROM Customers
ORDER BY cust_name;

十五、连接

连接用于连接多个表&#xff0c;使用 JOIN 关键字&#xff0c;并且条件语句使用 ON 而不是 WHERE。

连接可以替换子查询&#xff0c;并且比子查询的效率一般会更快。

可以用 AS 给列名、计算字段和表名取别名&#xff0c;给表名取别名是为了简化 SQL 语句以及连接相同表。

内连接

内连接又称等值连接&#xff0c;使用 INNER JOIN 关键字。

SELECT A.value, B.value
FROM tablea AS A INNER JOIN tableb AS B
ON A.key &#61; B.key;

可以不明确使用 INNER JOIN&#xff0c;而使用普通查询并在 WHERE 中将两个表中要连接的列用等值方法连接起来。

SELECT A.value, B.value
FROM tablea AS A, tableb AS B
WHERE A.key &#61; B.key;

自连接

自连接可以看成内连接的一种&#xff0c;只是连接的表是自身而已。

一张员工表&#xff0c;包含员工姓名和员工所属部门&#xff0c;要找出与 Jim 处在同一部门的所有员工姓名。

子查询版本

SELECT name
FROM employee
WHERE department &#61; (SELECT departmentFROM employeeWHERE name &#61; "Jim");

自连接版本

SELECT e1.name
FROM employee AS e1 INNER JOIN employee AS e2
ON e1.department &#61; e2.departmentAND e2.name &#61; "Jim";

自然连接

自然连接是把同名列通过等值测试连接起来的&#xff0c;同名列可以有多个。

内连接和自然连接的区别&#xff1a;内连接提供连接的列&#xff0c;而自然连接自动连接所有同名列。

SELECT A.value, B.value
FROM tablea AS A NATURAL JOIN tableb AS B;

外连接

外连接保留了没有关联的那些行。分为左外连接&#xff0c;右外连接以及全外连接&#xff0c;左外连接就是保留左表没有关联的行。

检索所有顾客的订单信息&#xff0c;包括还没有订单信息的顾客。

SELECT Customers.cust_id, Customer.cust_name, Orders.order_id
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id &#61; Orders.cust_id;

customers 表&#xff1a;

cust_idcust_name
1a
2b
3c

orders 表&#xff1a;

order_idcust_id
11
21
33
43

结果&#xff1a;

cust_idcust_nameorder_id
1a1
1a2
3c3
3c4
2bNull

十六、组合查询

使用 UNION 来组合两个查询&#xff0c;如果第一个查询返回 M 行&#xff0c;第二个查询返回 N 行&#xff0c;那么组合查询的结果一般为 M&#43;N 行。

每个查询必须包含相同的列、表达式和聚集函数。

默认会去除相同行&#xff0c;如果需要保留相同行&#xff0c;使用 UNION ALL。

只能包含一个 ORDER BY 子句&#xff0c;并且必须位于语句的最后。

SELECT col
FROM mytable
WHERE col &#61; 1
UNION
SELECT col
FROM mytable
WHERE col &#61;2;

十七、视图

视图是虚拟的表&#xff0c;本身不包含数据&#xff0c;也就不能对其进行索引操作。

对视图的操作和对普通表的操作一样。

视图具有如下好处&#xff1a;

  • 简化复杂的 SQL 操作&#xff0c;比如复杂的连接&#xff1b;
  • 只使用实际表的一部分数据&#xff1b;
  • 通过只给用户访问视图的权限&#xff0c;保证数据的安全性&#xff1b;
  • 更改数据格式和表示。

CREATE VIEW myview AS
SELECT Concat(col1, col2) AS concat_col, col3*col4 AS compute_col
FROM mytable
WHERE col5 &#61; val;

十八、存储过程

存储过程可以看成是对一系列 SQL 操作的批处理。

使用存储过程的好处&#xff1a;

  • 代码封装&#xff0c;保证了一定的安全性&#xff1b;
  • 代码复用&#xff1b;
  • 由于是预先编译&#xff0c;因此具有很高的性能。

命令行中创建存储过程需要自定义分隔符&#xff0c;因为命令行是以 ; 为结束符&#xff0c;而存储过程中也包含了分号&#xff0c;因此会错误把这部分分号当成是结束符&#xff0c;造成语法错误。

包含 in、out 和 inout 三种参数。

给变量赋值都需要用 select into 语句。

每次只能给一个变量赋值&#xff0c;不支持集合的操作。

delimiter //create procedure myprocedure( out ret int )begindeclare y int;select sum(col1)from mytableinto y;select y*y into ret;end //delimiter ;

call myprocedure(&#64;ret);
select &#64;ret;

十九、游标

在存储过程中使用游标可以对一个结果集进行移动遍历。

游标主要用于交互式应用&#xff0c;其中用户需要对数据集中的任意行进行浏览和修改。

使用游标的四个步骤&#xff1a;

  1. 声明游标&#xff0c;这个过程没有实际检索出数据&#xff1b;
  2. 打开游标&#xff1b;
  3. 取出数据&#xff1b;
  4. 关闭游标&#xff1b;

delimiter //
create procedure myprocedure(out ret int)begindeclare done boolean default 0;declare mycursor cursor forselect col1 from mytable;# 定义了一个 continue handler&#xff0c;当 sqlstate &#39;02000&#39; 这个条件出现时&#xff0c;会执行 set done &#61; 1declare continue handler for sqlstate &#39;02000&#39; set done &#61; 1;open mycursor;repeatfetch mycursor into ret;select ret;until done end repeat;close mycursor;end //delimiter ;

二十、触发器

触发器会在某个表执行以下语句时而自动执行&#xff1a;DELETE、INSERT、UPDATE。

触发器必须指定在语句执行之前还是之后自动执行&#xff0c;之前执行使用 BEFORE 关键字&#xff0c;之后执行使用 AFTER 关键字。BEFORE 用于数据验证和净化&#xff0c;AFTER 用于审计跟踪&#xff0c;将修改记录到另外一张表中。

INSERT 触发器包含一个名为 NEW 的虚拟表。

CREATE TRIGGER mytrigger AFTER INSERT ON mytable
FOR EACH ROW SELECT NEW.col into &#64;result;SELECT &#64;result; -- 获取结果

DELETE 触发器包含一个名为 OLD 的虚拟表&#xff0c;并且是只读的。

UPDATE 触发器包含一个名为 NEW 和一个名为 OLD 的虚拟表&#xff0c;其中 NEW 是可以被修改的&#xff0c;而 OLD 是只读的。

MySQL 不允许在触发器中使用 CALL 语句&#xff0c;也就是不能调用存储过程。

二十一、事务管理

基本术语&#xff1a;

  • 事务&#xff08;transaction&#xff09;指一组 SQL 语句&#xff1b;
  • 回退&#xff08;rollback&#xff09;指撤销指定 SQL 语句的过程&#xff1b;
  • 提交&#xff08;commit&#xff09;指将未存储的 SQL 语句结果写入数据库表&#xff1b;
  • 保留点&#xff08;savepoint&#xff09;指事务处理中设置的临时占位符&#xff08;placeholder&#xff09;&#xff0c;你可以对它发布回退&#xff08;与回退整个事务处理不同&#xff09;。

不能回退 SELECT 语句&#xff0c;回退 SELECT 语句也没意义&#xff1b;也不能回退 CREATE 和 DROP 语句。

MySQL 的事务提交默认是隐式提交&#xff0c;每执行一条语句就把这条语句当成一个事务然后进行提交。当出现 START TRANSACTION 语句时&#xff0c;会关闭隐式提交&#xff1b;当 COMMIT 或 ROLLBACK 语句执行后&#xff0c;事务会自动关闭&#xff0c;重新恢复隐式提交。

设置 autocommit 为 0 可以取消自动提交&#xff1b;autocommit 标记是针对每个连接而不是针对服务器的。

如果没有设置保留点&#xff0c;ROLLBACK 会回退到 START TRANSACTION 语句处&#xff1b;如果设置了保留点&#xff0c;并且在 ROLLBACK 中指定该保留点&#xff0c;则会回退到该保留点。

START TRANSACTION
// ...
SAVEPOINT delete1
// ...
ROLLBACK TO delete1
// ...
COMMIT

二十二、字符集

基本术语&#xff1a;

  • 字符集为字母和符号的集合&#xff1b;
  • 编码为某个字符集成员的内部表示&#xff1b;
  • 校对字符指定如何比较&#xff0c;主要用于排序和分组。

除了给表指定字符集和校对外&#xff0c;也可以给列指定&#xff1a;

CREATE TABLE mytable
(col VARCHAR(10) CHARACTER SET latin COLLATE latin1_general_ci )
DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;

可以在排序、分组时指定校对&#xff1a;

SELECT *
FROM mytable
ORDER BY col COLLATE latin1_general_ci;

二十三、权限管理

MySQL 的账户信息保存在 mysql 这个数据库中。

USE mysql;
SELECT user FROM user;

创建账户

新创建的账户没有任何权限。

CREATE USER myuser IDENTIFIED BY &#39;mypassword&#39;;

修改账户名

RENAME USER myuser TO newuser;

删除账户

DROP USER myuser;

查看权限

SHOW GRANTS FOR myuser;

授予权限

账户用 username&#64;host 的形式定义&#xff0c;username&#64;% 使用的是默认主机名。

GRANT SELECT, INSERT ON mydatabase.* TO myuser;

删除权限

GRANT 和 REVOKE 可在几个层次上控制访问权限&#xff1a;

  • 整个服务器&#xff0c;使用 GRANT ALL 和 REVOKE ALL&#xff1b;
  • 整个数据库&#xff0c;使用 ON database.*&#xff1b;
  • 特定的表&#xff0c;使用 ON database.table&#xff1b;
  • 特定的列&#xff1b;
  • 特定的存储过程。

REVOKE SELECT, INSERT ON mydatabase.* FROM myuser;

更改密码

必须使用 Password() 函数进行加密。

SET PASSWROD FOR myuser &#61; Password(&#39;new_password&#39;);

参考资料


  • BenForta. SQL 必知必会 [M]. 人民邮电出版社, 2013.

推荐阅读
  • 目录一、salt-job管理#job存放数据目录#缓存时间设置#Others二、returns模块配置job数据入库#配置returns返回值信息#mysql安全设置#创建模块相关 ... [详细]
  • 本文介绍 SQL Server 的基本概念和操作,涵盖系统数据库、常用数据类型、表的创建及增删改查等基础操作。通过实例帮助读者快速上手 SQL Server 数据库管理。 ... [详细]
  • 优化SQL Server批量数据插入存储过程的实现
    本文介绍了一种改进的SQL Server存储过程,用于生成批量插入语句。该方法不仅提高了性能,还支持单行和多行模式,适用于SQL Server 2005及以上版本。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 本文深入探讨了SQL数据库中常见的面试问题,包括如何获取自增字段的当前值、防止SQL注入的方法、游标的作用与使用、索引的形式及其优缺点,以及事务和存储过程的概念。通过详细的解答和示例,帮助读者更好地理解和应对这些技术问题。 ... [详细]
  • 1.执行sqlsever存储过程,消息:SQLServer阻止了对组件“AdHocDistributedQueries”的STATEMENT“OpenRowsetOpenDatas ... [详细]
  • 本文详细介绍了一种通过MySQL弱口令漏洞在Windows操作系统上获取SYSTEM权限的方法。该方法涉及使用自定义UDF DLL文件来执行任意命令,从而实现对远程服务器的完全控制。 ... [详细]
  • MySQL 基础操作与优化
    本文详细介绍了 MySQL 的基础连接、数据库及表的操作,涵盖创建、修改、删除等常用命令,并深入解析了数据类型、列属性、索引、外键和存储引擎等内容。 ... [详细]
  • Python + Pytest 接口自动化测试中 Token 关联登录的实现方法
    本文将深入探讨 Python 和 Pytest 在接口自动化测试中如何实现 Token 关联登录,内容详尽、逻辑清晰,旨在帮助读者掌握这一关键技能。 ... [详细]
  • 本文探讨了在 SQL Server 中使用 JDBC 插入数据时遇到的问题。通过详细分析代码和数据库配置,提供了解决方案并解释了潜在的原因。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • Oracle中NULL、空字符串和空格的处理与区别
    本文探讨了在Oracle数据库中使用NULL、空字符串('')和空格('_')时可能遇到的问题及解决方案。重点解释了它们之间的区别,以及在查询和函数中的行为。 ... [详细]
  • 探讨 HDU 1536 题目,即 S-Nim 游戏的博弈策略。通过 SG 函数分析游戏胜负的关键,并介绍如何编程实现解决方案。 ... [详细]
  • 版本控制工具——Git常用操作(下)
    本文由云+社区发表作者:工程师小熊摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码、使用分支、出现代码冲突的解决办法、紧急保存现场和恢复 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
author-avatar
ningxiao088_272
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有