PHP数据库-Mysql


PHP+Mysql是最流行的搭配。

连接

连接数据库是第一步,PHP中可以使用mysql_connect() 来连接,注意7.x已弃用该函数,5.x仍可使用,7.x可用mysqli_connect()
mysql_connect(servername,username,password);
例子:

<?php
$con = mysql_connect("localhost","root","root");
if (!$con)
  {
  die('Could not connect: ' . mysql_error());
  }
// some code
mysql_close($con);
?>

PHP脚本结束时,会自动关闭连接,如果需要提前可像例子中使用mysql_close()提前关闭。

执行SQL语句

建立连接后,就可以使用mysql_query(),向 MySQL 连接发送执行的SQL语句。
7.x使用mysqli_query()

  1. 建库
    mysql:CREATE DATABASE database_name
    创建名为 "my_db" 的数据库:mysql_query("CREATE DATABASE my_db",$con)
  2. 建表
    mysql:
CREATE TABLE table_name
(
column_name1 data_type,
.......
)

创建名为 "Persons" 的表,此表有三列。列名是 "FirstName", "LastName" 以及 "Age":

mysql_select_db("my_db", $con);
$sql = "CREATE TABLE Persons 
(
FirstName varchar(15),
LastName varchar(15),
Age int
)";
mysql_query($sql,$con);

在对某个数据库内的表操作时,必须先用mysql_select_db()选择对应数据库
7.x使用mysqli_select_db()


  1. mysql:INSERT INTO table_name VALUES (value1, value2,....)INSERT INTO table_name (column1, column2,...) VALUES (value1, value2,....)

SQL语句对大小写不敏感

向 "Persons" 表添加了一个新记录:

mysql_select_db("my_db", $con);
mysql_query("INSERT INTO Persons (FirstName, LastName, Age) VALUES ('Peter', 'Griffin', '35')");

  1. mysql:SELECT column_name(s) FROM table_name
    PHP:
    下面这个例子在 $result 变量中存放由 mysql_query() 函数返回的数据。使用 mysql_fetch_array() 函数以数组的形式从记录集返回第一行。每个随后对 mysql_fetch_array() 函数的调用都会返回记录集中的下一行。
mysql_select_db("my_db", $con);
$result = mysql_query("SELECT * FROM Persons");
while($row = mysql_fetch_array($result))
 {
 echo $row['FirstName'] . " " . $row['LastName'];
 echo "<br />";
 }

  1. 修改表中某行某列的值:UPDATE table_name SET column_name = new_value WHERE column_name = some_value
    修改Persons表中FirstName为Peter且LastName为Griffin的行中Age列的值为36:mysql_query("UPDATE Persons SET Age = '36' WHERE FirstName = 'Peter' AND LastName = 'Griffin'");

  2. 删除某表中的某行:DELETE FROM table_name WHERE column_name = some_value
    删除 "Persons" 表中所有 LastName='Griffin' 的行:mysql_query("DELETE FROM Persons WHERE LastName='Griffin'");
  3. where指定条件
    指定条件的查询:SELECT column FROM table WHERE 条件

    PHP:$result = mysql_query("SELECT * FROM Persons WHERE FirstName='Peter'");
  4. order by 排序
    ORDER BY 关键词用于将结果集中的数据按照某列的顺序排序。
    order by 列名/n(n是第n列)
    mysql:SELECT column_name(s) FROM table_name ORDER BY column_name

PDO

  • 连接
    $conn = new PDO("mysql:host=$servername;", $username, $password);
  • 建库建表插数据
    无结果返回使用exec()
$sql = "CREATE DATABASE myDBPDO";
//使用 exec() ,因为没有结果返回,注意,此处并未使用预处理,所以无防注入效果。
$conn->exec($sql);

预处理语句

预处理语句用于执行多个相同的 SQL 语句,并且执行效率更高。
预处理语句的工作原理如下:

  1. 预处理:创建 SQL 语句模板并发送到数据库。预留的值使用参数 "?" 标记 。例如:
    INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
  2. 数据库解析,编译,对SQL语句模板执行查询优化,并存储结果不输出。
  3. 执行:最后,将应用绑定的值传递给参数("?" 标记),数据库执行语句。应用可以多次执行语句,如果参数的值不一样。

简单理解就是,先传递没有参数的语句给数据库解析编译,在传递参数的值给数据库作为参数执行。与传统的拼接语句一步执行相比,预处理是分两步的。此种情况下,即使参数的输入没有过滤,但因为参数在数据库中只作为参数参与SQL语句执行,没有与语句拼接,注入也就无法进行。

相比于直接执行SQL语句,预处理语句有两个主要优点:

  1. 预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行)。
  2. 绑定参数减少了服务器带宽,你只需要发送查询的参数,而不是整个语句。
  3. 预处理语句针对SQL注入是非常有用的,因为参数值发送后使用不同的协议,保证了数据的合法性。但是注意,只要使用了字符串拼接SQL语句,即使使用了PDO,仍然可能存在注入。所以要杜绝拼接,使用?

实例:

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
 
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
 
// 检测连接
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}
 
// 预处理及绑定
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
 
// 设置参数并执行
$firstname = "John";
$lastname = "Doe";
$email = "john@example.com";
$stmt->execute();
 
$firstname = "Mary";
$lastname = "Moe";
$email = "mary@example.com";
$stmt->execute();
 
$firstname = "Julie";
$lastname = "Dooley";
$email = "julie@example.com";
$stmt->execute();
 
echo "新记录插入成功";
 
$stmt->close();
$conn->close();
?>

解析实例的代码:
INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
在 SQL 语句中,我们使用了问号 (?),在此我们可以将问号替换为整型,字符串,双精度浮点型和布尔值。接下来,让我们来看下 bind_param() 函数:
$stmt->bind_param("sss", $firstname, $lastname, $email);
该函数绑定了 SQL 的参数,且告诉数据库参数的值。 "sss" 参数列处理其余参数的数据类型。s 字符告诉数据库该参数为字符串。
参数有以下四种类型:
i - integer(整型)
d - double(双精度浮点型)
s - string(字符串)
b - BLOB(binary large object:二进制大对象)
每个参数都需要指定类型。
通过告诉数据库参数的数据类型,可以降低 SQL 注入的风险。

总结,预处理语句使用的三个步骤:

  1. 预处理 $conn->prepare
  2. 绑定参数 $stmt->bind_param
  3. 设置参数并执行 $stmt->execute();

防止SQL注入

防止SQL注入,我们需要注意以下几个要点:

  1. 永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
  2. 永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
  3. 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
  4. 不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
  5. 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装。

如何防止

对用户输入的数据进行转义从而来防止SQL注入,注意如果magic_quotes_gpc开启了,就不要再转义了,多重转义会导致转义失效。

  1. mysqli_real_escape_string()
    mysql指定的转义函数。
    此函数用来对字符串中的特殊字符进行转义, 以使得这个字符串是一个合法的 SQL 语句。 传入的字符串会根据当前连接的字符集进行转义,得到一个编码后的合法的 SQL 语句。
mysqli_real_escape_string ( mysqli $link , string $escapestr ) : string
link
规定要使用的 MySQL 连接。
escapestr
需要进行转义的字符串。
会被进行转义的字符包括:NUL(ASCII 0),\n,\r,\,'," 和 Control-Z

在调用 mysqli_real_escape_string() 函数之前, 必须先通过调用 mysqli_set_charset() 函数或者在 MySQL 服务器端设置合理的字符集,不合理的字符集会导致宽字节注入。

  1. addcslashes()
    返回在指定字符前添加反斜杠的字符串。
    对大小写敏感。
addcslashes ( string $str , string $charlist ) : string
string:规定要转义的字符串。
characters:规定要转义的字符或字符范围。
  1. addslashes()
    返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)。
    addslashes( string $str) : string
posted @ 2020-07-07 18:21  雨九九  阅读(240)  评论(0编辑  收藏  举报