至尊技术网 - MySQL 2022-12-28T15:53:00+08:00 Typecho https://www.zzwws.cn/feed/atom/tag/MySQL/ <![CDATA[MySQL 小数类型]]> https://www.zzwws.cn/archives/6386/ 2022-12-28T15:53:00+08:00 2022-12-28T15:53:00+08:00 悠悠楠杉 http://www.zzwws.cn 定点数decimal
能够保证数据精确的小数(小数部分可能不精确,超出长度会四舍五入),整数部分一定精确
decimal(M, D), M表示总长度,最大值不能超过65,D代表小数部分长度,最长不能超过30

浮点型
又称为精度类型,是一种可能丢失精度的数据类型,数据可能不那么准确

float 单精度类型
4字节存储,7位精度,表示数据范围比整数大得多
float 表示不指定小数位的浮点数
float(M, D)表示一共存储M个有效数字,其中小数部分占D位

double 双精度类型
8个字节存储,表示范围更大,精度有15位左右
double 表示不指定小数位的浮点数
double(M, D)表示一共存储M个有效数字,其中小数部分占D位

如何选择
当需要存储的小数对精度要求不高时,可以选择FLOAT单精度浮点型,可以节省内存空间,提高计算速度。
当需要进行高速数学计算、科学计算、卫星定位计算等对精度要求较高时,可以选择DOUBLE双精度浮点型。
当需要进行精确计算,如工资结算、转账打款等财务类型的数据,可以选择DECIMAL定点型。

]]>
<![CDATA[PHP面向对象封装MySQL PDO(已使用预处理)]]> https://www.zzwws.cn/archives/6343/ 2022-06-10T11:38:00+08:00 2022-06-10T11:38:00+08:00 悠悠楠杉 http://www.zzwws.cn Mysql.class.php

<?php
class Mysql
{
    public $link;

    public function __construct()
    {
        $this->conn();
    }

    /**
     * 连接数据库,从配置文件读取配置信息
     */
    public function conn()
    {
        $cfg = require 'config.php';
        try {
            $this->link = new PDO("mysql:dbname={$cfg['databaseName']};host={$cfg['host']};charset={$cfg['charset']};port={$cfg['port']}", $cfg['name'], $cfg['password']);
            $this->link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // 设置禁止本地模拟prepare
            //$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);// 设置捕获异常
        } catch (PDOException $e) {
            die("Error: " . $e->getMessage());
        }
    }

    /**
     * 查询多行数据
     * @param string $table 表名字
     * @param string $where where条件
     * @param string $field 字段
     * @param string $additional 附加sql语句
     * @return array
     */
    public function getAll($table, $where = [], $field = "*", $additional = '')
    {
        if (strpos($field, ",") !== false) {
            $arr = explode(",", $field);
            $str = '';
            foreach ($arr as $v) {
                $str .= "`{$v}`,";
            }
            $field = substr($str, 0, -1);
        } else if ($field != "*") {
            $field = "`{$field}`";
        }
        $sql = "SELECT {$field} FROM `{$table}`";
        $sql2 = '';
        $value = [];
        if ($where) {
            if (!is_array($where[0])) {
                if (strtolower($where[1]) == 'in') {
                    $where[1] = 'IN';
                    $sql2 = " `{$where[0]}` {$where[1]} (";
                    if (is_array($where[2])) {
                        foreach ($where[2] as $v) {
                            $value[] = $v;
                            $sql2 .= '?,';
                        }
                    } else {
                        $value[] = $where[2];
                        $sql2 .= '?';
                    }
                    $sql2 = rtrim($sql2, ',') . ')';
                } else {
                    $value[] = $where[2];
                    $sql2 = " `{$where[0]}` {$where[1]} ?";
                }
            } else {
                foreach ($where as $v) {
                    if (strtolower($v[1]) == 'in') {
                        $v[1] = 'IN';
                        $sql2 .= " `{$v[0]}` {$v[1]} (";
                        if (is_array($v[2])) {
                            foreach ($v[2] as $v2) {
                                $value[] = $v2;
                                $sql2 .= "?,";
                            }
                        } else {
                            $value[] = $v[2];
                            $sql2 .= "?";
                        }
                        $sql2 = rtrim($sql2, ',') . ') AND';
                    } else {
                        $value[] = $v[2];
                        $sql2 .= " `{$v[0]}` {$v[1]} ? AND";
                    }
                }
                $sql2 = substr($sql2, 0, -4);
            }
            if ($sql2) {
                $sql .= " WHERE " . $sql2;
            }
        }
        if ($additional) {
            $sql .= ' ' . $additional;
        }
        $res = $this->link->prepare($sql);
        $res->execute($value);
        $data = $res->fetchAll(PDO::FETCH_ASSOC);
        return $data;
    }

    /**
     * 查询单行数据
     * @param string $table 表名字
     * @param string $where where条件
     * @param string $field 字段
     * @param string $additional 附加sql语句
     * @return array
     */
    public function getRow($table, $where = [], $field = "*", $additional = '')
    {
        if (strpos($field, ",") !== false) {
            $arr = explode(",", $field);
            $str = '';
            foreach ($arr as $v) {
                $str .= "`{$v}`,";
            }
            $field = substr($str, 0, -1);
        } else if ($field != "*") {
            $field = "`{$field}`";
        }
        $sql = "SELECT {$field} FROM `{$table}`";
        $sql2 = '';
        $value = [];
        if ($where) {
            if (!is_array($where[0])) {
                if (strtolower($where[1]) == 'in') {
                    $where[1] = 'IN';
                    $sql2 = " `{$where[0]}` {$where[1]} (";
                    if (is_array($where[2])) {
                        foreach ($where[2] as $v) {
                            $value[] = $v;
                            $sql2 .= '?,';
                        }
                    } else {
                        $value[] = $where[2];
                        $sql2 .= '?';
                    }
                    $sql2 = rtrim($sql2, ',') . ')';
                } else {
                    $value[] = $where[2];
                    $sql2 = " `{$where[0]}` {$where[1]} ?";
                }
            } else {
                foreach ($where as $v) {
                    if (strtolower($v[1]) == 'in') {
                        $v[1] = 'IN';
                        $sql2 .= " `{$v[0]}` {$v[1]} (";
                        if (is_array($v[2])) {
                            foreach ($v[2] as $v2) {
                                $value[] = $v2;
                                $sql2 .= "?,";
                            }
                        } else {
                            $value[] = $v[2];
                            $sql2 .= "?";
                        }
                        $sql2 = rtrim($sql2, ',') . ') AND';
                    } else {
                        $value[] = $v[2];
                        $sql2 .= " `{$v[0]}` {$v[1]} ? AND";
                    }
                }
                $sql2 = substr($sql2, 0, -4);
            }
            if ($sql2) {
                $sql .= " WHERE " . $sql2;
            }
        }
        if ($additional) {
            $sql .= ' ' . $additional;
        }
        $res = $this->link->prepare($sql);
        $res->execute($value);
        $data = $res->fetch(PDO::FETCH_ASSOC);
        return $data;
    }

    /**
     * 自动创建sql语句并执行
     * @param string $table 表名字
     * @param array $data 关联数组 键/值与表的列/值对应
     * @param string $act 1为insert,2为update
     * @param array $where 条件,用于update
     * @return int 成功为insert产生的主键值,update是影响的行数,失败为0
     */
    public function exec($table, $data, $act = 1, $where = [])
    {
        $value = [];
        if ($act == 1) {
            $sql = "INSERT INTO `{$table}` (`";
            $sql .= implode('`,`', array_keys($data)) . '`)';
            $str = '';
            foreach ($data as $v) {
                $str .= "?,";
            }
            $str = substr($str, 0, -1);
            $sql .= " VALUES ({$str})";
            $value = array_values($data);
        } else {
            $sql = "UPDATE `{$table}` SET ";
            foreach ($data as $k => $v) {
                $sql .= "`" . $k . '`= ' . " ?,";
                $value[] = $v;
            }
            $sql = rtrim($sql, ',');
            $sql2 = '';
            if ($where) {
                if (!is_array($where[0])) {
                    if (strtolower($where[1]) == 'in') {
                        $where[1] = 'IN';
                        $sql2 = " `{$where[0]}` {$where[1]} (";
                        if (is_array($where[2])) {
                            foreach ($where[2] as $v) {
                                $value[] = $v;
                                $sql2 .= '?,';
                            }
                        } else {
                            $value[] = $where[2];
                            $sql2 .= '?';
                        }
                        $sql2 = rtrim($sql2, ',') . ')';
                    } else {
                        $value[] = $where[2];
                        $sql2 = " `{$where[0]}` {$where[1]} ?";
                    }
                } else {
                    foreach ($where as $v) {
                        if (strtolower($v[1]) == 'in') {
                            $v[1] = 'IN';
                            $sql2 .= " `{$v[0]}` {$v[1]} (";
                            if (is_array($v[2])) {
                                foreach ($v[2] as $v2) {
                                    $value[] = $v2;
                                    $sql2 .= "?,";
                                }
                            } else {
                                $value[] = $v[2];
                                $sql2 .= "?";
                            }
                            $sql2 = rtrim($sql2, ',') . ') AND';
                        } else {
                            $value[] = $v[2];
                            $sql2 .= " `{$v[0]}` {$v[1]} ? AND";
                        }
                    }
                    $sql2 = substr($sql2, 0, -4);
                }
                if ($sql2) {
                    $sql .= " WHERE " . $sql2;
                }
            }
        }
        $res = $this->link->prepare($sql);
        $run = $res->execute($value);
        if ($run) {
            if ($act == 1) {
                return $this->link->lastInsertId();
            } else {
                return $res->rowCount();
            }
        } else {
            return 0;
        }
    }

    /**
     * 删除数据
     * @param string $table 表名字
     * @param array $where where条件
     * @return bool
     */
    public function delete($table, $where = [])
    {
        $sql = "DELETE FROM `{$table}`";
        $sql2 = '';
        $value = [];
        if ($where) {
            if (!is_array($where[0])) {
                if (strtolower($where[1]) == 'in') {
                    $where[1] = 'IN';
                    $sql2 = " `{$where[0]}` {$where[1]} (";
                    if (is_array($where[2])) {
                        foreach ($where[2] as $v) {
                            $value[] = $v;
                            $sql2 .= '?,';
                        }
                    } else {
                        $value[] = $where[2];
                        $sql2 .= '?';
                    }
                    $sql2 = rtrim($sql2, ',') . ')';
                } else {
                    $value[] = $where[2];
                    $sql2 = " `{$where[0]}` {$where[1]} ?";
                }
            } else {
                foreach ($where as $v) {
                    if (strtolower($v[1]) == 'in') {
                        $v[1] = 'IN';
                        $sql2 .= " `{$v[0]}` {$v[1]} (";
                        if (is_array($v[2])) {
                            foreach ($v[2] as $v2) {
                                $value[] = $v2;
                                $sql2 .= "?,";
                            }
                        } else {
                            $value[] = $v[2];
                            $sql2 .= "?";
                        }
                        $sql2 = rtrim($sql2, ',') . ') AND';
                    } else {
                        $value[] = $v[2];
                        $sql2 .= " `{$v[0]}` {$v[1]} ? AND";
                    }
                }
                $sql2 = substr($sql2, 0, -4);
            }
            if ($sql2) {
                $sql .= " WHERE " . $sql2;
            }
        }
        $res = $this->link->prepare($sql);
        return $res->execute($value);
    }

    /**
     * count数据
     * @param string $table 表名字
     * @param array $where where条件
     * @param string $field 字段
     * @return int
     */
    public function count($table, $where = [],$field = '*')
    {
        $sql = "SELECT COUNT({$field}) FROM `{$table}`";
        $sql2 = '';
        $value = [];
        if ($where) {
            if (!is_array($where[0])) {
                if (strtolower($where[1]) == 'in') {
                    $where[1] = 'IN';
                    $sql2 = " `{$where[0]}` {$where[1]} (";
                    if (is_array($where[2])) {
                        foreach ($where[2] as $v) {
                            $value[] = $v;
                            $sql2 .= '?,';
                        }
                    } else {
                        $value[] = $where[2];
                        $sql2 .= '?';
                    }
                    $sql2 = rtrim($sql2, ',') . ')';
                } else {
                    $value[] = $where[2];
                    $sql2 = " `{$where[0]}` {$where[1]} ?";
                }
            } else {
                foreach ($where as $v) {
                    if (strtolower($v[1]) == 'in') {
                        $v[1] = 'IN';
                        $sql2 .= " `{$v[0]}` {$v[1]} (";
                        if (is_array($v[2])) {
                            foreach ($v[2] as $v2) {
                                $value[] = $v2;
                                $sql2 .= "?,";
                            }
                        } else {
                            $value[] = $v[2];
                            $sql2 .= "?";
                        }
                        $sql2 = rtrim($sql2, ',') . ') AND';
                    } else {
                        $value[] = $v[2];
                        $sql2 .= " `{$v[0]}` {$v[1]} ? AND";
                    }
                }
                $sql2 = substr($sql2, 0, -4);
            }
            if ($sql2) {
                $sql .= " WHERE " . $sql2;
            }
        }
        $res = $this->link->prepare($sql);
        $res->execute($value);
        $data = $res->fetch(PDO::FETCH_NUM);
        return $data[0];
    }
}

config.php

<?php
return array(
    'host' => 'localhost',
    'name' => 'root',
    'password' => 'root',
    'databaseName' => 'cs_cn',
    'port' => '3306',
    'charset' => 'utf8'
);

使用方法

<?php
require 'Mysql.class.php';

$mysql = new Mysql();

// 添加
$data = [
    'code' => mt_rand(1000000000,9999999999),
    'url' => 'https://www.zzwws.cn',
    'ip' => mt_rand(1000000000,9999999999),
    'add_time' => time()
];
$res = $mysql->exec('zz_url',$data);
if($res){
    echo '添加成功';
}else{
    echo '添加失败';
}

// 修改
$data = [
    'code' => mt_rand(1000000000,9999999999)
];
$where = ['id','=',51];
// 或者
// $where = [
//     ['id','=',51],
//     ['ip','=','3755406202']
// ];

$res = $mysql->exec('zz_url',$data,2,$where);
if($res){
    echo '修改成功';
}else{
    echo '修改失败';
}

// 查询一行数据
$row = $mysql->getRow('zz_url',['id','=',51],'id,code');
if(!$row){
    echo '获取失败';
}
print_r($row);

// 查询多行数据
$rows = $mysql->getAll('zz_url');
print_r($rows);

// 删除
$where = [
    ['id','=',52]
];
// 或者
// $where = [
//     ['id','in',[1,2,3]]
// ];
$res = $mysql->delete('zz_url',$where);
var_dump($res);

// count
$count = $mysql->count('zz_url',['url','=','https://www.zzwws.cn']);
var_dump($count);

// query方法(没有预处理)
$res = $mysql->link->query("SELECT * FROM zz_url WHERE id = '1'");
$row = $res->fetch(PDO::FETCH_ASSOC);
print_r($row);
]]>
<![CDATA[MySQL数据库导入sql提示 Unknown collation: ‘utf8mb4_0900_ai_ci‘]]> https://www.zzwws.cn/archives/5946/ 2021-10-19T15:43:53+08:00 2021-10-19T15:43:53+08:00 悠悠楠杉 http://www.zzwws.cn

错误原因:高版本数据库(8.0)转存sql文件 并导入低版本数据库(5.6)

解决办法:
方案一:升级MySQL至高版本
方案二:将需要导入的sql文件,把其中的utf8mb4_0900_ai_ci全部替换为utf8mb4_unicode_ci或者utf8mb4_general_ci,重新执行sql文件

]]>
<![CDATA[从零开始带你成为MySQL实战优化高手]]> https://www.zzwws.cn/archives/5716/ 2021-09-04T18:59:01+08:00 2021-09-04T18:59:01+08:00 悠悠楠杉 http://www.zzwws.cn

下载地址:https://www.aliyundrive.com/s/LCANSeEhMhU

]]>
<![CDATA[PHP防止SQL注入]]> https://www.zzwws.cn/archives/5551/ 2021-08-14T21:02:00+08:00 2021-08-14T21:02:00+08:00 悠悠楠杉 http://www.zzwws.cn SQL注入的万能语句' or 1=1#

当我们在用户名处输入' or 1=1#,密码随便写,把它带入到语句中,就变成了

select * from user where uername='' or1=1#' and password='123456'

在SQL语句中#是注释符,所以后面的语句都会被注释掉

select * from user where username='' or1=1

也就是说可以用 'or 1=1# 这么一个字符串就可以绕开登录的密码,直接进入程序,防止这种情况出现,可以使用以下的预处理机制!

使用 PDO

1、通过传递一个插入值的数组执行一条预处理语句

$st = $db->prepare('select * from zz_order where id = ? and name = ?');
$st->execute([$id,$name]);// 成功时返回 true,失败时返回 false
$data = $st->fetch(PDO::FETCH_ASSOC);
print_r($data);

2、在 prepare 函数里面把参数用 ‘:name’ 这样的形式来替代,然后使用 execute 绑定参数。

$st = $db->prepare('select * from zz_order where id = :id');
$st->execute([':id' => $id]);
$data = $st->fetch(PDO::FETCH_ASSOC);
print_r($data);

3、通过绑定 PHP 变量执行一条预处理语句

$st = $db->prepare("select * from zz_order where id = ?");
$st->bindParam(1, $id);
$st->execute();
$data = $st->fetchAll(PDO::FETCH_ASSOC);
print_r($data);

使用 Mysqli

在 prepare 函数里面把参数用 ‘?’ 来替代,然后使用 bind_param 绑定参数。在 bind_param 中,第一个参数 's' 代表了参数的类型与个数(此处为一个字符串类型)。

$stmt = $db->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    // do something with $row
}

//bind_param参数类型
i - integer(整型)
d - double(双精度浮点型)
s - string(字符串)
b - BLOB(布尔值)

PDO

需要注意的是使用PDO去访问MySQL数据库时,真正的prepared statements默认情况下是不使用的。为了解决这个问题,你需要禁用模拟的prepared statements。下面是使用PDO创建一个连接的例子:

try {
    $db = new PDO('mysql:dbname=cs_cn;host=127.0.0.1;charset=utf8', 'root', 'root');
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);// 设置禁止本地模拟prepare
    //$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);// 设置捕获异常
} catch (PDOException $e) {
    die("Error!: " . $e->getMessage() . "<br/>");
}

ThinkPHP防止sql注入:https://www.zzwws.cn/archives/5488/

]]>
<![CDATA[mysql插入数字都变成2147483647的解决方法]]> https://www.zzwws.cn/archives/5487/ 2021-08-05T10:53:00+08:00 2021-08-05T10:53:00+08:00 悠悠楠杉 http://www.zzwws.cn 在用Excel导入数据的时候,碰到11位的数字都变成2147483647,原因是int类型的数据,最大只能到2147483647,所以11位的都变成了2147483647,

解决办法:

把字段类型由int改为bigint,就可以了.

下面是mysql的数据类型详解

1.整型(xxxint)

MySQL数据类型含义
tinyint(m)1个字节表示(-128~127)
smallint(m)2个字节表示(-32768~32767)
mediumint(m)3个字节表示(-8388608~8388607)
int(m)4个字节表示(-2147483648~2147483647)
bigint(m)8个字节表示(+-9.22*10的18次方)

2.浮点型(float和double)

MySQL数据类型含义
float(m,d)单精度浮点型,8位精度(4字节),m是十进制数字的总个数,d是小数点后面的数字个数
double(m,d)双精度浮点型,16位精度(8字节)

参数m只影响显示效果,不影响精度,d却不同,会影响到精度。比如设一个字段定义

3.定点数(decimal)
decimal(m,d) 定点类型浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值。参数m是定点类型数字的最大个数(精度),范围为0~65,d小数点右侧数字的个数,范围为0~30,但不得超过m。对定点数的计算能精确到65位数字。

4.字符串(char,varchar,xxxtext)

MySQL数据类型含义
char(n)固定长度的字符串,最多255个字符
varchar(n)固定长度的字符串,最多65535个字符
tinytext可变长度字符串,最多255个字符
text可变长度字符串,最多65535个字符
mediumtext可变长度字符串,最多2的24次方-1个字符
longtext可变长度字符串,最多2的32次方-1个字符

5.二进制数据(xxxBlob)
XXXBLOB和xxxtext是对应的,不过存储方式不同,xxxTEXT是以文本方式存储的,如果存储英文的话区分大小写,而xxxBlob是以二进制方式存储的,不区分大小写。xxxBlob存储的数据只能整体读出。xxxTEXT可以指定字符集,xxxblob不用指定字符集。

6.日期时间类型(date,time,datetime,timestamp)

MySQL数据类型含义
date日期'2008-12-2'
time时间'12:25:36'
datetime日期时间'2008-12-2 22:06:44'
timestamp不固定

timestamp比较特殊,如果定义一个字段的类型为timestamp,这个字段的时间会在其他字段修改的时候自动刷新。所以这个数据类型的字段可以存放这条记录最后被修改的时间,而不是真正来的存放时间。

7.数据类型的属性

MySQL关键字含义
NULL数据列可包含NULL值
NOT NULL数据列不允许包含NULL值
DEFAULT xxx默认值,如果插入记录的时候没有指定值,将取这个默认值
PRIMARY KEY主键
AUTO_INCREMENT递增,如果插入记录的时候没有指定值,则在上一条记录的值上加1,仅适用于整数类型
UNSIGNED无符号
CHARACTER SET name指定一个字符集
]]>
<![CDATA[PHP查询大量数据内存耗尽问题的解决方法]]> https://www.zzwws.cn/archives/5040/ 2021-05-10T15:28:38+08:00 2021-05-10T15:28:38+08:00 悠悠楠杉 http://www.zzwws.cn 从数据库查询大量数据时会出现内容不够的提示:

PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted

这个问题在PHP的官方网站上叫缓冲查询和非缓冲查询(Buffered and Unbuffered queries)。PHP的查询缺省模式是缓冲模式。也就是说,查询数据结果会一次全部提取到内存里供PHP程序处理。这样给了PHP程序额外的功能,比如说,计算行数,将指针指向某一行等。更重要的是程序可以对数据集反复进行二次查询和过滤等操作。但这种缓冲查询模式的缺陷就是消耗内存,也就是用空间换速度。

相对的,另外一种PHP查询模式是非缓冲查询,数据库服务器会一条一条的返回数据,而不是一次全部返回,这样的结果就是PHP程序消耗较少的内存,但却增加了数据库服务器的压力,因为数据库会一直等待PHP来取数据,一直到数据全部取完。

很显然,缓冲查询模式适用于小数据量查询,而非缓冲查询适应于大数据量查询。

对于PHP的缓冲模式查询大家都知道,下面列举的例子是如何执行非缓冲查询API。

非缓冲查询方法一: mysqli

<?php 
$mysqli = new mysqli("localhost", "my_user", "my_password", "world"); 
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT); 
if ($uresult) { 
  while ($row = $uresult->fetch_assoc()) { 
    echo $row['Name'] . PHP_EOL; 
  } 
} 
$uresult->close(); 
?> 

非缓冲查询方法二: pdo_mysql

<?php 
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass'); 
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 
$uresult = $pdo->query("SELECT Name FROM City"); 
if ($uresult) { 
  while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) { 
    echo $row['Name'] . PHP_EOL; 
  } 
} 
?> 

非缓冲查询方法三: mysql

<?php 
$conn = mysql_connect("localhost", "my_user", "my_pass"); 
$db  = mysql_select_db("world"); 
$uresult = mysql_unbuffered_query("SELECT Name FROM City"); 
if ($uresult) { 
  while ($row = mysql_fetch_assoc($uresult)) { 
    echo $row['Name'] . PHP_EOL; 
  } 
} 
?>
]]>
<![CDATA[PHP面向对象封装MySQL操作函数、文件上传]]> https://www.zzwws.cn/archives/4997/ 2021-01-04T17:36:00+08:00 2021-01-04T17:36:00+08:00 悠悠楠杉 http://www.zzwws.cn Mysql.class.php

<?php
class Mysql
{
    public $link;

    public function __construct()
    {
        $this->conn();
    }

    /**
     * 连接数据库,从配置文件读取配置信息
     */
    public function conn()
    {
        $cfg = require 'config.php';
        $this->link = new mysqli($cfg['host'], $cfg['name'], $cfg['password'], $cfg['databaseName'], $cfg['port']);
        $this->query('set names ' . $cfg['charset']);
    }

    /**
     * 发送query查询
     * @param string $sql sql语句
     * @return mixed
     */
    public function query($sql)
    {
        return $this->link->query($sql);
    }

    /**
     * 查询多行数据
     * @param string $sql sql语句
     * @return array
     */
    public function getAll($sql)
    {
        $res = $this->query($sql);
        $data = [];
        while ($row = $res->fetch_assoc()) {
            $data[] = $row;
        }
        return $data;
    }

    /**
     * 查询单行数据
     * @param string $sql sql语句
     * @return array
     */
    public function getRow($sql)
    {
        $res = $this->query($sql);
        return $res->fetch_assoc();
    }

    /**
     * 查询单个数据
     * @param string $sql sql语句
     * @return array mixed
     */
    public function getOne($sql)
    {
        $res = $this->query($sql);
        return $res->fetch_row()[0];
    }

    /**
     * 自动创建sql语句并执行
     * @param string $table 表名字
     * @param array $data 关联数组 键/值与表的列/值对应
     * @param string $act 动作/update/insert
     * @param string $where 条件,用于update
     *
     */
    public function exec($table, $data, $act = 'insert', $where = '0')
    {

        if ($act == 'insert') {
            //插入语句 insert into 表名 (字段1,字段2) values ('values1','values2')
            $sql = "insert into $table (";
            $sql .= implode(',', array_keys($data)) . ')';
            $sql .= " values ('";
            $sql .= implode("','", array_values($data)) . "')";
        } else {
            //修改语句 update 表名 set 字段1='values1',字段2='values2' where id=1
            $sql = "update $table set ";
            foreach ($data as $k => $v) {
                $sql .= $k . '=' . "'$v',";
            }
            $sql = rtrim($sql, ',');
            $sql .= " where $where";
        }
        return $this->query($sql);
    }

    /**
     * 返回上一条insert语句产生的主键值
     */
    public function lastId()
    {
        return $this->link->insert_id;
    }

    /**
     * 返回上一条语句影响的行数
     */
    public function affectRows()
    {
        return $this->link->affected_rows;
    }
}

Upload.class.php

<?php
abstract class AUpload
{
    public $allowext = array('jpg', 'jpeg', 'png', 'rar');
    public $maxsize = 1;
    protected $error = '';

    abstract public function getInfo($name);
    abstract public function createDir();
    abstract public function randStr($len = 8);
    abstract protected function checkType($ext);
    abstract protected function checkSize($size);
    abstract public function up($name);

    public function getError()
    {
        return $this->error;
    }
}

class Upload extends AUpload
{
    /**
     * 分析$_FILES中$name域的信息,比如$_FILES['pic']
     * @param string $name 表单中的file里的name值
     * @return array 上传文件的信息
     */
    public function getInfo($name)
    {
        return $_FILES[$name];
    }

    /**
     * 创建目录 /upload/2021/01/04
     * @return string 目录路径
     */
    public function createDir()
    {
        $dir = '/upload/' . date('Y/m/d');
        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        }
        return $dir;
    }

    /**
     * 生成随机字符串
     * @param int $len 随机字符串的长度
     * @return string 返回生成的字符串
     */
    public function randStr($len = 6)
    {
        $str = str_shuffle('abcedfghjkmnpqrstuvwxyzABCEDFGHJKMNPQRSTUVWXYZ0123456789');
        return substr($str, 0, $len);
    }

    /**
     * 检查文件类型
     * @param $ext 文件后缀
     * @return boolean
     */
    protected function checkType($ext)
    {
        return in_array($ext, $this->allowext);
    }

    /**
     * 检测文件大小
     * @param $size 文件大小
     * @return boolean
     */
    protected function checkSize($size)
    {
        return $size < $this->maxsize * 1024 * 1024;
    }

    /**
     * 上传文件
     * @param string $name 表单中file的name值
     * @return string 上传的文件,如/upload/2021/01/04/1609749834kfyzXr.jpg
     */
    public function up($name)
    {
        if (!isset($_FILES[$name])) {
            echo '没有上传文件';exit();
        }
        $info = $this->getInfo($name);

        $ext = ltrim(strrchr($info['name'], '.'), '.');
        if (!$this->checkType($ext)) {
            echo '不允许上传此类型文件';exit();
        }

        if (!$this->checkSize($info['size'])) {
            echo '文件过大';exit();
        }

        $dir = $this->createDir();
        $filename = time() . $this->randStr() . '.' . $ext;
        if (move_uploaded_file($info['tmp_name'], $dir . '/' . $filename)) {
            $data['path'] = $dir;
            $data['filename'] = $filename;
            return $data;
        } else {
            echo '上传失败';
        }
    }
}

$file = new Upload();
var_dump($file->up('pic'));

upload.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>上传</title>
</head>

<body>
    <form action="Upload.class.php" method="post" enctype="multipart/form-data">
        <input type="file" name="pic">
        <button type="submit" id="submit">提交</button>
    </form>

</body>

</html>

config.php

<?php
return array(
    'host' => 'localhost',
    'name' => 'cs',
    'password' => '123456',
    'databaseName' => 'cs',
    'port' => '3306',
    'charset' => 'utf8'
);

使用方法

$mysql = new Mysql();

1、增

$art['title'] = trim($_POST['title']);
$art['cat_id'] = trim($_POST['cat_id']);
$art['content'] = trim($_POST['content']);
$art['pubtime'] = time();
if ($mysql->exec('art', $art)) {
        echo('添加成功');
    } else {
        echo('添加失败');
    }

2、删

$sql = "delete from cat where cat_id='$cat_id'";
if ($mysql->query($sql)) {
    echo('删除成功');
} else {
    echo('删除失败');
}

3、改

$cat_id = $_GET['cat_id'];
$cat['catname'] = trim($_POST['catname']);
if ($mysql->exec('cat',$cat,'update',"cat_id=$cat_id")) {
    echo('修改成功');
} else {
    echo('修改失败');
}

4、查
查询多行数据

$sql = "select * from cat";
$arr = $mysql->getAll($sql);
print_r($arr);

取出一行数据

$sql = "select * from cat where cat_id='$cat_id'";
if (!$mysql->getRow($sql)) {
    echo('栏目不存在');
    exit();
}

查询返回一个结果

$sql = "select * from cat where cat_id='$cat_id'";
echo $mysql->getOne($sql);

获取上一步insert 操作产生的主键id

$mysql->lastId();


]]>
<![CDATA[MySQL中varchar与char的区别]]> https://www.zzwws.cn/archives/4966/ 2020-12-05T10:08:08+08:00 2020-12-05T10:08:08+08:00 悠悠楠杉 http://www.zzwws.cn 区别一,定长和变长
char 表示定长,长度固定,varchar表示变长,即长度可变。char如果插入的长度小于定义长度时,则用空格填充;varchar小于定义长度时,还是按实际长度存储,插入多长就存多长。

因为其长度固定,char的存取速度还是要比varchar要快得多,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以会占据多余的空间,可谓是以空间换取时间效率。varchar则刚好相反,以时间换空间。

区别之二,存储的容量不同
对 char 来说,最多能存放的字符个数 255,和编码无关。
而 varchar 呢,最多能存放 65532 个字符。varchar的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是 65,532字节。

]]>
<![CDATA[PHP 封装MySQL操作函数、魔术常量、封装函数]]> https://www.zzwws.cn/archives/4964/ 2020-12-02T09:49:00+08:00 2020-12-02T09:49:00+08:00 悠悠楠杉 http://www.zzwws.cn mysql.php

<?php

/**
 * mysql.php mysql系列操作函数
 * @author nianbaibai
 */

/**
 * 连接数据库
 *
 * @return resource 连接成功,返回连接数据库的资源
 */
function mConn()
{
    static $conn = null;
    if ($conn === null) {
        $db = require ROOT . '/lib/config.php';
        $conn = mysqli_connect("$db[host]", "$db[name]", "$db[password]", "$db[databaseName]", "$db[port]");
        mysqli_query($conn, 'set names ' . $db['charset']);
    }

    return $conn;
}

/**
 * 查询的函数
 * @return mixed resoure/bool
 */
function mQuery($sql)
{
    $rs = mysqli_query(mConn(), $sql);
    if ($rs) {
        // mLog($sql);//执行成功的日志,如果需要的可以显示这段
    } else {
        mLog($sql . "\n" . mysqli_error(mConn()));
    }

    return $rs;
}

/**
 * log日志记录功能
 * @param str $str 待记录的字符串
 */
function mLog($str)
{
    $filename = ROOT . '/log/' . date('Ymd') . '.txt';
    $log = "-----------------------------------------\n" . date('Y/m/d H:i:s') . "\n" . $str . "\n" . "-----------------------------------------\n\n";
    return file_put_contents($filename, $log, FILE_APPEND);
}

/**
 * select 查询多行数据
 *
 * @param str $sql select 待查询的sql语句
 * @return mixed select 查询成功,返回二维数组,失败返回false
 */

function mGetAll($sql)
{
    $rs = mQuery($sql);
    if (!$rs) {
        return false;
    }

    $data = array();
    while ($row = mysqli_fetch_assoc($rs)) {
        $data[] = $row;
    }

    return $data;
}

/*$sql = "select * from cat";
print_r(mGetAll($sql));
 */

/**
 * select 取出一行数据
 *
 * @param str $sql 待查询的sql语句
 * @return arr/false 查询成功 返回一个一维数组
 */

function mGetRow($sql)
{
    $rs = mQuery($sql);
    if (!$rs) {
        return false;
    }

    return mysqli_fetch_assoc($rs);
}

/*$sql = "select * from cat where cat_id=1";
print_r(mGetRow($sql));*/

/**
 * select 查询返回一个结果
 *
 * @param str $sql 待查询的select语句
 * @return mixed 成功,返回结果,失败返回false
 */
function mGetOne($sql)
{
    $rs = mQuery($sql);
    if (!$rs) {
        return false;
    }

    return mysqli_fetch_row($rs)[0];
}

/*$sql = "select count(*) from art where cat_id=1";
echo mGetOne($sql);*/
/**
 * 自动拼接insert 和 update sql语句,并且调用mQuery() 去执行sql
 *
 * @param str $table 表名
 * @param arr $data 接收到的数据,一维数组
 * @param str $act 动作 默认为'insert'
 * @param str $where 防止update更改时少加where条件
 * @return bool insert 或者update 插入成功或失败
 */

function mExec($table, $data, $act = 'insert', $where = 0)
{
    if ($act == 'insert') {
        $sql = "insert into $table (";
        $sql .= implode(',', array_keys($data)) . ") values ('";
        $sql .= implode("','", array_values($data)) . "')";
        return mQuery($sql);
    } else if ($act == 'update') {
        $sql = "update $table set ";
        foreach ($data as $k => $v) {
            $sql .= $k . "='" . $v . "',";
        }

        $sql = rtrim($sql, ',') . " where " . $where;
        return mQuery($sql);
    }
}
//$data = array('title'=>'今天的空气' , 'content'=>'空气质量优' , 'pubtime'=>12345678,'author'=>'baibai');
//insert into art (title,content,pubtime,author) values ('今天的空气','空气质量优','12345678','baibai');
//update art set title='今天的空气',conte='空气质量优',pubtime='12345678',author='baibai' where art_id=1;
//echo mExec('art' , $data , 'update' , 'art_id=1');;
//insert into cat (id,catname) values (5 , 'test');

/**
 * 取得上一步insert 操作产生的主键id
 */
function getLastId()
{
    return mysqli_insert_id(mConn());
}

/**
 * 使用反斜线 转义字符串
 * @param arr 待转义的数组
 * @return arr 被转义后的数组
 */

function _addslashes($arr)
{
    foreach ($arr as $k => $v) {
        if (is_string($v)) {
            $arr[$k] = addslashes($v);
        } else if (is_array($v)) {
            $arr[$k] = _addslashes($v);
        }
    }

    return $arr;
}

config.php

<?php
//salt为cookie登录的安全码
return array(
    'host' => 'localhost',
    'name' => 'cs',
    'password' => '123456',
    'databaseName' => 'cs',
    'port' => '3306',
    'charset' => 'utf8',
    'salt' => 'Q!!RN13q&y'
);

func.php

<?php
/**
 *@param str $msg 成功返回的信息
 *@param str $file 跳转的文件名,返回上一页为-1
 *@param int $time 延时跳转的时间,单位秒
 */
function succ($msg, $file = '', $time = 1)
{
    $res = 'succ';
    require ROOT . '/view/admin/info.html';
    if ($file != '') {
        if ($file == '-1') {
            // header("Refresh:$time;url=$_SERVER[HTTP_REFERER]");
            echo '<script>window.setTimeout(function() {window.history.back(-1);},' . $time . '000)</script>';
        } else {
            header("Refresh:$time;url=$file");
        }
    }
    exit();
}

/**
 *@param str $msg 失败返回的报错信息
 *@param str $file 跳转的文件名,返回上一页为-1
 *@param int $time 延时跳转的时间,单位秒
 */
function error($msg, $file = '', $time = 1)
{
    $res = 'fail';
    require ROOT . '/view/admin/info.html';
    if ($file != '') {
        if ($file == '-1') {
            // header("Refresh:$time;url=$_SERVER[HTTP_REFERER]");
            echo '<script>window.setTimeout(function() {window.history.back(-1);},' . $time . '000)</script>';
        } else {
            header("Refresh:$time;url=$file");
        }
    }
    exit();
}

/**
 *获取访客IP
 */
function getRealIp()
{
    static $realip = null;
    if ($realip !== null) {
        return $realip;
    }

    if (getenv('REMOTE_ADDR')) {
        $realip = getenv('REMOTE_ADDR');
    } else if (getenv('HTTP_CLIENT_IP')) {
        $realip = getenv('HTTP_CLIENT_IP');
    } else if (getenv('HTTP_X_FROWARD_FOR')) {
        $realip = getenv('HTTP_X_FROWARD_FOR');
    }

    return $realip;
}

/**
 * 生成随机字符串
 * @param int $num 生成的随机字符串的个数
 * @return str 生成的随机字符串
 */
function randStr($num = 6)
{
    $str = str_shuffle('abcedfghjkmnpqrstuvwxyzABCEDFGHJKMNPQRSTUVWXYZ0123456789');
    return substr($str, 0, $num);
}

//echo randStr();

/**
 * 创建目录 ROOT.'/upload/2015/01/25/qwefas.jpg'
 * @return str 成功返回路径,失败返回false
 */
function createDir()
{
    $path = '/upload/' . date('Y/m/d');
    $fpath = ROOT . $path;
    if (is_dir($fpath) || mkdir($fpath, 0777, true)) {
        return $path;
    } else {
        return false;
    }
}

/**
 * 获取文件后缀
 * @param str $filename 文件名
 * @return str 文件的后缀名,且带点.
 */
function getExt($filename)
{
    return strrchr($filename, '.');
}

/**
 * 检测用户是否登录
 * @return bool 已登录返回true,未登录返回false
 */
function acc()
{
    if (!isset($_COOKIE['name']) || !isset($_COOKIE['ccode'])) {
        return false;
    }
    return $_COOKIE['ccode'] === cCode($_COOKIE['name']);
}

/**
 * 加密用户名
 * @param str $name 用户登陆时输入的用户名
 * @return str md5(用户名+salt)=>md5码
 */
function cCode($name)
{
    $salt = require ROOT . '/lib/config.php';
    return md5($name . '|' . $salt['salt']);
}

info.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
     <div id="rside">
            <?php if($res == 'succ'){?>
            <div class="succ"><?php echo $msg?></div>
            <?php }else if($res == 'fail'){?>
            <div class="danger"><?php echo $msg?></div>
            <?php }?>
        </div>
</body>
</html>

login.php

<?php

require 'lib/init.php';

if (acc()) {
    header('location: artlist.php');
}
if (empty($_POST)) {
    require ROOT . '/view/admin/login.html';
} else {
    $name = trim($_POST['username']);
    if ($name == '') {
        error('用户名不能为空');
    }
    if (!preg_match('/^[A-Za-z0-9_\x{4e00}-\x{9fa5}]+$/u', $name)) {
//用户名只能由数字、字母、中文汉字及下划线组成,不能包含特殊符号,在php中,不支持[\u4e00-\u9fa5]匹配汉字,而是用\x表示十六进制数据,然而php中用"[\x4e00-\x9fa5]"的写法也是错的,必须用{}把它包起来才行。此外,由于编码关系,需要用到"/u"声明编码格式。
        error('用户名格式不正确');
    }
    $password = trim($_POST['password']);
    if ($password == '') {
        error('密码不能为空');
    }
    // $sql = "select * from user where name='$name' and password='$password'";
    $sql = "select * from user where name='$name'";
    $res = mGetRow($sql);
    if (!$res) {
        error('用户名不存在');
    } else if (md5($res['salt'] . $password) !== $res['password']) {//这里的salt为密码的安全码,可以在注册成功后生成一个随机的安全码
        error('密码错误');
    } else {
        setcookie('name', $res['name']);
        setcookie('ccode', cCode($res['name']));
        header('location: artlist.php');
    }
}

init.php

<?php

//echo __DIR__,'<br>';//D:\xampp\htdocs\1\Blog
//echo __FILE__,'<br>';//D:\xampp\htdocs\1\Blog\init.php
//echo __LINE__;//4

header('content-type:text/html;charset=utf8');
define('ROOT', dirname(__DIR__)); //定义个ROOT常量,dirname往上跳一级
require ROOT . '/lib/mysql.php';
require ROOT . '/lib/func.php';
$_GET = _addslashes($_GET);
$_POST = _addslashes($_POST);
$_COOKIE = _addslashes($_COOKIE);

使用方法

首先引入init.php,这里的art和cat是表名,mysqli_query($conn, $sql)可变为mQuery($sql)

1、增

$art['title'] = trim($_POST['title']);
$art['cat_id'] = trim($_POST['cat_id']);
$art['content'] = trim($_POST['content']);
$art['pubtime'] = time();
if (mExec('art', $art)) {
        succ('添加成功');
    } else {
        error('添加失败');
    }

2、删

$sql = "delete from cat where cat_id='$cat_id'";
if (mQuery($sql)) {
    succ('删除成功');
} else {
    error('删除失败');
}

3、改

$cat_id = $_GET['cat_id'];
$cat['catname'] = trim($_POST['catname']);
if (mExec('cat',$cat,'update',"cat_id=$cat_id")) {
    succ('修改成功');
} else {
    error('修改失败');
}

4、查
查询多行数据

$sql = "select * from cat";
$arr = mGetAll($sql);
print_r($arr);

取出一行数据

$sql = "select * from cat where cat_id='$cat_id'";
if (!mGetRow($sql)) {
    error('栏目不存在');
    exit();
}

查询返回一个结果

$sql = "select * from cat where cat_id='$cat_id'";
echo mGetOne($sql);

获取上一步insert 操作产生的主键id

getLastId();

使用反斜线,转义字符串
使用方法:在顶部添加一下代码

$_GET = _addslashes($_GET);
$_POST = _addslashes($_POST);
$_COOKIE = _addslashes($_COOKIE);

检测用户是否登录

if(!acc()){
    header('location: login.php');
}

登录成功后添加name和ccode的cookie,请参考上面的login.php

setcookie('name', $res['name']);
setcookie('ccode', cCode($res['name']));

退出登录

setcookie('name', '', 0);
setcookie('ccode', '', 0);
header('location: login.php');
]]>