MySQL快速入门

1 MySQL - 简介

什么是数据库?

数据库是存储数据集合的独立应用程序。每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制它所保存的数据。

还可以使用其他类型的数据存储,例如文件系统上的文件或内存中的大型哈希表,但对于这些类型的系统,数据读取和写入不会那么快速和容易。

如今,我们使用关系数据库管理系统(RDBMS)来存储和管理大量数据。这称为关系数据库,因为所有数据都存储在不同的表中,并且使用主键或称为外键的其他键建立关系

一个关系数据库管理系统(RDBMS)是一种软件-

  • 使您能够使用表,列和索引实现数据库。

  • 保证各行表之间的参照完整性。

  • 自动更新索引。

  • 解释SQL查询并合并来自各种表的信息。

RDBMS术语

在我们继续解释MySQL数据库系统之前,让我们了解一些与数据库相关的定义。

  • 数据库(Database) - 数据库是包含相关数据的表的集合。

  • 表格(Table) - 表格是包含数据的矩阵。数据库中的表格看起来像一个简单的电子表格。

  • 列(Column) - 一列(数据元素)包含同一种类的数据,例如列邮政编码。

  • 行(Row) - 行(=元组,条目或记录)是一组相关数据,例如一个订阅的数据。

  • 冗余(Redundancy) - 冗余存储数据两次,以使系统更快。

  • 主键(Primary Key) - 主键是唯一的。在一个表中键值不能出现两次。用这个key,你只能找到一行。

  • 外键(Foreign key) - 外键是两个表之间的连接,通过外键,将两个表建立关联。

  • 复合键(Compound Key) - 复合键(有的也称为联合主键)是一个由多列组成的键,因为一列不够唯一确定一条数据。

  • 索引(Index) - 数据库中的索引类似于一本书的目录,通过索引可以快速地定位数据。

  • 参照完整性(Referential Integrity) - 参照完整性可确保外键值始终指向现有行。

MySQL数据库

MySQL是一种快速,易用的RDBMS,可用于许多小型和大型企业。MySQL由瑞典公司MySQL AB开发。由于许多原因,MySQL变得很受欢迎 -

  • MySQL是在开源许可下发布的。所以你没有钱可以使用它。

  • MySQL本身就是一个非常强大的程序。它处理最昂贵和最强大的数据库包的大部分功能。

  • MySQL使用众所周知的SQL数据语言的标准格式。

  • MySQL可以在许多操作系统上运行,并且支持多种语言,包括PHP,PERL,C,C ++,JAVA等。

  • 即使使用大型数据集,MySQL的工作速度也非常快并且运行良好

  • MySQL对PHP非常友好,这是最受欢迎的Web开发语言。

  • MySQL支持大型数据库,最多可以有5000万行或更多的表。表格的默认文件大小限制为4GB,但您可以将此限制(如果您的操作系统可以处理它)达到800万TB的理论限制。

  • MySQL是可定制的。开源GPL许可证允许程序员修改MySQL软件以适应他们自己的特定环境。

  • 2 MySQL - 安装

    在Linux / UNIX上安装MySQL

    在Linux系统上安装MySQL的推荐方式是通过RPM。MySQL AB在其网站上提供以下RPM供下载 -

    • MySQL - MySQL数据库服务器管理数据库和表,控制用户访问并处理SQL查询。

    • MySQL-client - MySQL客户端程序,它可以连接到服务器并与服务器交互。

    • MySQL-devel - 编译其他使用MySQL的程序时可以方便使用的库和头文件。

    • MySQL-shared - MySQL客户端的共享库。

    • MySQL-bench - MySQL数据库服务器的基准测试和性能测试工具。

    这里列出的MySQL RPM都是建立在SuSE Linux系统上的,但它们通常可以在其他Linux变体上工作,没有任何问题。

    现在,您需要遵循以下步骤进行安装 -

    • 使用root用户登录系统

    • 切换到包含MySQL RPM的目录。

    • 通过执行以下命令来安装MySQL数据库服务器。请记住用斜体文件名替换斜体文件名。

    [root@host]# rpm -i MySQL-5.0.9-0.i386.rpm
    

    上述命令负责安装MySQL服务器,创建MySQL用户,创建必要的配置并自动启动MySQL服务器。

    您可以在/usr/bin和/usr/sbin中找到所有与MySQL相关的二进制文件。所有表和数据库将在/var/lib/mysql目录中创建。

    • 以下代码框有一个可选但推荐的步骤,以相同的方式安装剩余的RPM -

    [root@host]# rpm -i MySQL-client-5.0.9-0.i386.rpm
    [root@host]# rpm -i MySQL-devel-5.0.9-0.i386.rpm
    [root@host]# rpm -i MySQL-shared-5.0.9-0.i386.rpm
    [root@host]# rpm -i MySQL-bench-5.0.9-0.i386.rpm
    

    在Windows上安装MySQL

    现在,任何版本的Windows上的默认安装都比以前更容易,因为现在MySQL已经整齐地与安装程序一起打包了。只需下载安装程序包,将其解压缩到任意位置并运行setup.exe文件即可。

    默认安装程序setup.exe将引导您完成简单的过程,默认情况下会将所有内容安装在C:\ mysql下。

    通过从命令提示符第一次启动服务器来测试服务器。转到mysqld服务器的位置,这个位置可能是C:\mysql\bin,然后键入 -

    mysqld.exe --console
    

     - 如果你在NT上,那么你将不得不使用mysqld-nt.exe而不是mysqld.exe

    如果一切顺利,你会看到关于启动和InnoDB的一些消息如果没有,您可能会遇到权限问题。确保数据库进程所运行的任何用户(可能是MySQL)都可以访问保存数据的目录。

    MySQL不会将自己添加到开始菜单,并且没有特别好的GUI方法来停止服务器。因此,如果您倾向于通过双击mysqld可执行文件来启动服务器,则应记住使用mysqladmin,任务列表,任务管理器或其他特定于Windows的方法手动停止该进程。

    验证MySQL安装

    在MySQL成功安装之后,基表已经初始化并且服务器已经启动:你可以通过一些简单的测试来验证一切正常。

    使用mysqladmin实用程序获取服务器状态

    使用mysqladmin二进制来检查服务器版本。这个二进制文件可以在linux上的/ usr / bin和windows上的C:\ mysql \ bin下使用。

    [root@host]# mysqladmin --version
    

    它将在Linux上产生以下结果。它可能会根据您的安装而有所不同 -

    mysqladmin  Ver 8.23 Distrib 5.0.9-0, for redhat-linux-gnu on i386
    

    如果你没有收到这样的消息,那么你的安装可能会有一些问题,你需要一些帮助来解决它。

    使用MySQL客户端执行简单的SQL命令

    您可以通过MySQL客户端并使用mysql命令连接到您的MySQL服务器此时,您不需要输入任何密码,它将被设置为空白。

    你可以使用下面的命令 -

    [root@host]# mysql
    

    应该会看到一个mysql>提示符。现在,您已连接到MySQL服务器,并且您可以在mysql>提示符处执行所有SQL命令,如下所示 -

    mysql> SHOW DATABASES;
    +----------+
    | Database |
    +----------+
    |   mysql  | 
    |   test   |  
    +----------+
    2 rows in set (0.13 sec)
    

    安装后步骤

    MySQL为root用户提供一个空密码。只要成功安装了数据库和客户端,就需要设置以下代码块中给出的root密码 -

    [root@host]# mysqladmin -u root password "new_password";
    

    现在连接到你的MySQL服务器,使用下面的命令 -

    [root@host]# mysql -u root -p
    Enter password:*******
    

    UNIX用户也希望将你的MySQL目录放入你的PATH中,这样你就不必在每次使用命令行客户端时都输入完整的路径。

    对于bash来说,它会是这样 -

    export PATH = $PATH:/usr/bin:/usr/sbin
    

    在启动时运行MySQL

    如果你想在启动时运行MySQL服务器,那么确保你在/etc/rc.local文件中有以下条目。

    /etc/init.d/mysqld start
    

    另外,你应该在/etc/init.d/目录下有mysqld二进制文件。

    3 管理和连接

    运行并关闭MySQL服务器

    首先检查你的MySQL服务器是否正在运行。您可以使用以下命令来检查它 -

    ps -ef | grep mysqld
    

    如果您的MySql正在运行,那么您会在结果中看到mysqld进程。如果服务器未运行,则可以使用以下命令启动它 -

    root@host# cd /usr/bin
    ./safe_mysqld &
    

    现在,如果你想关闭一个已经运行的MySQL服务器,那么你可以通过使用下面的命令来完成 -

    root@host# cd /usr/bin
    ./mysqladmin -u root -p shutdown
    Enter password: ******
    

    设置MySQL用户帐户

    为了向MySQL添加新用户,只需要在数据库mysql中用户表中添加一个新条目即可

    以下程序是使用密码guest123添加具有SELECT,INSERT和UPDATE特权的新用户访客示例; SQL查询是 -

    root@host# mysql -u root -p
    Enter password:*******
    mysql> use mysql;
    Database changed
    
    mysql> INSERT INTO user 
              (host, user, password, 
               select_priv, insert_priv, update_priv) 
               VALUES ('localhost', 'guest', 
               PASSWORD('guest123'), 'Y', 'Y', 'Y');
    Query OK, 1 row affected (0.20 sec)
    
    mysql> FLUSH PRIVILEGES;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> SELECT host, user, password FROM user WHERE user = 'guest';
    +-----------+---------+------------------+
    |    host   |   user  |     password     |    
    +-----------+---------+------------------+
    | localhost |  guest  | 6f8c114b58f2ce9e |
    +-----------+---------+------------------+
    1 row in set (0.00 sec)
    

    添加新用户时,请记住使用MySQL提供的PASSWORD()函数加密新密码。如上例所示,密码mypass被加密为6f8c114b58f2ce9e。

    注意FLUSH PRIVILEGES声明。这告诉服务器重新加载授权表。如果您不使用它,则至少在服务器重新启动之前,您将无法使用新的用户帐户连接到MySQL。

    您还可以通过在执行INSERT查询时将用户表中以下列的值设置为'Y',或者可以稍后使用UPDATE查询更新它们,为新用户指定其他权限。

    • Select_priv
    • Insert_priv
    • Update_priv
    • Delete_priv
    • Create_priv
    • Drop_priv
    • Reload_priv
    • Shutdown_priv
    • Process_priv
    • File_priv
    • Grant_priv
    • References_priv
    • Index_priv
    • Alter_priv

    添加用户帐户的另一种方法是使用GRANT SQL命令。以下示例将为特定数据库(名为TUTORIALS)添加用户zara,密码为zara123

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use mysql;
    Database changed
    
    mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
        -> ON TUTORIALS.*
        -> TO 'zara'@'localhost'
        -> IDENTIFIED BY 'zara123';
    

    这也将在称为user的MySQL数据库表中创建一个条目

     - 在SQL命令结尾处给出一个分号(;)。分号代表一个SQL语句的结束。

    /etc/my.cnf文件配置

    在大多数情况下,你不应该碰这个文件。默认情况下,它将包含以下条目 -

    [mysqld]
    datadir = /var/lib/mysql
    socket = /var/lib/mysql/mysql.sock
    
    [mysql.server]
    user = mysql
    basedir = /var/lib
    
    [safe_mysqld]
    err-log = /var/log/mysqld.log
    pid-file = /var/run/mysqld/mysqld.pid
    

    在这里,您可以为err-log指定一个不同的目录,否则您不应该更改此表中的任何条目。

    管理MySQL命令

    这里列出了一些重要的MySQL命令,你将会花时间使用MySQL数据库 -

    • USE Databasename - 这将用于在MySQL工作区中选择一个数据库。

    • SHOW DATABASES - 列出可由MySQL DBMS访问的数据库。

    • SHOW TABLES - 使用use命令选择数据库后,显示数据库中的表格。

    • SHOW COLUMNS FROM tablename:显示属性,属性类型,关键信息,是否允许NULL,默认值以及表的其他信息。

    • SHOW INDEX FROM tablename - 提供中所有索引的详细信息,包括PRIMARY KEY。

    • SHOW TABLE STATUS LIKE tablename\G - 报告MySQL DBMS性能和统计信息的详细信息。

    MySQL的连接

    您可以在命令提示符下使用mysql二进制文件建立MySQL数据库

    这里是一个简单的例子,从命令提示符连接到MySQL服务器 -

    [root@host]# mysql -u root -p
    Enter password:******
    

    这将为您提供mysql>命令提示符,您将可以在其中执行任何SQL命令。以下是上述命令的结果 -

    以下代码块显示了上述代码的结果 -

    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2854760 to server version: 5.0.9
    
    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
    

    在上面的例子中,我们使用root作为用户,但您也可以使用任何其他用户。任何用户都将能够执行所有允许该用户使用的SQL操作。

    您可以随时使用mysql>提示符下exit命令从MySQL数据库断开连接

    mysql> exit
    Bye

    4 数据类型

    正确定义表中的字段对于数据库的整体优化非常重要。您应该只使用您真正需要使用的字段的类型和大小。例如,如果您知道只打算使用2个字符,则不要定义10个字符的字段。这些类型的字段(或列)的,也被称为数据类型,所述后数据的类型,你会在这些字段中存储。

    MySQL使用了很多不同的数据类型,分为三类 -

    • 数字
    • 日期和时间
    • 字符串类型。

    现在让我们详细讨论它们。

    数字数据类型

    MySQL使用所有标准的ANSI SQL数字数据类型,所以如果你从不同的数据库系统来到MySQL,这些定义对你来说看起来很熟悉。以下列表显示了常用的数字数据类型及其说明 -

    • INT - 可以有符号或无符号的正常大小的整数。如果有符号,则允许的范围是-2147483648到2147483647.如果没有符号,则允许的范围是从0到4294967295.您可以指定最多11位数的宽度。

    • TINYINT - 可以是有符号或无符号的非常小的整数。如果有符号,则允许的范围是从-128到127.如果没有符号,则允许的范围是从0到255.您可以指定最多4位数的宽度。

    • SMALLINT - 可以是有符号或无符号的小整数。如果有符号,则允许的范围是从-32768到32767.如果没有符号,则允许的范围是从0到65535.您可以指定最多5位数的宽度。

    • MEDIUMINT - 可以有符号或无符号的中等大小的整数。如果有符号,则允许的范围是-8388608到8388607.如果没有符号,允许的范围是从0到16777215.您可以指定最多9位数的宽度。

    • BIGINT - 可以是有符号或无符号的大整数。如果有符号,则允许的范围是从-9223372036854775808到9223372036854775807.如果没有符号,允许的范围是从0到18446744073709551615。您可以指定最多20位数的宽度。

    • FLOAT(M,D) - 有符号的浮点数。您可以定义显示长度(M)和小数位数(D)。长度和小数位数不是必须指定的,默认为10,2,其中2是小数位数,10是总位数(包括小数位数)。小数精度可以达到24位FLOAT。

    • DOUBLE(M,D) - 有符号的双精度浮点数。您可以定义显示长度(M)和小数位数(D)。这不是必需的,默认为16,4,其中4是小数位数。小数精度可以达到53个地方的DOUBLE。REAL是DOUBLE的同义词。

    • DECIMAL(M,D) - 一个不能无符号的解压后的浮点数。在解压缩的小数中,每个小数对应一个字节。定义显示长度(M)和小数位数(D)是必需的。NUMERIC是DECIMAL的同义词。

    日期和时间类型

    MySQL的日期和时间数据类型如下 -

    • DATE - YYYY-MM-DD格式的日期,介于1000-01-01和9999-12-31之间。例如,1973年12月30 将保存为1973-12-30。

    • DATETIME - 日期和时间组合,格式为YYYY-MM-DD HH:MM:SS,格式为1000-01-01 00:00:00至9999-12-31 23:59:59。例如,1973 年12月30 下午3点30分将存储为1973-12-30 15:30:00。

    • TIMESTAMP - 1970年1月1 午夜到2037 年某个时间的时间戳。这看起来像以前的DATETIME格式,只有数字之间没有连字符; 1973 年12月30 日下午3点30分将存储为19731230153000(YYYYMMDDHHMMSS)。

    • TIME - 以HH:MM:SS格式存储时间。

    • YEAR(M) - 以2位或4位数格式存储一年。如果长度指定为2(例如YEAR(2)),YEAR可以介于1970到2069(70到69)之间。如果长度指定为4,那么YEAR可以是1901到2155.默认长度是4。

    字符串类型

    尽管数字和日期类型很有趣,但您将要存储的大部分数据都是字符串格式。该列表描述了MySQL中的常用字符串数据类型。

    • CHAR(M) - 一个长度在1到255个字符之间的固定长度字符串(例如CHAR(5)),存储时用空格指定长度的空格。定义长度不是必需的,但默认值是1。

    • VARCHAR(M) - 长度介于1到255个字符之间的可变长度字符串。例如,VARCHAR(25)。创建VARCHAR字段时必须定义一个长度。

    • BLOB或TEXT - 最大长度为65535个字符的字段。BLOB是“二进制大对象”,用于存储大量的二进制数据,如图像或其他类型的文件。定义为TEXT的字段也包含大量数据。两者的区别在于对存储数据的排序和比较在BLOB 区分大小写,并且在TEXT字段不区分大小写您不用BLOB或TEXT指定长度。

    • TINYBLOB或TINYTEXT - 最大长度为255个字符的BLOB或TEXT列。您不用TINYBLOB或TINYTEXT指定长度。

    • MEDIUMBLOB或MEDIUMTEXT - BLOB或TEXT列,最大长度为16777215个字符。您不用MEDIUMBLOB或MEDIUMTEXT指定长度。

    • LONGBLOB或LONGTEXT - 最大长度为4294967295个字符的BLOB或TEXT列。您不用LONGBLOB或LONGTEXT指定长度。

    • ENUM - 枚举,这是一个列表的幻想术语。在定义ENUM时,您正在创建一个项目列表,从中必须选择该值(或者可以为NULL)。例如,如果您希望您的字段包含“A”或“B”或“C”,您可以将ENUM定义为ENUM('A','B','C'),并且只有那些值(或NULL)可以永远填充该领域。

    5 常用操作

    使用mysqladmin创建数据库

    您需要特殊权限才能创建或删除MySQL数据库。所以假设你有权访问root用户,你可以使用mysql mysqladmin二进制创建任何数据库

    这里有一个简单的例子来创建一个名为TUTORIALS的数据库-

    [root@host]# mysqladmin -u root -p create TUTORIALS
    Enter password:******
    

    这将创建一个名为TUTORIALS的MySQL数据库。

    使用mysqladmin删除数据库

    您需要特殊权限才能创建或删除MySQL数据库。所以,假设您有权访问root用户,您可以使用mysql mysqladmin二进制文件创建任何数据库

    删除任何数据库时要小心,因为您将丢失数据库中的所有可用数据。

    这里是删除上一章中创建的数据库(TUTORIALS)的示例 -

    [root@host]# mysqladmin -u root -p drop TUTORIALS
    Enter password:******
    

    这会给你一个警告,它会确认你是否真的想删除这个数据库。

    Dropping the database is potentially a very bad thing to do.
    Any data stored in the database will be destroyed.
    
    Do you really want to drop the 'TUTORIALS' database [y/N] y
    Database "TUTORIALS" dropped

    一旦你连接到MySQL服务器,就需要选择一个数据库来处理。这是因为MySQL服务器可能有多个数据库可用。

    从命令提示符中选择MySQL数据库

    从mysql>提示符中选择数据库非常简单。您可以使用SQL命令使用选择一个数据库。

    这里是一个选择名为TUTORIALS的数据库的例子-

    [root@host]# mysql -u root -p
    Enter password:******
    mysql> use TUTORIALS;
    Database changed
    mysql> 
    

    现在,您已经选择了TUTORIALS数据库,并且所有后续操作都将在TUTORIALS数据库上执行。

     - 所有数据库名称,表名称,表字段名称都区分大小写。因此,在给出任何SQL命令时,您必须使用正确的名称。

    创建表

    首先,表创建命令需要以下细节 -

    • 表格的名称
    • 字段的名称
    • 每个字段的定义

    语法

    以下是创建MySQL表的通用SQL语法 -

    CREATE TABLE table_name (column_name column_type);
    

    现在,我们将在TUTORIALS数据库中创建下表

    create table tutorials_tbl(
       tutorial_id INT NOT NULL AUTO_INCREMENT,
       tutorial_title VARCHAR(100) NOT NULL,
       tutorial_author VARCHAR(40) NOT NULL,
       submission_date DATE,
       PRIMARY KEY ( tutorial_id )
    );
    

    在这里,需要解释一下 -

    • 字段属性NOT NULL,因为我们不希望该字段为NULL。所以,如果用户尝试创建一个带有NULL值的记录,那么MySQL将引发一个错误。

    • 字段属性AUTO_INCREMENT,告诉MySQL继续并将下一个可用数字添加到id字段。

    • 关键字PRIMARY KEY用于将列定义为主键。您可以使用由逗号分隔的多个列来定义主键。

    从命令提示符创建表

    从mysql>提示符创建MySQL表很容易。您将使用SQL命令CREATE TABLE创建一个表。

    这里是一个例子,它将创建tutorials_tbl -

    root@host# mysql -u root -p
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> CREATE TABLE tutorials_tbl(
       -> tutorial_id INT NOT NULL AUTO_INCREMENT,
       -> tutorial_title VARCHAR(100) NOT NULL,
       -> tutorial_author VARCHAR(40) NOT NULL,
       -> submission_date DATE,
       -> PRIMARY KEY ( tutorial_id )
       -> );
    Query OK, 0 rows affected (0.16 sec)
    mysql>
    

     - MySQL在SQL命令结尾处给出分号(;)。

    删除表

    删除现有的MySQL表非常容易,但是在删除任何现有表时需要非常小心,因为在删除表后数据丢失将不会恢复。

    语法

    这是一个通用的SQL语法来删除一个MySQL表 -

    DROP TABLE table_name ;
    

    从命令提示符中删除表

    要从命令提示符中删除表,我们需要在mysql>提示符下执行DROP TABLE SQL命令。

    以下程序是删除tutorials_tbl的示例-

    root@host# mysql -u root -p
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> DROP TABLE tutorials_tbl
    Query OK, 0 rows affected (0.8 sec)
    mysql>

    插入查询

    要将数据插入到MySQL表中,您需要使用SQL INSERT INTO命令。您可以使用mysql>提示或使用任何脚本(如PHP)将数据插入到MySQL表中。

    句法

    下面是INSERT INTO命令的通用SQL语法,用于将数据插入到MySQL表中 -

    INSERT INTO table_name ( field1, field2,...fieldN )
       VALUES
       ( value1, value2,...valueN );
    

    要插入字符串数据类型,需要将所有值保留为双引号或单引号。例如"value"

    从命令提示符插入数据

    要从命令提示符插入数据,我们将使用SQL INSERT INTO命令将数据插入到MySQL表tutorials_tbl中。

    以下示例将在tutorials_tbl表中创建3条记录-

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    
    mysql> INSERT INTO tutorials_tbl 
       ->(tutorial_title, tutorial_author, submission_date)
       ->VALUES
       ->("Learn PHP", "John Poul", NOW());
    Query OK, 1 row affected (0.01 sec)
    
    mysql> INSERT INTO tutorials_tbl
       ->(tutorial_title, tutorial_author, submission_date)
       ->VALUES
       ->("Learn MySQL", "Abdul S", NOW());
    Query OK, 1 row affected (0.01 sec)
    
    mysql> INSERT INTO tutorials_tbl
       ->(tutorial_title, tutorial_author, submission_date)
       ->VALUES
       ->("JAVA Tutorial", "Sanjay", '2007-05-06');
    Query OK, 1 row affected (0.01 sec)
    mysql>
    

     - 请注意,所有箭头符号( - >)不是SQL命令的一部分。它们表示一个新行,并且它们是通过MySQL提示符自动创建的,同时按下Enter键而不在命令的每行末尾添加分号。

    在上面的例子中,我们还没有提供tutorial_id,因为在创建表的时候,我们给了这个字段的AUTO_INCREMENT选项。所以MySQL负责自动插入这些ID。在这里,NOW()是一个MySQL函数,它返回当前的日期和时间。

    选择查询

    SQL SELECT命令用于从MySQL数据库中获取数据。您可以在mysql>提示符以及PHP等任何脚本中使用此命令。

    语法

    这里是SELECT命令的通用SQL语法从MySQL表中获取数据 -

    SELECT field1, field2,...fieldN 
    FROM table_name1, table_name2...
    [WHERE Clause]
    [OFFSET M ][LIMIT N]
    
    • 使用一个或多个以逗号分隔的表,使用WHERE子句包含各种条件,但WHERE子句是SELECT命令的可选部分。

    • 您可以在单个SELECT命令中获取一个或多个字段。

    • 您可以指定星号(*)代替字段。在这种情况下,SELECT将返回所有字段。

    • 您可以使用WHERE子句指定任何条件。

    • 您可以使用OFFSET指定一个偏移量,从SELECT开始返回记录。默认情况下,偏移量从零开始。

    • 您可以使用LIMIT属性限制返回次数

    从命令提示符获取数据

    这将使用SQL SELECT命令从MySQL表tutorials_tbl中获取数据

    以下示例将返回tutorials_tbl表中的所有记录-

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> SELECT * from tutorials_tbl 
    +-------------+----------------+-----------------+-----------------+
    | tutorial_id | tutorial_title | tutorial_author | submission_date |
    +-------------+----------------+-----------------+-----------------+
    |           1 | Learn PHP      | John Poul       | 2007-05-21      |
    |           2 | Learn MySQL    | Abdul S         | 2007-05-21      |
    |           3 | JAVA Tutorial  | Sanjay          | 2007-05-21      |
    +-------------+----------------+-----------------+-----------------+
    3 rows in set (0.01 sec)
    
    mysql>

    WHERE子句

    我们已经看到SQL SELECT命令从MySQL表中获取数据。我们可以使用一个名为WHERE子句的条件子句来过滤出结果。使用这个WHERE子句,我们可以指定一个选择标准从表中选择所需的记录。

    语法

    以下代码块具有SELECT命令的通用SQL语法和WHERE子句以从MySQL表中获取数据 -

    SELECT field1, field2,...fieldN table_name1, table_name2...
    [WHERE condition1 [AND [OR]] condition2.....
    • 使用一个或多个以逗号分隔的表,以使用WHERE子句包含各种条件,但WHERE子句是SELECT命令的可选部分。

    • 您可以使用WHERE子句指定任何条件。

    • 您可以使用ANDOR运算符指定多个条件

    • WHERE子句可以与DELETE或UPDATE SQL命令一起使用来指定条件。

    WHERE子句的工作就像一个if条件中的任何编程语言。该子句用于将给定值与MySQL表中可用的字段值进行比较。如果来自外部的给定值等于MySQL表中的可用字段值,则它返回该行。

    以下是可以与WHERE子句一起使用的运算符列表

    假设字段A保存10,字段B保存20,则 -

    操作者 描述
    = 检查两个操作数的值是否相等,如果是,则条件成立。 (A = B)不正确。
    != 检查两个操作数的值是否相等,如果值不相等则条件成立。 (A!= B)是真的。
    > 检查左操作数的值是否大于右操作数的值,如果是,则条件成立。 (A> B)不正确。
    < 检查左操作数的值是否小于右操作数的值,如果是,则条件成立。 (A <B)是真的。
    > = 检查左操作数的值是否大于或等于右操作数的值,如果是,则条件成立。 (A> = B)不正确。
    <= 检查左操作数的值是否小于或等于右操作数的值,如果是,则条件成立。 (A <= B)为真。

    当您想要从表中提取选定的行时,WHERE子句非常有用,特别是当您使用MySQL连接时连接在另一章讨论。

    使用主键搜索记录以加快搜索速度是一种常见做法

    如果给定的条件不匹配表中的任何记录,那么查询将不会返回任何行。

    从命令提示符获取数据

    这将使用SQL SELECT命令和WHERE子句从MySQL表中提取选定的数据 - tutorials_tbl

    以下示例将返回authors名称为Sanjaytutorials_tbl表中的所有记录

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> SELECT * from tutorials_tbl WHERE tutorial_author = 'Sanjay';
    +-------------+----------------+-----------------+-----------------+
    | tutorial_id | tutorial_title | tutorial_author | submission_date |
    +-------------+----------------+-----------------+-----------------+
    |      3      | JAVA Tutorial  |      Sanjay     |    2007-05-21   |      
    +-------------+----------------+-----------------+-----------------+
    1 rows in set (0.01 sec)
    
    mysql>

    除非对字符串执行LIKE比较,否则比较不区分大小写。您可以按照以下方式使用BINARY关键字使搜索区分大小写-

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> SELECT * from tutorials_tbl \
       WHERE BINARY tutorial_author = 'sanjay';
    Empty set (0.02 sec)
    
    mysql>

    更新查询

    可能需要修改MySQL表中现有数据的位置。您可以通过使用SQL UPDATE命令来完成此操作。这将修改任何MySQL表的任何字段值。

    语法

    以下代码块具有UPDATE命令的通用SQL语法,用于修改MySQL表中的数据 -

    UPDATE table_name SET field1 = new-value1, field2 = new-value2
    [WHERE Clause]
    • 您可以完全更新一个或多个字段。
    • 您可以使用WHERE子句指定任何条件。
    • 您可以一次更新单个表中的值。

    当您想要更新表中的选定行时,WHERE子句非常有用。

    从命令提示符更新数据

    这将使用SQL UPDATE命令和WHERE子句更新MySQL表tutorials_tbl中的选定数据

    以下示例将更新tutorial_id为3的记录tutorial_title字段。

    root@host# mysql -u root -p password;
    Enter password:*******
    
    mysql> use TUTORIALS;
    Database changed
    
    mysql> UPDATE tutorials_tbl 
       -> SET tutorial_title = 'Learning JAVA' 
       -> WHERE tutorial_id = 3;
    Query OK, 1 row affected (0.04 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql>

    删除查询

    如果要从任何MySQL表中删除记录,则可以使用SQL命令DELETE FROM您可以在mysql>提示符以及PHP等任何脚本中使用此命令。

    句法

    以下代码块具有DELETE命令的通用SQL语法,用于从MySQL表中删除数据。

    DELETE FROM table_name [WHERE Clause]
    
    • 如果未指定WHERE子句,则将从给定的MySQL表中删除所有记录。

    • 您可以使用WHERE子句指定任何条件。

    • 您可以一次删除单个表中的记录。

    当您想要删除表中的选定行时,WHERE子句非常有用。

    从命令提示符中删除数据

    这将使用SQL DELETE命令和WHERE子句将选定的数据删除到MySQL表 - tutorials_tbl

    以下示例将从tutorial_id为3的tutorial_tbl中删除一条记录。

    root@host# mysql -u root -p password;
    Enter password:*******
    
    mysql> use TUTORIALS;
    Database changed
    
    mysql> DELETE FROM tutorials_tbl WHERE tutorial_id=3;
    Query OK, 1 row affected (0.23 sec)
    
    mysql>

    LIKE子句

    我们看到了SQL SELECT命令从MySQL表中获取数据。我们也可以使用称为WHERE子句的条件子句来选择所需的记录。

    “等于”符号(=)的WHERE子句适用于我们想要进行完全匹配的地方。就像“tutorial_author ='Sanjay'”一样。但是可能有一个要求,我们希望过滤掉tutorial_author名称应该包含“jay”的所有结果。这可以使用SQL LIKE子句和WHERE子句来处理

    如果SQL LIKE子句与%字符一起使用,则它将像UNIX中的元字符(*)那样工作,同时列出命令提示符下的所有文件或目录。如果没有%字符,那么LIKE子句与WHERE子句等号一样

    语法

    以下代码块具有SELECT命令的通用SQL语法以及LIKE子句以从MySQL表中获取数据。

    SELECT field1, field2,...fieldN table_name1, table_name2...
    WHERE field1 LIKE condition1 [AND [OR]] filed2 = 'somevalue'
    
    • 您可以使用WHERE子句指定任何条件。

    • 您可以使用LIKE子句和WHERE子句。

    • 您可以使用LIKE子句代替等号进行签名。

    • 当LIKE与%符号一起使用时,它将像元字符搜索一样工作。

    • 您可以使用ANDOR运算符指定多个条件

    • WHERE ... LIKE子句可以与DELETE或UPDATE SQL命令一起使用来指定条件。

    在命令提示符处使用LIKE子句

    这将使用SQL SELECT命令和WHERE ... LIKE子句从MySQL表中获取选定的数据 - tutorials_tbl

    以下示例将返回作者姓名以jay结尾tutorials_tbl表中的所有记录-

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> SELECT * from tutorials_tbl 
        -> WHERE tutorial_author LIKE '%jay';
    +-------------+----------------+-----------------+-----------------+
    | tutorial_id | tutorial_title | tutorial_author | submission_date |
    +-------------+----------------+-----------------+-----------------+
    |      3      |  JAVA Tutorial |     Sanjay      |    2007-05-21   |   
    +-------------+----------------+-----------------+-----------------+
    1 rows in set (0.01 sec)
    
    mysql>

    结果排序

    我们已经看到SQL SELECT命令从MySQL表中获取数据。当你选择行时,MySQL服务器可以以任何顺序自由返回它们,除非你通过说明如何对结果进行排序来指示它。但是,您可以通过添加一个ORDER BY子句来对结果集进行排序,该子句用于命名要排序的一列或多列。

    句法

    以下代码块是SELECT命令的通用SQL语法以及ORDER BY子句,用于对MySQL表中的数据进行排序。

    SELECT field1, field2,...fieldN table_name1, table_name2...
    ORDER BY field1, [field2...] [ASC [DESC]]
    
    • 如果该字段被列出,您可以对任何字段的返回结果进行排序。

    • 您可以在多个字段上对结果进行排序。

    • 您可以使用关键字ASC或DESC以升序或降序获得结果。默认情况下,它是升序。

    • 您可以通常的方式使用WHERE ... LIKE子句来放置一个条件。

    在命令提示符处使用ORDER BY子句

    这将使用SQL SELECT命令和ORDER BY子句从MySQL表中获取数据 - tutorials_tbl

    试试下面的例子,它按照升序返回结果。

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> SELECT * from tutorials_tbl ORDER BY tutorial_author ASC
    +-------------+----------------+-----------------+-----------------+
    | tutorial_id | tutorial_title | tutorial_author | submission_date |
    +-------------+----------------+-----------------+-----------------+
    |      2      |  Learn MySQL   |     Abdul S     |    2007-05-24   |   
    |      1      |   Learn PHP    |    John Poul    |    2007-05-24   |   
    |      3      | JAVA Tutorial  |     Sanjay      |    2007-05-06   |   
    +-------------+----------------+-----------------+-----------------+
    3 rows in set (0.42 sec)
    
    mysql>

    验证按升序列出的所有作者姓名。

    关联表

    在前面的章节中,我们一次只从一个表中获取数据。这对于简单的需求来说已经足够了,但是在大多数真实世界的MySQL中,您通常需要在单个查询中从多个表中获取数据。

    您可以在单个SQL查询中使用多个表。加入MySQL的行为是指将两个或多个表格拆分成一个表格。

    您可以在SELECT,UPDATE和DELETE语句中使用JOINS来加入MySQL表。我们将看到一个与简单的MySQL JOIN不同的LEFT JOIN的例子。

    在命令提示符处使用关联

    假设在TUTORIALS中我们有两个表tcount_tbltutorials_tbl现在看看下面给出的例子 -

    以下例子 -

    root@host# mysql -u root -p password;
    Enter password:*******
    mysql> use TUTORIALS;
    Database changed
    mysql> SELECT * FROM tcount_tbl;
    +-----------------+----------------+
    | tutorial_author | tutorial_count |
    +-----------------+----------------+
    |      mahran     |       20       |     
    |      mahnaz     |      NULL      |        
    |       Jen       |      NULL      |          
    |      Gill       |       20       |          
    |    John Poul    |        1       |      
    |     Sanjay      |        1       |        
    +-----------------+----------------+
    6 rows in set (0.01 sec)
    mysql> SELECT * from tutorials_tbl;
    +-------------+----------------+-----------------+-----------------+
    | tutorial_id | tutorial_title | tutorial_author | submission_date |
    +-------------+----------------+-----------------+-----------------+
    |      1      |  Learn PHP     |     John Poul   |    2007-05-24   |   
    |      2      |  Learn MySQL   |      Abdul S    |    2007-05-24   |   
    |      3      | JAVA Tutorial  |      Sanjay     |    2007-05-06   |   
    +-------------+----------------+-----------------+-----------------+
    3 rows in set (0.00 sec)
    mysql>

    现在我们可以编写一个SQL查询来连接这两个表。该查询将从表tutorials_tbl中选择所有作者,并从tcount_tbl中选取相应数量的教程

    mysql> SELECT a.tutorial_id, a.tutorial_author, b.tutorial_count
        -> FROM tutorials_tbl a, tcount_tbl b
        -> WHERE a.tutorial_author = b.tutorial_author;
    +-------------+-----------------+----------------+
    | tutorial_id | tutorial_author | tutorial_count |
    +-------------+-----------------+----------------+
    |      1      |    John Poul    |        1       |
    |      3      |     Sanjay      |        1       |
    +-------------+-----------------+----------------+
    2 rows in set (0.01 sec)
    mysql>

    6 高级知识

    NULL值处理

    我们已经看到SQL SELECT命令和WHERE子句一起从MySQL表中获取数据,但是当我们试图给出一个条件时,该条件将字段或列值与NULL进行比较时,它无法正常工作。

    为了处理这种情况,MySQL提供了三种操作 -

    • IS NULL - 如果列值为NULL,则此运算符返回true。

    • IS NOT NULL - 如果列值不为NULL,则此运算符返回true。

    • <=> - 该运算符比较值,即使对于两个NULL值(与=运算符不同)也是如此。

    涉及NULL的条件是特殊的。您不能使用= NULL或!= NULL在列中查找空值。这种比较总是失败,因为不可能判断它们是否属实。有时,即使NULL = NULL也会失败。

    要查找是否为NULL的列,请使用IS NULLIS NOT NULL

    在命令提示符处使用NULL值

    假设TUTORIALS数据库中有一个名为tcount_tbl的表,它包含两列,即tutorial_authortutorial_count,其中NULL tutorial_count表示该值未知。

    尝试下面的例子 -

    root@host# mysql -u root -p password;
    Enter password:*******
    
    mysql> use TUTORIALS;
    Database changed
    
    mysql> create table tcount_tbl
       -> (
       -> tutorial_author varchar(40) NOT NULL,
       -> tutorial_count  INT
       -> );
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> INSERT INTO tcount_tbl
       -> (tutorial_author, tutorial_count) values ('mahran', 20);
    
    mysql> INSERT INTO tcount_tbl
       -> (tutorial_author, tutorial_count) values ('mahnaz', NULL);
    
    mysql> INSERT INTO tcount_tbl
       -> (tutorial_author, tutorial_count) values ('Jen', NULL);
    
    mysql> INSERT INTO tcount_tbl
       -> (tutorial_author, tutorial_count) values ('Gill', 20);
    
    mysql> SELECT * from tcount_tbl;
    +-----------------+----------------+
    | tutorial_author | tutorial_count |
    +-----------------+----------------+
    |     mahran      |       20       |
    |     mahnaz      |      NULL      |
    |      Jen        |      NULL      |
    |     Gill        |       20       |
    +-----------------+----------------+
    4 rows in set (0.00 sec)
    
    mysql>
    

    你可以看到=和!=不能和NULL值一起工作,如下所示 -

    mysql> SELECT * FROM tcount_tbl WHERE tutorial_count = NULL;
    Empty set (0.00 sec)
    
    mysql> SELECT * FROM tcount_tbl WHERE tutorial_count != NULL;
    Empty set (0.01 sec)
    

    要查找tutorial_count列是否为NULL的记录,应按以下程序中所示编写查询。

    mysql> SELECT * FROM tcount_tbl 
        -> WHERE tutorial_count IS NULL;
    +-----------------+----------------+
    | tutorial_author | tutorial_count |
    +-----------------+----------------+
    |     mahnaz      |      NULL      |
    |      Jen        |      NULL      |
    +-----------------+----------------+
    2 rows in set (0.00 sec)
    mysql> SELECT * from tcount_tbl 
        -> WHERE tutorial_count IS NOT NULL;
    +-----------------+----------------+
    | tutorial_author | tutorial_count |
    +-----------------+----------------+
    |     mahran      |       20       |
    |     Gill        |       20       |
    +-----------------+----------------+
    2 rows in set (0.00 sec)

    正则表达式

    你已经看到MySQL模式与LIKE ...%匹配MySQL支持基于正则表达式和REGEXP运算符的另一种模式匹配操作如果您知道PHP或PERL,那么您理解起来非常简单,因为这种匹配与正则表达式的脚本相同。

    以下是模式表,可以和REGEXP运算符一起使用

    模式 模式匹配
    ^ 字符串的开始
    $ 字符串结尾
    . 任何单个字符
    [...] 在方括号之间列出的任何字符
    [^ ...] 未在方括号之间列出的任何字符
    P1 | P2 | P3 轮换; 匹配任何模式p1,p2或p3
    * 前面元素的零个或多个实例
    + 前面元素的一个或多个实例
    {N} 先前元素的n个实例
    {M,N} m到前面元素的n个实例

    现在基于上表,您可以设备的各种类型的SQL查询来满足您的要求。在这里,我列出了一些用于理解的内容。

    考虑我们有一个名为person_tbl的表,它有一个名为name的字段-

    查询以查找以“st”开头的所有名称-

    mysql> SELECT name FROM person_tbl WHERE name REGEXP '^st';

    查询以查找以'ok'结尾的所有名字-

    mysql> SELECT name FROM person_tbl WHERE name REGEXP 'ok$';

    查询以查找包含'mar'的所有名称-

    mysql> SELECT name FROM person_tbl WHERE name REGEXP 'mar';

    查询查找所有以元音开头并以'ok'结尾的名字-

    mysql> SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$';

    事务

    事务是一组连续的数据库操作操作,其操作就好像它是一个单一的工作单元。换句话说,除非组内的每个单独操作都成功,否则事务永远不会完成。如果事务中的任何操作失败,则整个事务将失败。

    实际上,您会将许多SQL查询分组到一个组中,并且您将将它们全部作为事务的一部分执行。

    事务的属性

    事务具有以下四种标准属性,通常由首字母缩略词ACID引用-

    • 原子性(Atomicity) - 确保工作单元内的所有操作都成功完成; 否则,事务在故障点中止并且以前的操作回滚到它们以前的状态。

    • 一致性(Consistency) - 确保数据库在成功提交事务后正确更改状态。

    • 隔离(Isolation) - 这使事务可以独立运作,并且彼此透明。

    • 耐久性(Durability) - 确保承诺交易的结果或效果在系统故障的情况下持续存在。

    在MySQL中,事务以语句BEGIN WORK开始并以COMMITROLLBACK语句结束。开始和结束语句之间的SQL命令构成了事务的批量。

    COMMIT和ROLLBACK

    这两个关键字CommitRollback主要用于MySQL事务。

    • 成功的事务完成后,应发出COMMIT命令,以便对所有涉及表的更改生效。

    • 如果发生故障,应该发出一个ROLLBACK命令来将事务中引用的每个表返回到其先前的状态。

    您可以通过设置名为AUTOCOMMIT的会话变量来控制事务的行为如果AUTOCOMMIT设置为1(缺省值),那么每个SQL语句(在一个事务中或不在一个事务中)都被认为是一个完整的事务,并在完成时默认提交。

    当AUTOCOMMIT设置为0时,通过发出SET AUTOCOMMIT = 0命令,随后的一系列语句就像事务一样,直到发出明确的COMMIT语句才会提交任何活动。

    您可以使用mysql_query()函数在PHP中执行这些SQL命令

    事务的一般示例

    这一系列事件独立于所使用的编程语言。逻辑路径可以用您用来创建应用程序的任何语言来创建。

    您可以使用mysql_query()函数在PHP中执行这些SQL命令

    • 通过发出SQL命令BEGIN WORK开始事务

    • 发出一个或多个SQL命令,如SELECT,INSERT,UPDATE或DELETE。

    • 检查是否没有错误,一切都是根据您的要求。

    • 如果有任何错误,则发出ROLLBACK命令,否则发出COMMIT命令。

    MySQL中事务安全的表类型

    您不能直接使用交易,但可以使用某些例外情况。但是,它们不安全并且有保证。如果您计划在MySQL编程中使用事务,那么您需要以特殊方式创建表。有很多类型的表支持事务,但最流行的是InnoDB

    从源代码编译MySQL时,对InnoDB表的支持需要一个特定的编译参数。如果您的MySQL版本没有InnoDB支持,请要求您的Internet服务提供商构建支持InnoDB表类型的MySQL版本,或者下载并安装适用于Windows或Linux / UNIX MySQL-Max二进制分发版,并使用表类型一个开发环境。

    如果您的MySQL安装支持InnoDB表,只需在表创建语句中添加TYPE = InnoDB定义即可。

    例如,下面的代码创建一个名为tcount_tbl的InnoDB表-

    root@host# mysql -u root -p password;
    Enter password:*******
    
    mysql> use TUTORIALS;
    Database changed
    
    mysql> create table tcount_tbl
       -> (
       -> tutorial_author varchar(40) NOT NULL,
       -> tutorial_count  INT
       -> ) TYPE = InnoDB;
    Query OK, 0 rows affected (0.05 sec)
    

    有关InnoDB的更多详细信息,您可以点击以下链接 - InnoDB

    您可以使用其他表类型,如GEMINIBDB,但它取决于您的安装,无论它是否支持这两种表类型。

    ALTER命令

    如果要更改表的名称,任何表字段或者如果要添加或删除表中的现有列,则MySQL ALTER命令非常有用。

    让我们从创建一个名为testalter_tbl的表开始

    root@host# mysql -u root -p password;
    Enter password:*******
    
    mysql> use TUTORIALS;
    Database changed
    
    mysql> create table testalter_tbl
       -> (
       -> i INT,
       -> c CHAR(1)
       -> );
    Query OK, 0 rows affected (0.05 sec)
    mysql> SHOW COLUMNS FROM testalter_tbl;
    +-------+---------+------+-----+---------+-------+
    | Field |  Type   | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    |   i   | int(11) | YES  |     |   NULL  |       |
    |   c   | char(1) | YES  |     |   NULL  |       |
    +-------+---------+------+-----+---------+-------+
    2 rows in set (0.00 sec)
    

    删除,添加或重新定位列

    如果您想从上面的MySQL表中删除现有的列,那么您将使用DROP子句和ALTER命令,如下所示 -

    mysql> ALTER TABLE testalter_tbl  DROP i;
    

    如果该列是表中唯一剩下的一个,则DROP子句将不起作用。

    要添加列,请使用ADD并指定列定义。以下语句将i恢复到testalter_tbl -

    mysql> ALTER TABLE testalter_tbl ADD i INT;
    

    在发布这个语句之后,testalter将包含与第一次创建表时相同的两列,但不会有相同的结构。这是因为默认情况下会在表的最后添加新列。所以即使最初是mytbl中的第一列,现在它已经是最后一个了。

    mysql> SHOW COLUMNS FROM testalter_tbl;
    +-------+---------+------+-----+---------+-------+
    | Field |  Type   | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    |   c   | char(1) | YES  |     |   NULL  |       |
    |   i   | int(11) | YES  |     |   NULL  |       |
    +-------+---------+------+-----+---------+-------+
    2 rows in set (0.00 sec)
    

    若要指示您希望在表格中的特定位置放置一列,请使用FIRST使其成为第一列或使用AFTER col_name来指示新列应置于col_name之后。

    尝试以下ALTER TABLE语句,在每个语句之后使用SHOW COLUMNS来查看每个语句的影响 -

    ALTER TABLE testalter_tbl DROP i;
    ALTER TABLE testalter_tbl ADD i INT FIRST;
    ALTER TABLE testalter_tbl DROP i;
    ALTER TABLE testalter_tbl ADD i INT AFTER c;
    

    FIRST和AFTER说明符只适用于ADD子句。这意味着如果您想重新定位表格中的现有列,您必须首先将其丢弃,然后在新位置添加它。

    更改(更改)列定义或名称

    要更改列的定义,请使用MODIFYCHANGE子句以及ALTER命令。

    例如,要将列c从CHAR(1)更改为CHAR(10),可以使用以下命令 -

    mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);
    

    使用CHANGE,语法有点不同。在CHANGE关键字之后,您指定要更改的列,然后指定包含新名称的新定义。

    试试下面的例子 -

    mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT;
    

    如果现在使用CHANGE将jBIGINT转换INT而不更改列名称,则语句如下所示 -

    mysql> ALTER TABLE testalter_tbl CHANGE j j INT;
    

    ALTER TABLE对空值和默认值属性的影响 - 当您修改或更改列时,还可以指定列是否可以包含NULL值以及默认值是什么。事实上,如果你不这样做,MySQL会自动为这些属性赋值。

    以下代码块是一个示例,其中NOT NULL列默认值为100。

    mysql> ALTER TABLE testalter_tbl 
       -> MODIFY j BIGINT NOT NULL DEFAULT 100;
    

    如果你不使用上面的命令,那么MySQL将在所有列中填充NULL值。

    更改(更改)列的默认值

    您可以使用ALTER命令更改任何列的默认值

    试试下面的例子。

    mysql> ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
    mysql> SHOW COLUMNS FROM testalter_tbl;
    +-------+---------+------+-----+---------+-------+
    | Field |  Type   | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    |   c   | char(1) | YES  |     |   NULL  |       |
    |   i   | int(11) | YES  |     |   1000  |       |
    +-------+---------+------+-----+---------+-------+
    2 rows in set (0.00 sec)
    

    通过使用DROP子句和ALTER命令,您可以从任何列中删除默认约束

    mysql> ALTER TABLE testalter_tbl ALTER i DROP DEFAULT;
    mysql> SHOW COLUMNS FROM testalter_tbl;
    +-------+---------+------+-----+---------+-------+
    | Field |  Type   | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    |   c   | char(1) | YES  |     |   NULL  |       |
    |   i   | int(11) | YES  |     |   NULL  |       |
    +-------+---------+------+-----+---------+-------+
    2 rows in set (0.00 sec)
    

    更改(更改)表格类型

    您可以通过使用TYPE子句和ALTER命令来使用表类型试试下面的例子将testalter_tbl改为MYISAM表类型。

    要找出表的当前类型,请使用SHOW TABLE STATUS语句。

    mysql> ALTER TABLE testalter_tbl TYPE = MYISAM;
    mysql>  SHOW TABLE STATUS LIKE 'testalter_tbl'\G
    *************************** 1. row ****************
               Name: testalter_tbl
               Type: MyISAM
         Row_format: Fixed
               Rows: 0
     Avg_row_length: 0
        Data_length: 0
    Max_data_length: 25769803775
       Index_length: 1024
          Data_free: 0
     Auto_increment: NULL
        Create_time: 2007-06-03 08:04:36
        Update_time: 2007-06-03 08:04:36
         Check_time: NULL
     Create_options:
            Comment:
    1 row in set (0.00 sec)
    

    重命名(更改)表

    要重命名表,请使用ALTER TABLE语句RENAME选项

    尝试以下示例将testalter_tbl重命名alter_tbl

    mysql> ALTER TABLE testalter_tbl RENAME TO alter_tbl;
    

    您可以使用ALTER命令在MySQL文件上创建和删除INDEX命令。我们将在下一章详细讨论这个命令。

    索引

    数据库索引是一种提高表中操作速度的数据结构。可以使用一列或多列创建索引,为快速随机查找和有效访问记录顺序提供基础。

    在创建索引时,应该考虑哪些列将用于进行SQL查询并在这些列上创建一个或多个索引。

    实际上,索引也是一种表格,它将主键或索引字段以及指向每个记录的指针保存到实际表中。

    用户看不到索引,它们只是用来加快查询速度,并且将被数据库搜索引擎用于非常快速地定位记录。

    INSERT和UPDATE语句在有索引的表上占用更多时间,而SELECT语句在这些表上变快。原因是在执行插入或更新时,数据库也需要插入或更新索引值。

    简单而独特的索引

    您可以在表格上创建唯一的索引。唯一索引意味着两行不能具有相同的索引值。以下是在表上创建索引的语法。

    CREATE UNIQUE INDEX index_name
    ON table_name ( column1, column2,...);
    

    您可以使用一个或多个列来创建索引。

    例如,我们可以使用tutorial_authortutorials_tbl上创建一个索引

    CREATE UNIQUE INDEX AUTHOR_INDEX
    ON tutorials_tbl (tutorial_author)
    

    您可以在表格上创建一个简单的索引。只需从查询中省略UNIQUE关键字即可创建简单的索引。简单索引允许在表中使用重复值。

    如果要按降序对列中的值进行索引,则可以在列名称后添加保留字DESC。

    mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
    ON tutorials_tbl (tutorial_author DESC)
    

    ALTER命令添加和删除INDEX

    有四种类型的用于向表中添加索引的语句 -

    • ALTER TABLE tbl_name ADD PRIMARY KEY(column_list) - 此语句添加PRIMARY KEY,这意味着索引值必须唯一且不能为NULL。

    • ALTER TABLE tbl_name ADD UNIQUE index_name(column_list) - 此语句创建一个索引,其值必须是唯一的(NULL值可能会多次出现)。

    • ALTER TABLE tbl_name ADD INDEX index_name(column_list) - 这增加了一个普通索引,其中任何值都可能出现多次。

    • ALTER TABLE tbl_name ADD FULLTEXT index_name(column_list) - 这会创建一个用于文本搜索的特殊FULLTEXT索引。

    以下代码块是在现有表中添加索引的示例。

    mysql> ALTER TABLE testalter_tbl ADD INDEX (c);
    

    您可以使用DROP子句和ALTER命令删除任何INDEX 

    试试下面的例子来删除上面创建的索引。

    mysql> ALTER TABLE testalter_tbl DROP INDEX (c);
    

    您可以使用DROP子句和ALTER命令删除任何INDEX。

    ALTER命令添加和删除PRIMARY KEY

    您也可以以相同的方式添加主键。但要确保主键在不为NULL的列上工作。

    以下代码块是将主键添加到现有表中的示例。这将首先创建一个NOT NULL列,然后将其添加为主键。

    mysql> ALTER TABLE testalter_tbl MODIFY i INT NOT NULL;
    mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (i);
    

    您可以使用ALTER命令删除主键,如下所示 -

    mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY;
    

    要删除不是PRIMARY KEY的索引,必须指定索引名称。

    显示INDEX信息

    您可以使用SHOW INDEX命令列出与表关联的所有索引。垂直格式输出(由\ G指定)通常对此语句非常有用,以避免长线换行 -

    试试下面的例子 -

    mysql> SHOW INDEX FROM table_name\G
    ........

    临时表

    在某些情况下,临时表可能非常有用以保留临时数据。临时表应该知道的最重要的事情是,它们将在当前客户机会话终止时被删除。

    什么是临时表格?

    临时表已添加到MySQL版本3.23中。如果您使用的是早于3.23版本的MySQL,则无法使用临时表,但可以使用堆表

    如前所述,只有会话存在时,临时表才会持续。如果您在PHP脚本中运行代码,则在脚本完成执行时,临时表将自动销毁。如果您通过MySQL客户端程序连接到MySQL数据库服务器,那么临时表将存在,直到您关闭客户端或手动销毁表。

    以下程序是一个示例,显示临时表的用法。使用mysql_query()函数可以在PHP脚本中使用相同的代码

    mysql> CREATE TEMPORARY TABLE SalesSummary (
       -> product_name VARCHAR(50) NOT NULL
       -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00
       -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00
       -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0
    );
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> INSERT INTO SalesSummary
       -> (product_name, total_sales, avg_unit_price, total_units_sold)
       -> VALUES
       -> ('cucumber', 100.25, 90, 2);
    
    mysql> SELECT * FROM SalesSummary;
    +--------------+-------------+----------------+------------------+
    | product_name | total_sales | avg_unit_price | total_units_sold |
    +--------------+-------------+----------------+------------------+
    |   cucumber   |   100.25    |     90.00      |         2        |
    +--------------+-------------+----------------+------------------+
    1 row in set (0.00 sec)
    

    当你发出一个SHOW TABLES命令时,你的临时表就不会在列表中列出来。现在,如果您将注销MySQL会话,然后您将发出SELECT命令,那么您将在数据库中找不到可用数据。即使你的临时表也不存在。

    删除临时表

    默认情况下,当数据库连接终止时,MySQL将删除所有临时表。如果你想在两者之间删除它们,那么你可以通过发出DROP TABLE命令来完成。

    以下程序是放弃临时表的示例 -

    mysql> CREATE TEMPORARY TABLE SalesSummary (
       -> product_name VARCHAR(50) NOT NULL
       -> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00
       -> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00
       -> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0
    );
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> INSERT INTO SalesSummary
       -> (product_name, total_sales, avg_unit_price, total_units_sold)
       -> VALUES
       -> ('cucumber', 100.25, 90, 2);
    
    mysql> SELECT * FROM SalesSummary;
    +--------------+-------------+----------------+------------------+
    | product_name | total_sales | avg_unit_price | total_units_sold |
    +--------------+-------------+----------------+------------------+
    |   cucumber   |   100.25    |     90.00      |         2        |
    +--------------+-------------+----------------+------------------+
    1 row in set (0.00 sec)
    mysql> DROP TABLE SalesSummary;
    mysql>  SELECT * FROM SalesSummary;
    ERROR 1146: Table 'TUTORIALS.SalesSummary' doesn't exist

    克隆表

    当您需要表格的精确副本并且CREATE TABLE ... SELECT不适合您的用途时,可能会出现这种情况,因为副本必须包含相同的索引,默认值等等。

    您可以按照以下步骤处理这种情况 -

    • 使用SHOW CREATE TABLE来获得CREATE TABLE语句,该语句指定源表的结构,索引和全部。

    • 修改语句以将表名更改为克隆表的名称并执行该语句。这样,你将有确切的克隆表。

    • 或者,如果您需要复制表格内容,也可以发出INSERT INTO ... SELECT语句。

    试试以下示例为tutorials_tbl创建一个克隆表

    第1步 - 获取有关表格的完整结构。

    mysql> SHOW CREATE TABLE tutorials_tbl \G;
    *************************** 1. row ***************************
          Table: tutorials_tbl
    Create Table: CREATE TABLE `tutorials_tbl` (
       `tutorial_id` int(11) NOT NULL auto_increment,
       `tutorial_title` varchar(100) NOT NULL default '',
       `tutorial_author` varchar(40) NOT NULL default '',
       `submission_date` date default NULL,
       PRIMARY KEY  (`tutorial_id`),
       UNIQUE KEY `AUTHOR_INDEX` (`tutorial_author`)
    ) TYPE = MyISAM
    1 row in set (0.00 sec)
    
    ERROR:
    No query specified

    第2步 - 重命名该表并创建另一个表。

    mysql> CREATE TABLE clone_tbl (
       -> tutorial_id int(11) NOT NULL auto_increment,
       -> tutorial_title varchar(100) NOT NULL default '',
       -> tutorial_author varchar(40) NOT NULL default '',
       -> submission_date date default NULL,
       -> PRIMARY KEY  (tutorial_id),
       -> UNIQUE KEY AUTHOR_INDEX (tutorial_author)
    -> ) TYPE = MyISAM;
    Query OK, 0 rows affected (1.80 sec)

    第3步 - 执行第2 后,您将在数据库中创建一个克隆表。如果你想从旧表中复制数据,那么你可以通过使用INSERT INTO ... SELECT语句来完成。

    mysql> INSERT INTO clone_tbl (tutorial_id,
       ->                        tutorial_title,
       ->                        tutorial_author,
       ->                        submission_date)
       -> SELECT tutorial_id,tutorial_title,
       ->        tutorial_author,submission_date
       -> FROM tutorials_tbl;
    Query OK, 3 rows affected (0.07 sec)
    Records: 3  Duplicates: 0  Warnings: 0

    最后,你将拥有一个精确的克隆表,就像你想要的那样。

    数据库信息

    获取和使用MySQL元数据

    有三种类型的信息,您希望从MySQL获得。

    • 有关查询结果的信息 - 这包括受任何SELECT,UPDATE或DELETE语句影响的记录数。

    • 有关表格和数据库的信息 - 这包括有关表格和数据库结构的信息。

    • 关于MySQL服务器的信息 - 这包括数据库服务器的状态,版本号等。

    在MySQL提示符下很容易获得所有这些信息,但在使用PERL或PHP API时,我们需要显式调用各种AP​​I以获取所有这些信息。

    获取受查询影响的行数

    现在让我们看看如何获​​得这些信息。

    PERL示例

    在DBI脚本中,受影响的行数由do()execute()命令返回,具体取决于执行查询的方式。

    # Method 1
    # execute $query using do( )
    my $count = $dbh->do ($query);
    # report 0 rows if an error occurred
    printf "%d rows were affected\n", (defined ($count) ? $count : 0);
    
    # Method 2
    # execute query using prepare( ) plus execute( )
    my $sth = $dbh->prepare ($query);
    my $count = $sth->execute ( );
    printf "%d rows were affected\n", (defined ($count) ? $count : 0);
    

    PHP示例

    在PHP中,调用mysql_affected_rows()函数以查明查询更改了多少行。

    $result_id = mysql_query ($query, $conn_id);
    # report 0 rows if the query failed
    $count = ($result_id ? mysql_affected_rows ($conn_id) : 0);
    print ("$count rows were affected\n");
    

    列表表格和数据库

    列出所有数据库和数据库服务器可用的表格非常简单。如果您没有足够的权限,您的结果可能为

    除了以下代码块中显示的方法之外,您可以使用SHOW TABLESSHOW DATABASES查询来获取PHP或PERL中的表或数据库列表。

    PERL示例

    # Get all the tables available in current database.
    my @tables = $dbh->tables ( );
    foreach $table (@tables ){
       print "Table Name $table\n";
    }
    

    PHP示例

    <?php
       $con = mysql_connect("localhost", "userid", "password");
       
       if (!$con) {
          die('Could not connect: ' . mysql_error());
       }
    
       $db_list = mysql_list_dbs($con);
    
       while ($db = mysql_fetch_object($db_list)) {
          echo $db->Database . "<br />";
       }
       mysql_close($con);
    ?>
    

    获取服务器元数据

    MySQL中有一些重要的命令可以在MySQL提示符下执行,也可以使用PHP等任何脚本来获取有关数据库服务器的各种重要信息。

    S. No. 命令和说明
    1

    SELECT VERSION()

    服务器版本字符串

    2

    SELECT DATABASE()

    当前数据库名称(如果没有则为空)

    3

    SELECT USER()

    当前用户名

    4

    显示状态

    服务器状态指示器

    5

    显示变量

    服务器配置变量


    使用序列

    一个序列是一组整数1,2,3,...,它们是按照特定需求的顺序生成的。序列在数据库中经常使用,因为许多应用程序要求表中的每一行都包含一个唯一的值,序列提供了一种简单的方法来生成它们。

    本章介绍如何在MySQL中使用序列。

    使用AUTO_INCREMENT列

    MySQL使用Sequences的最简单方法是将列定义为AUTO_INCREMENT,并将剩余的内容留给MySQL来处理。

    试试下面的例子。这将创建表,之后它将在该表中插入几行,因为它是由MySQL自动递增的,所以不需要给出记录ID。

    mysql> CREATE TABLE insect
       -> (
       -> id INT UNSIGNED NOT NULL AUTO_INCREMENT,
       -> PRIMARY KEY (id),
       -> name VARCHAR(30) NOT NULL, # type of insect
       -> date DATE NOT NULL, # date collected
       -> origin VARCHAR(30) NOT NULL # where collected
    );
    Query OK, 0 rows affected (0.02 sec)
    mysql> INSERT INTO insect (id,name,date,origin) VALUES
       -> (NULL,'housefly','2001-09-10','kitchen'),
       -> (NULL,'millipede','2001-09-10','driveway'),
       -> (NULL,'grasshopper','2001-09-10','front yard');
    Query OK, 3 rows affected (0.02 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    mysql> SELECT * FROM insect ORDER BY id;
    +----+-------------+------------+------------+
    | id |    name     |    date    |   origin   |
    +----+-------------+------------+------------+
    |  1 |  housefly   | 2001-09-10 |   kitchen  |
    |  2 |  millipede  | 2001-09-10 |  driveway  |
    |  3 | grasshopper | 2001-09-10 | front yard |
    +----+-------------+------------+------------+
    3 rows in set (0.00 sec)

    获取AUTO_INCREMENT值

    LAST_INSERT_ID()是SQL的功能,让你可以从了解如何发出SQL语句的任何客户端中使用它。否则,PERL和PHP脚本提供专用函数来检索最后一条记录的自动递增值。

    PERL示例

    使用mysql_insertid属性获取查询生成AUTO_INCREMENT值。该属性通过数据库句柄或语句句柄进行访问,具体取决于您发出查询的方式。

    以下示例通过数据库句柄引用它。

    $dbh->do ("INSERT INTO insect (name,date,origin)
    VALUES('moth','2001-09-14','windowsill')");
    my $seq = $dbh->{mysql_insertid};

    PHP示例

    发出生成AUTO_INCREMENT值的查询后,通过调用mysql_insert_id()命令来检索该值

    mysql_query ("INSERT INTO insect (name,date,origin)
    VALUES('moth','2001-09-14','windowsill')", $conn_id);
    $seq = mysql_insert_id ($conn_id);

    重新编号现有序列

    可能会出现这样的情况,即删除了表中的许多记录,并且想要重新排序所有记录。这可以通过使用简单的技巧来完成,但是如果您的表与另一个表连接,则应该非常小心。

    如果您确定AUTO_INCREMENT列的重新排序是不可避免的,那么执行此操作的方法是从表中删除列,然后再次添加它。

    以下示例显示如何使用此技术对表中id值进行重新编号

    mysql> ALTER TABLE insect DROP id;
    mysql> ALTER TABLE insect
       -> ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
       -> ADD PRIMARY KEY (id);

    以特定值启动序列

    默认情况下,MySQL将从1开始,但在创建表时也可以指定任何其他编号。

    以下程序是一个示例,显示了MySQL将如何从100开始序列。

    mysql> CREATE TABLE insect
       -> (
       -> id INT UNSIGNED NOT NULL AUTO_INCREMENT = 100,
       -> PRIMARY KEY (id),
       -> name VARCHAR(30) NOT NULL, # type of insect
       -> date DATE NOT NULL, # date collected
       -> origin VARCHAR(30) NOT NULL # where collected
    );

    或者,您可以创建该表,然后使用ALTER TABLE命令设置初始序列值

    mysql> ALTER TABLE t AUTO_INCREMENT = 100;

    处理重复

    通常,表或结果集有时包含重复的记录。大部分时间允许,但有时需要停止重复记录。它需要识别重复记录并将其从表中删除。本章将介绍如何防止表中出现重复记录以及如何删除已存在的重复记录。

    防止表中出现重复

    您可以在具有相应字段的表上使用PRIMARY KEYUNIQUE索引来停止重复记录。

    让我们举一个例子 - 下表不包含这样的索引或主键,因此它将允许first_namelast_name的重复记录

    CREATE TABLE person_tbl (
       first_name CHAR(20),
       last_name CHAR(20),
       sex CHAR(10)
    );

    要防止在此表中创建具有相同名字和姓氏值的多个记录,请将PRIMARY KEY添加到其定义中。当你这样做时,还有必要将索引列声明为NOT NULL,因为PRIMARY KEY不允许NULL值 -

    CREATE TABLE person_tbl (
       first_name CHAR(20) NOT NULL,
       last_name CHAR(20) NOT NULL,
       sex CHAR(10),
       PRIMARY KEY (last_name, first_name)
    );

    如果将表中的记录插入到表中复制列中的现有记录或定义索引的列中,则表中存在唯一索引通常会导致发生错误。

    使用INSERT IGNORE命令而不是INSERT命令。如果一条记录没有复制现有记录,那么MySQL照常插入它。如果记录是重复的,那么IGNORE关键字告诉MySQL放弃它而不会产生错误。

    以下示例不会出错,同时它也不会插入重复记录。

    mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
       -> VALUES( 'Jay', 'Thomas');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
       -> VALUES( 'Jay', 'Thomas');
    Query OK, 0 rows affected (0.00 sec)

    使用REPLACE命令而不是INSERT命令。如果记录是新的,那么就像INSERT一样插入它。如果它是重复的,则新记录取代旧记录。

    mysql> REPLACE INTO person_tbl (last_name, first_name)
       -> VALUES( 'Ajay', 'Kumar');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> REPLACE INTO person_tbl (last_name, first_name)
       -> VALUES( 'Ajay', 'Kumar');
    Query OK, 2 rows affected (0.00 sec)

    INSERT IGNORE和REPLACE命令应根据要实现的重复处理行为进行选择。INSERT IGNORE命令保留第一组重复记录和丢弃剩余的记录。REPLACE命令保留最后一组重复项并删除任何较早的重复项。

    强制唯一性的另一种方法是向表中添加一个UNIQUE索引而不是PRIMARY KEY。

    CREATE TABLE person_tbl (
       first_name CHAR(20) NOT NULL,
       last_name CHAR(20) NOT NULL,
       sex CHAR(10)
       UNIQUE (last_name, first_name)
    );

    计数和识别重复

    以下是在表中使用first_name和last_name计数重复记录的查询。

    mysql> SELECT COUNT(*) as repetitions, last_name, first_name
       -> FROM person_tbl
       -> GROUP BY last_name, first_name
       -> HAVING repetitions > 1;

    该查询将返回person_tbl表中所有重复记录的列表。一般来说,要确定重复的一组值,请按照以下步骤进行操作。

    • 确定哪些列包含可能重复的值。

    • 在列选择列表中列出这些列以及COUNT(*)

    • 列出GROUP BY子句中的列

    • 添加HAVING子句,通过要求组计数大于1来消除唯一值。

    从查询结果中消除重复项

    您可以使用DISTINCT命令和SELECT语句来查找表中可用的唯一记录。

    mysql> SELECT DISTINCT last_name, first_name
       -> FROM person_tbl
       -> ORDER BY last_name;

    DISTINCT命令的替代方法是添加一个GROUP BY子句,用于命名您选择的列。这具有删除重复项并仅选择指定列中值的唯一组合的效果。

    mysql> SELECT last_name, first_name
       -> FROM person_tbl
       -> GROUP BY (last_name, first_name);

    使用表替换删除重复项

    如果表中有重复的记录,并且您想要从该表中删除所有重复的记录,请按照以下步骤进行操作。

    mysql> CREATE TABLE tmp SELECT last_name, first_name, sex
       ->                  FROM person_tbl;
       ->                  GROUP BY (last_name, first_name);
    
    mysql> DROP TABLE person_tbl;
    mysql> ALTER TABLE tmp RENAME TO person_tbl;

    从表中删除重复记录的简单方法是向该表中添加INDEX或PRIMARY KEY。即使此表已经可用,您也可以使用此技术删除重复的记录,并且您将来也可以安全使用。

    mysql> ALTER IGNORE TABLE person_tbl
       -> ADD PRIMARY KEY (last_name, first_name);

    SQL注入

    如果您通过网页进行用户输入并将其插入到MySQL数据库中,那么您有可能因为一个称为SQL注入的安全问题而自行开放本章将教你如何帮助防止这种情况发生,并帮助你保护你的脚本和MySQL语句。

    SQL注入通常发生在你向用户询问输入时,如他们的名字,而不是他们给你一个MySQL声明的名字,你会不知不觉地在你的数据库上运行。

    永远不要相信用户提供的数据,只有在验证后才处理这些数据; 作为一项规则,这是通过模式匹配完成的。在以下示例中,用户名限制为字母数字字符加下划线,长度为8到20个字符 - 根据需要修改这些规则。

    if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
       $result = mysql_query("SELECT * FROM users 
                              WHERE username=$matches[0]");
    } else  {
       echo "username not accepted";
    }
    

    为了演示这个问题,请考虑下面的摘录。

    // supposed input
    $name = "Qadir'; DELETE FROM users;";
    mysql_query("SELECT * FROM users WHERE name = '{$name}'");
    

    函数调用应该从users表中检索一条记录,其中名称列与用户指定的名称相匹配。在正常情况下,$ name只能包含字母数字字符和空格。但是,在这里,通过向$ name添加一个全新的查询,对数据库的调用变成了一场灾难。注入的DELETE查询删除用户的所有记录。

    幸运的是,如果您使用MySQL,则mysql_query()函数不允许在单个函数调用中进行查询堆栈或执行多个查询。如果您尝试堆叠查询,则呼叫失败。

    但是,其他PHP数据库扩展(例如SQLitePostgreSQL)则很乐意执行堆栈查询,执行所有在一个字符串中提供的查询,并产生严重的安全问题。

    防止SQL注入

    您可以在诸如PERL和PHP之类的脚本语言中巧妙处理所有转义字符。PHP的MySQL扩展提供了函数mysql_real_escape_string()来转义MySQL特有的输入字符。

    if (get_magic_quotes_gpc()) {
       $name = stripslashes($name);
    }
    
    $name = mysql_real_escape_string($name);
    mysql_query("SELECT * FROM users WHERE name = '{$name}'");
    

    LIKE Quandary

    为了解决LIKE问题,自定义转义机制必须将用户提供的%和_字符转换为文字。使用addcslashes()函数,该函数可让您指定要转义的字符范围。

    $sub = addcslashes(mysql_real_escape_string("%something_"), "%_");
    // $sub == \%something\_
    mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");
    

    数据库导出

    将表数据导出到文本文件的最简单方法是使用SELECT ... INTO OUTFILE语句,该语句将查询结果直接导出到服务器主机上的文件中。

    使用SELECT ... INTO OUTFILE语句导出数据

    该语句的语法结尾处包含常规SELECT命令和INTO OUTFILE文件名默认输出格式与LOAD DATA命令相同。因此,以下语句将tutorials_tbl导出/tmp/tutorials.txt,作为制表符分隔的换行符终止的文件。

    mysql> SELECT * FROM tutorials_tbl 
       -> INTO OUTFILE '/tmp/tutorials.txt';
    

    您可以使用各种选项更改输出格式,以指示如何引用和分隔列和记录。要以带有CRLF终止行的CSV格式导出tutorial_tbl表,请使用以下代码。

    mysql> SELECT * FROM passwd INTO OUTFILE '/tmp/tutorials.txt'
       -> FIELDS TERMINATED BY ',' ENCLOSED BY '"'
       -> LINES TERMINATED BY '\r\n';
    

    SELECT ... INTO OUTFILE具有以下属性-

    • 输出文件是由MySQL服务器直接创建的,所以文件名应该表明文件在服务器主机上的写入位置。没有LOCAL版本的声明类似于LOAD DATALOCAL版本

    • 您必须具有MySQL FILE权限才能执行SELECT ... INTO语句。

    • 输出文件不能已经存在。这可以防止MySQL破坏可能很重要的文件。

    • 您应该在服务器主机上有一个登录帐户或某种方式从该主机检索文件。否则,SELECT ... INTO OUTFILE命令很可能对您没有任何价值。

    • 在UNIX下,该文件被创建为世界可读,并由MySQL服务器拥有。这意味着虽然您可以阅读文件,但您可能无法删除它。

    将表格导出为原始数据

    的mysqldump程序用于复制或备份表和数据库。它可以将表输出写入原始数据文件或作为一组INSERT语句来重新创建表中的记录。

    要将表转储为数据文件,您必须指定一个--tab选项来指示目录,您希望MySQL服务器在其中写入文件。

    例如,要将tutorials_tbl表从TUTORIALS数据库转储/ tmp目录中的文件,请使用如下所示的命令。

    $ mysqldump -u root -p --no-create-info \
       --tab=/tmp tutorials tutorials_tbl
    password ******
    

    以SQL格式导出表格内容或定义

    要将SQL格式的表导出到文件,请使用下面显示的命令。

    $ mysqldump -u root -p TUTORIALS tutorials_tbl > dump.txt
    password ******
    

    这将创建一个文件,内容如下所示。


    -- MySQL dump 8.23
    --
    -- Host: localhost    Database: TUTORIALS
    ---------------------------------------------------------
    -- Server version       3.23.58
    
    --
    -- Table structure for table `tutorials_tbl`
    --
    
    CREATE TABLE tutorials_tbl (
       tutorial_id int(11) NOT NULL auto_increment,
       tutorial_title varchar(100) NOT NULL default '',
       tutorial_author varchar(40) NOT NULL default '',
       submission_date date default NULL,
       PRIMARY KEY  (tutorial_id),
       UNIQUE KEY AUTHOR_INDEX (tutorial_author)
    ) TYPE = MyISAM;
    
    --
    -- Dumping data for table `tutorials_tbl`
    --
    
    INSERT INTO tutorials_tbl 
       VALUES (1,'Learn PHP','John Poul','2007-05-24');
    INSERT INTO tutorials_tbl 
       VALUES (2,'Learn MySQL','Abdul S','2007-05-24');
    INSERT INTO tutorials_tbl 
       VALUES (3,'JAVA Tutorial','Sanjay','2007-05-06');
    

    要转储多个表,请将它们全部命名为数据库名称参数。要转储整个数据库,请不要在数据库后命名任何表,如以下代码块所示。

    $ mysqldump -u root -p TUTORIALS > database_dump.txt
    password ******
    

    要备份主机上可用的所有数据库,请使用以下代码。

    $ mysqldump -u root -p --all-databases > database_dump.txt
    password ******
    

    --all-databases选项在MySQL 3.23.12版本中可用。此方法可用于实施数据库备份策略。

    将表或数据库复制到另一个主机

    如果要将表或数据库从一台MySQL服务器复制到另一台,则使用带数据库名称和表名称mysqldump

    在源主机上运行以下命令。这会将完整的数据库转储到dump.txt文件中。

    $ mysqldump -u root -p database_name table_name > dump.txt
    password *****
    

    如上所述,您可以复制完整的数据库而不使用特定的表名。

    现在,另一台主机上的ftp dump.txt文件并使用以下命令。在运行此命令之前,请确保您已在目标服务器上创建了database_name。

    $ mysql -u root -p database_name < dump.txt
    password *****
    

    在不使用中间文件的情况下完成此操作的另一种方法是直接通过网络将mysqldump的输出发送到远程MySQL服务器。如果您可以从源数据库所在的主机连接到这两个服务器,请使用以下命令(确保您在两台服务器上均可访问)。

    $ mysqldump -u root -p database_name \
       | mysql -h other-host.com database_name
    

    在mysqldump中,一半命令连接到本地服务器并将转储输出写入管道。剩下的一半命令连接到other-host.com上的远程MySQL服务器。它读取输入管道并将每个语句发送到other-host.com服务器。

    数据库导入

    MySQL中有两种简单的方法可以将数据从以前备份的文件加载到MySQL数据库中。

    用LOAD DATA导入数据

    MySQL提供了一个充当批量数据加载器的LOAD DATA语句。下面是一个示例语句,它从当前目录中读取文件dump.txt,并将其加载到当前数据库的mytbl中。

    mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl;
    • 如果LOCAL关键字不存在,MySQL将使用查看绝对路径名的方式在服务器主机上查找数据文件,该路径名从文件系统的根开始完全指定文件的位置。MySQL从给定的位置读取文件。

    • 默认情况下,LOAD DATA假定数据文件包含由换行符(换行符)终止的行,并且行中的数据值由制表符分隔。

    • 要明确指定文件格式,请使用FIELDS子句来描述行中字段的特征,并使用LINES子句来指定行结束顺序。以下LOAD DATA语句指定数据文件包含由冒号分隔的值和由回车符和换行符结尾的行。

    mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl
       -> FIELDS TERMINATED BY ':'
       -> LINES TERMINATED BY '\r\n';
    • LOAD DATA命令假定数据文件中的列与表中的列具有相同的顺序。如果不是这样,您可以指定一个列表来指示应将数据文件列加载到哪个表列中。假设你的表有列a,b和c,但是数据文件中的连续列对应于列b,c和a。

    您可以按照以下代码块中所示加载文件。

    mysql> LOAD DATA LOCAL INFILE 'dump.txt' 
       -> INTO TABLE mytbl (b, c, a);

    用mysqlimport导入数据

    MySQL还包含一个名为mysqlimport的实用程序,它充当LOAD DATA的包装器,以便您可以直接从命令行加载输入文件。

    要将dump.txt中的数据加载mytbl中,请在UNIX提示符处使用以下命令。

    $ mysqlimport -u root -p --local database_name dump.txt
    password *****

    如果使用mysqlimport,命令行选项提供格式说明符。与前面两个LOAD DATA语句对应mysqlimport命令如下面的代码块所示。

    $ mysqlimport -u root -p --local --fields-terminated-by = ":" \
       --lines-terminated-by = "\r\n"  database_name dump.txt
    password *****

    您指定选项的顺序与mysqlimport无关,只是它们应该都在数据库名称之前。

    mysqlimport的语句使用--columns选项来指定列的顺序-

    $ mysqlimport -u root -p --local --columns=b,c,a \
        database_name dump.txt
    password *****

    处理引号和特殊字符

    FIELDS子句可以指定除TERMINATED BY之外的其他格式选项默认情况下,LOAD DATA假定值不加引号,并将反斜杠(\)解释为特殊字符的转义字符。要明确指示值引号字符,请使用ENCLOSED BY命令。在输入处理过程中,MySQL将从数据值的末尾剥离该字符。要更改默认转义字符,请使用ESCAPED BY

    当您指定ENCLOSED BY表示应该从数据值中删除引号字符时,可以通过将引号字符加倍或在转义字符前面加上引号字符,从而将引号字符逐字地包括在数据值中。

    例如,如果引号和转义字符是“和\”,则输入值“a”“b \”c“将被解释为”b“c

    对于mysqlimport,用于指定引号和转义值的相应命令行选项是--fields-enclosed-by-fields-escaped-by






猜你喜欢

转载自blog.csdn.net/ancony_/article/details/80035154