我是靠谱客的博主 爱听歌世界,最近开发中收集的这篇文章主要介绍查询mysql总结及预处理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

任务:进一步深入mysqli_multi_query()用法。
一、连接到mysql:
$dbc = mysqli_connect(host,user,password,databasename);
等价于:
$dbc = mysqli_connect(host,user,pwd);
mysqli_select_db($dbc,db_name);
如果发生错误,可以调用:mysqli_connect_error() 返回错误信息,不带参数。
$dbc = @mysqli_connect(host,user,pwd,db) or die(’无法连接到mysql:’.mysqli_connect_error());
@是错误控制运算符,防止在web浏览器显示php错误。此外,@也可以放在mysqli_query前面。上面是一种首选做法,因为错误将由or die处理。die()会终止脚本执行。
可以将连接文件放在路径外。
设置编码:mysqli_query(”set names gb2312″);
二、执行查询:
不管是select, delete, update,insert 查询都是用:
$result=mysqli_query($dbc,SQL);
对于insert ,delete,update等查询不会返回结果,$result将返回true或false,因此可以用这个来判断下一步:
$result = mysqli_query($dbc,sql);
if($result) {//susses}
如果查询没有成功,必定发生某种mysql错误,可能调用
mysqli_error($dbc)    //注意和mysqli_connect_error()区别
三、关闭连接:
mysqli_close($dbc) 这不是必需要的,php会在脚本最后自动关闭,但最好写上。
四、多条查询:
mysqli_multi_query()允许同时执行多条查询。但语法更复杂一点。特别是当返回结果时。
五、检索select查询结果:
mysqli_fetch_array($result [, type])是最常用的,以数组格式一次返回一行数据。由它来配合while()来遍历返回数据。带有一个可选参数type,用于指定返回的数组类型:关联的还是索引的,或二者均可。参数类型如下:
MYSQLI_ASSOC   示例:$rows['columnName']
MYSQLI_NUM 示例:$rows[0] ,这一种效率较高一点。
MYSQLI_BOTH 示例:$rows[0]或$rows['columnName']
当使用mysqli_fetch_array($result [, type])后,可以采取一个可选步聚的是:一旦查询结果完成了工作,即可释放这些信息,来消除$result占用的系统内存开销。这一步是可选的,PHP同样也在会结果时自动清理:
mysqli_free_result($result)   //注意参数是不是$rows!
流程如下:
while($rows=mysqli_fetch_array($result))   //或while($rows=mysqli_fetch_array($result,MYSQLI_ASSOC))
{//遍历
……code do something……
echo $rows[0]
mysqli_free_result($result)
}
注意:
mysqli_fetch_array()和mysqli_fetch_array($result,MYSQLI_NUM)等价。
mysqli_fetch_assoc()和mysqli_fetch_array($result,MYSQLI_ASSOC)等价。
六、确保sql安全,使用转义函数:
mysqli_real_escape_string($dbc,para)
该函数用于检验用户提交的并将组合到sql查询语句的变量值,它将转义那些有可能无意或带恶意的字符。如单引号,在外国人的姓名有可能会包含该符号(如O’Toole),这时就需要用它。
案例:
$name = $_POST['name'];
$name = mysqli_real_escape_string($dbc,$name);
$query = “Select … From tb where name=’$name’”; //这样可以确保带入sql 时参数的安全。
注意:如果在使用php6之前的版本,若启用MAGIC QUOTES魔法引用时,那么在使用mysqli_real_escape_string前,需要用stripslashes(para)删除魔法引用添加的任何斜杠,如下:
$fn = mysqli_real_escape_string($dbc,trim(stripslashes($_POST['firstName'])));
七、统计select返回的记录数:
使用mysqli_num_rows($result)统计select 返回的结果行数。$num=mysqli_num_rows($r),对于上面所说的while流程,可以更改成以下更严谨的写法,而不只是分析查询是否成功,因为如果数据库为空的话,就不会出错。
$sql = “select * from tb where id=$id”;
$r = @mysqli_query($dbc,$sql);
$num = mysqli_num_rows($r);
if($num>0){ //这样比if($r)更准确。不是仅仅分析是否成功运行。
// Do something;
mysqli_free_result($r)
}
mysqli_close($dbc);
八、返回insert ,update,delete受影响行数:
和上面不同的是,如果查询不是select则用mysqli_affected_rows()函数返回受影响行数。用法如下:
$num = mysqli_affected_rows($dbc); //注意参数是$dbc;
如:
$q = “update tb set pass=SHA1(’$newpassword’) where id=$row[0]“;
$r = @myslqi_query($dbc,$q);
if(mysqli_affected_rows($dbc)==1){
//Do something
}else{
echo mysqli_error($dbc);
exit(); //终止脚本。
}
注意:
1、如果使用truncate tb清空表时,则mysqli_affected_rows()会返回0,即使查询成功执行并且删除了每一行。
2、如果用update查询时,但实质上没有更改任何列的值,比如用相同的密码代替一个旧密码,则也会返回0。
九、批量查询:预处理语句(第12章第4节:P311)
版本:MYSQL 4.1开始添加预处理。php5可以使用。
预处理的好处:
1、更大安全性。2、更好性能。3、批量查询。
对于预处理语句,只会把查询本身发送给mysql,并且只会解析一次,然后单独把值发送给mysql。
$q = ‘Insert into tb(num) values (?)’;
$stmt = mysqli_prepare($dbc,$q); mysqli_stmt_bind_param($stmt,’i',$n); for($n=1;$n=100;$n++) { mysqli_stmt_execute($stmt); } 可以通过insert , update , delete , select 查询创建预处理,

步骤: 1

$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,’i',$n);
for($n=1;$n<=100;$n++)
{
mysqli_stmt_execute($stmt);
}
可以通过insert , update , delete , select 查询创建预处理,步骤:
1、定义查询:
$q = “select firstname,lastname from users where uid = ?”;   //(正常则是uid=$id)
2、将查询传给mysql预处理:
$stmt = mysqli_prepare($dbc,$q);   //此时mysql会解析查询,但不会执行。
3、将变量绑定到查询占位符”?”,如下:
mysqli_stmt_bind_param($stmt,’i',$id);
其中’i'的含义是mysql_stmt_bind_param函数期望接收到的值为int类型,共有以下几种:
——————————————————————————–
字母                    表示绑定的值类型
d                             Decimal
i                               Integer
b                              Blob (二进制类型)
s                               所有其它类型
———————————————————————————-
如果查询语句有多个变量,如:
$q = “select uid,firstname from users where email=? AND pass=SHA1(?)”; //注意这里都没有对?问号加单引号,即使是字符型。这是和标准查询的区别。
多个变量直接在绑定时按顺序在引号内列出即可。如下:
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,’ss’,$e,$p);
还需要注意的时,在调用绑定函数前,可以不需要先对变量定义设置,如上面的$e,$p在下面才设置,这不会出错。
4、完成绑定后,可以给php变量赋值(如果还没有值的话)。然后执行语句。
$id=15;
mysqli_stmt_execute($stmt);
5、关闭预处理:
mysqli_stmt_close($stmt);
6、关闭连接
mysqli_close($dbc);
执行预处理时,如有出错则用mysqli_stmt_error($stmt)调用。
示例:
$dbc =mysqli_connect(’localhost’,'username’,'pwd’,'forum’);
$q = ‘insert into messages(forumid,parentid,userid,subject,body,forumdate) values(?,?,?,?,?,NOW())’;
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,’iiiss’,$forumid,$parentid,$userid,$subject,$body);
$forumid = (int)$_POST['forumid'];
$parentid=(int) $_POST['parentid'];
$user_id =3;
$subject = strip_tags($_POST['subject']); //strip_tags
$body = strip_tags($_POST['body']);
mysqli_stmt_execute($stmt);
if(mysqli_stmt_affected_rows($stmt)==1)
{
//do …
}else{
echo mysqli_stmt_error($stmt);
}
mysqli_stmt_close($stmt);
mysqli_close($dbc);
以上演示了预处理的一种语句,实际上预处理有两种语句:
1、绑定参数(bound parameter):如上面的示例
2、绑定结果(bound result):将查询结果绑定到php变量。
十、阻止sql注入:(第12章第4节:P311)
1、验证在查询中要使用的数据,如果有可能,就可执行类型强制转换。如:
$forumid = (int)$_POST['forumid'];
if($forumid>0) …   //如果强制转换成int完=0时,则不符数据型要求。
2、使用mysqli_real_escape_string($dbc,para)
3、使用mysqli_real_escape_string($dbc,para)替代办法:预处理,参上面。
十一、早先的php和mysql连接方式:
mysql_connect,在写法上只差上面一个字母i,但用法差不多。以下简单示例:
$conn = mysql_connect(”127.0.0.1″,”mysqltest”,”123456″);
mysql_select_db(”shop”); //如果用$selectdb = mysql_select_db(”shop”);则$selectdb=1
mysql_query(”set names gb2312″); //mysql_query(”set names utf8″);
$exec=”select * from product”;
$result=mysql_query($exec,$conn); //或:$result=mysql_query($exec);
while($rs=mysql_fetch_object($result))
{
echo “品名:[".$rs->pname . "] &nbsp;&nbsp;”;
echo “价格:”.
$rs->price . “&nbsp;&nbsp;”;
echo “入库时间:”.$rs->addTime . “&nbsp;&nbsp;”;
echo “<br />”;

} echo $result; 如果要进行结果判断有无再输出,则可以用: $conn = mysql_connect(127.0.0.1,mysqltest,123456); mysql_select_db(shop); mysql_query(set names gb2312); //mysql_query(set names utf8)

 

}
echo $result;
如果要进行结果判断有无再输出,则可以用:
$conn = mysql_connect(”127.0.0.1″,”mysqltest”,”123456″);
mysql_select_db(”shop”);
mysql_query(”set names gb2312″); //mysql_query(”set names utf8″);
$exec=”select * from product”;
if($result=mysql_query($exec,$conn)){
while($rs=mysql_fetch_object($result))
{
echo “品名:[".$rs->pname . "] &nbsp;&nbsp;”;
echo “价格:”.
$rs->price . “&nbsp;&nbsp;”;
echo “入库时间:”.$rs->addTime . “&nbsp;&nbsp;”;
echo “<br />”;
标签:查询mysql总结及预处理 分类:数据库房

菜鸟mysql错误代码和消息对照表

时间:2011年10月30日作者:小侃评论次数:0

朋友给我的一个mysql错误代码及对应信息表,对新手和英语感冒的同学有帮助。 东西比较大,贴一些常见的代码上来。剩下的大家下载附件看吧。 消息:无法创建文件’%s’ (errno: %d) 错误:1005 SQLSTATE: HY000 (ER_CANT_CREATE_TABLE) 消息:无法创建表’%s

朋友给我的一个mysql错误代码及对应信息表,对新手和英语感冒的同学有帮助。
东西比较大,贴一些常见的代码上来。剩下的大家下载附件看吧。
消息:无法创建文件’%s’ (errno: %d)
·错误:1005 SQLSTATE: HY000 (ER_CANT_CREATE_TABLE)
消息:无法创建表’%s’ (errno: %d)
·错误:1006 SQLSTATE: HY000 (ER_CANT_CREATE_DB)
消息:无法创建数据库’%s’ (errno: %d)
·错误:1007 SQLSTATE: HY000 (ER_DB_CREATE_EXISTS)
消息:无法创建数据库’%s’,数据库已存在。
·错误:1008 SQLSTATE: HY000 (ER_DB_DROP_EXISTS)
消息:无法撤销数据库’%s’,数据库不存在。
·错误:1009 SQLSTATE: HY000 (ER_DB_DROP_DELETE)
消息:撤销数据库时出错(无法删除’%s’,errno: %d)
·错误:1010 SQLSTATE: HY000 (ER_DB_DROP_RMDIR)
消息:撤销数据库时出错(can’t rmdir ‘%s’, errno: %d)
·错误:1011 SQLSTATE: HY000 (ER_CANT_DELETE_FILE)
消息:删除’%s’时出错 (errno: %d)
·错误:1012 SQLSTATE: HY000 (ER_CANT_FIND_SYSTEM_REC)
消息:无法读取系统表中的记录。
·错误:1021 SQLSTATE: HY000 (ER_DISK_FULL)
消息:磁盘满(%s);等待某人释放一些空间…
·错误:1044 SQLSTATE: 42000 (ER_DBACCESS_DENIED_ERROR)
消息:拒绝用户’%s’@'%s’访问数据库’%s’。
·错误:1045 SQLSTATE: 28000 (ER_ACCESS_DENIED_ERROR)
消息:拒绝用户’%s’@'%s’的访问(使用密码:%s)
·错误:1046 SQLSTATE: 3D000 (ER_NO_DB_ERROR)
消息:未选择数据库。
·错误:1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
消息:未知命令。

标签:mysql对照表 分类:数据库房

mysql多实例启动的几个错误分析

时间:2011年10月30日作者:小侃评论次数:0

昨天布置一台mysql服务器,需要用到几个实例测试,原来布置的时候一直比较顺利,这次却碰到了几个问题,贴出了共享呢一下! 1. 111019 15:04:28 mysqld_safe The file /usr/local/mysql/bin/mysqld does not exist or is not executable. Please cd to the m

昨天布置一台mysql服务器,需要用到几个实例测试,原来布置的时候一直比较顺利,这次却碰到了几个问题,贴出了共享呢一下!
1. 111019 15:04:28 mysqld_safe The file /usr/local/mysql/bin/mysqld
does not exist or is not executable. Please cd to the mysql installation
directory and restart this script from there as follows:
./bin/mysqld_safe&
See http://dev.mysql.com/doc/mysql/en/mysqld-safe.html for more information
错误码如上,之前没有出现过,现在出现的是mysqld_safe在调用/usr/local/mysql/bin/mysqld的时候 这个文件不存在或者是不能够执行。这个是因为我在/etc/my.cnf这个地方没有指定在每个实例节点的basedir,添加上去basedir=/opt/mysql/即可
2. WARNING: Log file disabled. Maybe directory or file isn’t writable?
mysqld_multi log file version 2.16; run: Wed Oct 19 15:07:28 2011 Starting MySQL servers
111019 15:07:29 mysqld_safe Logging to ‘/data/mysql_data/error.err’.
111019 15:07:29 mysqld_safe Logging to ‘/data/mysql_data3307/error.err’.
111019 15:07:29 mysqld_safe Logging to ‘/data/mysql_data3307/error.err’.
111019 15:07:29 mysqld_safe Starting mysqld daemon with databases from /data/mysql_data/
111019 15:07:29 mysqld_safe Starting mysqld daemon with databases from /data/mysql_data3307/
111019 15:07:29 mysqld_safe Starting mysqld daemon with databases from /data/mysql_data3308/
会有如上提示,意思是mysqld_mutil多实例启动一个日志文件没有找到或者没有权限写入,而且把这些日志信息打印出来,非常不好。
解决方法:在[mysqld_mutil]这个节点下加一个log = /opt/mysql/mysqld_mutil.err即可,启动不会有如上警告且不会将日志信息打印在屏幕上,可在日志文件中查看
3. Can’t execute /usr/local/mysql/bin//mysqld_multi from dir /usr/local/
该错误是因为没有找到mysqld_mutil这个启动文件,因为我的mysql安装文件不放在/usr/local这个目录下,所有会出现如上三个错误。
另外,还不知如上几个错误,大部分错误是以为我没有将mysql安装在/usr/local目录下面,之前一直放在该目录下面。所以,大家在安装mysql的时候 ,尽量放在/usr/local目录下,若一定不放在该目录下面,需要修改几处配置文件,一般为/etc/init.d/mysqld_m、mysqld_mutil、my.cnf这些常见的配置文件中的数据存放路径、基础路径、日志路径等

标签:mysql多实例启动错误分析 分类:数据库房

数据库的分页查询

时间:2011年10月23日作者:小侃评论次数:0

sql语句分页多种方式ROW_NUMBER()OVER
方式一
select top @pageSize * from company where id not in
(select top @pageSize*(@pageIndex-1) id from company)
& nbsp;
方式二ROW_NUMBER()OVER
& nbsp;
–ROW_NUMBER() 就是生成一个有顺序的行号,而他生成顺序的标准,就是后面紧跟的OVER(ORDER BY ID)
–还必须添加OVER语句以便告诉SQL Server你希望怎样添加行序号。
select getdate()
select * from company where id in (
–搜索出settable表中所有的编号,也就是company表中的id,这里只不过要得到num(即有顺序的编号)
select id from
–搜索出出表中的所有的id,并且新建一列num用来存取排序的编号,并且把这张表赋值给settable
(select id,row_number() over (order by id) as
num from company)
as settable
–添加搜索条件页索引和页大小
where num between (@pageIndex-1)*@pageSize+1 and @pageIndex*@pageSize)
select getdate()
& nbsp;
方式三
SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY id asc) AS rownum,
id
FROM company ) AS D
WHERE rownum BETWEEN (@pageIndex-1)*@pageSize+1 AND @pageIndex*@pageSize
ORDER BY id asc
& nbsp;
Sql Server 2000的自定义分页,但是在sql server 2000中,要实现显示某一页,就返回那一页数据的效果的方法实在不尽人意.网上很多通用的分页存储过程,但看着就头大.如果使用我前面提到的使用in,not in,top来进行返回特定页,特殊的限制又会比较多(比如ID要递增).现在Sql Server 2005中提供了一个函数ROW_NUMBER(),可以使自定义分页变得简单许多.&nbsp;&nbsp;&nbsp;&nbsp; 我们先来看看ROW_NUMBER()是干什么的.执行下面这段SQL语句:&nbsp;&nbsp;&nbsp;&nbsp; SELECT [ReportID],[UserName], [ReportID],&nbsp;&nbsp;&nbsp;&nbsp; [TimeStart], [TimeEnd],ROW_NUMBER() OVER (ORDER BY ReportID) AS RowNo&nbsp;&nbsp;&nbsp;&nbsp; FROM [ExecutionLog]很简单,ROW_NUMBER() 就是生成一个顺序的行号,而他生成顺序的标准,就是后面紧跟的OVER(ORDER BY ReportID).现在,你看到了自定义分页的影子了吗?:)下面,我们看看怎么具体应用这个RowNo进行分页.&nbsp;&nbsp;&nbsp;&nbsp; 现在,假设我每一页的数据是10条,我们就可以使用如下所示的SQL语句返回指定页的数据:&nbsp;&nbsp;&nbsp;&nbsp; @”&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT TOP 10 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT top 10 [InstanceName], [UserName], [ReportID],&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [TimeStart], [TimeEnd],ROW_NUMBER() OVER (ORDER BY ReportID) AS RowNo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM [ExecutionLog]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) AS A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE RowNo > ” + pageIndex*10&nbsp;&nbsp;&nbsp;&nbsp; pageIndex就是我们需要数据的页数.很简单,不是吗?并且,这种方式几乎没有什么限制,因为他相当于对于任何检索,都生成了一个新的排序列.我们就可以使用该列进行自定义分页.
================
下面举个例子:
ROW_NUMBER函数
SQL Server2005为我们引入了一个ROW_NUMBER函数。你是否曾经需要为你的查询结果集做行序号?你有时会发现能够为行做序号是一件很有用的事情。从前,你不得不作棘手的事,像创建一个有序号列的临时表,然后把你的SELECT结果插入到这个临时表中。现在,用ROW_NUMBER函数,你就可以获得添加在你的结果集的增加列中的行序号。为了获得行序号,你只要简单的将ROW_NUMBER函数作为一列添加进你的SELECT语句中。你还必须添加OVER语句以便告诉SQL Server你希望怎样添加行序号。
SELECT ROW_NUMBER() OVER(ORDER BY employee_id) AS ‘Row Number’, * from  dbo.employee
结果
Row Number employee_id Firstname Lastname soc_sec1 5623222 Tim Jones 123-65-87452 5632111 Rob Kinkad 456-69-87543 6365666 Jim Miller 236-56-89894 7563333 Joe Roberts 564-89-5555
这个查询返回所有的雇员和一个显示每条记录在哪一行的一个序号。OVER语句使SQL Server基于employee_id列增加行序号。换句话说,产生了行序号,就好像数据按employee_id做了排序。这是很重要的一点,因为你仍然可以改变SELECT的排序顺序。以下面的查询为例:
SELECT ROW_NUMBER() OVER(ORDER BY employee_id) AS ‘Row Number’, * from  dbo.employee  ORDER BY soc_sec
结果
Row Number employee_id Firstname Lastname soc_sec1 5623222 Tim Jones 123-65-87453 6365666 Jim Miller 236-56-89892 5632111 Rob Kinkad 456-69-87544 7563333 Joe Roberts 564-89-5555
注意第二个结果集数据是按社会安全编号来排序的,但是行号仍然创建得好像数据是按employee_id排序的。
——————————-分页存储过程
IF EXISTS (SELECT * FROM sysobjects where name=’P_student’)DROP PROCEDURE P_studentgoCREATE PROCEDURE P_student@startIndex INT,&nbsp;&nbsp;&nbsp; @pageSize INTASbegin WITH studentList AS (SELECT ROW_NUMBER() OVER (ORDER BY O.stuid ) Row,O.stuid,O.stuname,O.stuage,O.stuinfofrom student O)
SELECT Row, stuid,stuname,stuage,stuinfoFROM studentListWHERE Row between @startIndex and @startIndex+@pageSize-1end
& nbsp;
& nbsp;
——————-分页2———
set ANSI_NULLS ONset QUOTED_IDENTIFIER ONGOALTER PROCEDURE [dbo].[Deer_Page](@startIndex INT,@pageSize INT,@strSql varchar(5000) —查询条件,@TableName varchar(50),@DoCount AS bit=1&nbsp;&nbsp;&nbsp;&nbsp; — 0值返回记录总数, 非 0 值则返回记录)ASbegin tranIF @DoCount=0&nbsp;&nbsp;&nbsp; Goto GetCountElse&nbsp;&nbsp;&nbsp; Goto GetSearch
GetCount: –返回记录总数&nbsp;&nbsp;&nbsp; DECLARE @SearchSql AS Nvarchar(4000)&nbsp;&nbsp;&nbsp; SET @SearchSql= ‘SELECT Count(*) AS Total FROM ‘+@TableName+’ WHERE IntReserve1=0′&nbsp;&nbsp;&nbsp; exec sp_executesql @SearchSql&nbsp;&nbsp;&nbsp; –print @SearchSqlCOMMIT TRAN&nbsp;&nbsp;&nbsp; return
GetSearch: –返回记录DECLARE @SqlQuery varchar(4000)SET @SqlQuery=’SELECT * FROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (SELECT ROW_NUMBER() OVER (ORDER BY O.ID ) Row, * from ‘+@TableName+’ O Where IntReserve1=0) as temp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE Row BETWEEN ‘+cast(@startIndex as varchar) +’ and ‘+cast(@startIndex+@pageSize-1 as varchar)+ @strsql—print @SqlQueryexecute(@SqlQuery)COMMIT TRAN

 

 

http://www.chnxiaokan.com/?cat=13

最后

以上就是爱听歌世界为你收集整理的查询mysql总结及预处理的全部内容,希望文章能够帮你解决查询mysql总结及预处理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部