zoukankan      html  css  js  c++  java
  • 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),
    ,
    ,,'," 和 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
  • 相关阅读:
    Jmeter与LoadRunner 测试Java项目的坑
    关于<forEach>的<if>混合使用显示数据
    无题。省
    无题。思
    767A Snacktower
    喵哈哈村的括号序列

    队列
    优先队列
    768A Oath of the Night's Watch
  • 原文地址:https://www.cnblogs.com/Rain99-/p/13262412.html
Copyright © 2011-2022 走看看