第 2 章 MySQL简介

在你能执行任意数据库操作前,需要选择一个数据库。为此,可使用USE关键字。

数据库、表、列、用户、权限等的信息被存储在数据库和表中(MySQL使用MySQL来存储这些信息)。不过,内部的表一般不直接访问。可用MySQL的SHOW命令来显示这些信息(MySQL从内部表中提取这些信息)

为了获得一个数据库内的表的列表,使用SHOW TABLES;

SHOW COLUMNS 要求给出一个表名(这个例子中的 FROM_customers),它对每个字段返回一行,行中包含字段名、数据类型、是否允许NULL、键信息、默认值以及其他信息(如字段cust_id的auto_increment)。

DESCRIBE customers;是SHOW COLUMNS FROM customers;的一种快捷方式。

第 4 章 检索数据

最经常使用的SQL语句就是SELECT语句了。它的用途是从一个或多个表中检索信息。

SELECT last_name FROM actor

SQL语句不区分大小写,因此SELECT与select是相同的。

多条SQL语句必须以分号(;)分隔。

要想从一个表中检索多个列,使用相同的SELECT语句。唯一的不同是必须在SELECT关键字后给出多个列名,列名之间必须以逗号分隔。SELECT last_name , first_name FROM actor

除了指定所需的列外(如上所述,一个或多个列),SELECT语句还可以检索所有的列而不必逐个列出它们。这可以通过在实际列名的位置使用星号(*)通配符来达到。

使用DISTINCT关键字,顾名思义,此关键字指示MySQL只返回不同的值。

SELECT DISTINCT last_name , first_name FROM actor

为了返回第一行或前几行,可使用LIMIT子句。LIMIT 5指示MySQL返回不多于5行。LIMIT 5, 5指示MySQL返回从行5开始的5行。SELECT DISTINCT last_name FROM actor LIMIT 5,5;

检索出来的第一行为行0而不是行1。因此,LIMIT 1, 1将检索出第二行而不是第一行。

第5章 排序检索数据

为了明确地排序用SELECT语句检索出的数据,可使用ORDER BY子句。ORDER BY子句取一个或多个列的名字,据此对输出进行排序。

SELECT DISTINCT last_name , first_name FROM actor ORDER BY first_name

经常需要按不止一个列进行数据排序。例如,如果要显示雇员清单,可能希望按姓和名排序(首先按姓排序,然后在每个姓中再按名排序)为了按多个列排序,只要指定列名,列名之间用逗号分开即可(就像选择多个列时所做的那样)

数据排序不限于升序排序(从A到Z)。这只是默认的排序顺序,还可以使用ORDER BY子句以降序(从Z到A)顺序排序。为了进行降序排序,必须指定DESC关键字。DESC关键字只应用到直接位于其前面的列名。SELECT DISTINCT last_name , first_name FROM actor ORDER BY first_name DESC

与DESC相反的关键字是ASC(ASCENDING)

在给出ORDER BY子句时,应该保证它位于FROM子句之后。如果使用LIMIT,它必须位于ORDER BY 之后。使用子句的次序不对将产生错误消息。

第6章 过滤数据

在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。WHERE子句在表名(FROM子句)之后给出。在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后。

SELECT customer_id,amount FROM payment WHERE amount = 11.99 ORDER BY customer_id DESC

在使用BETWEEN时,必须指定两个值——所需范围的低端值和高端值。这两个值必须用AND关键字 分隔。BETWEEN匹配范围中所有的值,包括指定的开始值和结束值。

SELECT customer_id,amount FROM payment WHERE amount BETWEEN 5 AND 10 ORDER BY customer_id DESC

SELECT语句有一个特殊的WHERE子句,可用来检查具有NULL值的列。这个WHERE子句就是IS NULL子句。

SELECT customer_id,amount FROM payment WHERE amount IS NULL

第 7 章 数据过滤

为了进行更强的过滤控制,MySQL允许给出多个WHERE子句。这些子句可以两种方式使用:以AND子句的方式或OR子句的方式使用。为了通过不止一个列进行过滤,可使用AND操作符给WHERE子句附加条件。

SELECT customer_id,amount FROM payment WHERE amount =0.99 AND customer_id = 1

OR操作符与AND操作符不同,它指示MySQL检索匹配任一条件的行。

SELECT customer_id,amount FROM payment WHERE amount =0.99 OR customer_id = 1

SQL(像多数语言一样)在处理OR操作符前,优先处理AND操作符。此问题的解决方法是使用圆括号明确地分组相应的操作符。

IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。

SELECT customer_id,amount FROM payment WHERE customer_id IN (1,2,3)

WHERE子句中的NOT操作符有且只有一个功能,那就是否定它之后所跟的任何条件。

SELECT customer_id,amount FROM payment WHERE customer_id NOT IN (1,2,3)

第 8 章 用通配符进行过滤

最常使用的通配符是百分号(%)。在搜索串中,%表示任何字符出现任意次数。

SELECT customer_id,amount FROM payment WHERE customer_id LIKE '2%’

搜索模式'%anvil%'表示匹配任何位置包含文本anvil的值,而不论它之前或之后出现什么字符。

SELECT customer_id,amount FROM payment WHERE customer_id LIKE '%2%’

另一个有用的通配符是下划线(_)。下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符。与%能匹配0个字符不一样,_总是匹配一个字符,不能多也不能少。

第9章 用正则表达式进行搜索

正则表达式是用来匹配文本的特殊的串(字符集合)。如果你想从一个文本文件中提取电话号码,可 以使用正则表达式。如果你需要查找名字中间有数字的所有文件,可以使用一个正则表达式。

LIKE匹配整个列。如果被匹配的文本在列值中出现,LIKE将不会找到它,相应的行也不被返回(除非使用通配符)。而REGEXP在列值内进行匹配,如果被匹配的文本在列值中出现,REGEXP将会找到它,相应的行将被返回。这是一个非常重要的差别。

为搜索两个串之一(或者为这个串,或者为另一个串),使用|:

SELECT customer_id,amount FROM payment WHERE customer_id REGEXP '2|3’

匹配任何单一字符。但是,如果你只想匹配特定的字符,怎么办?可通过指定一组用[和]括起来的字符来完成

Untitled

这里,使用了正则表达式[123] Ton。[123]定义一组字符,它的意思是匹配1或2或3,因此,1 ton和2 ton都匹配且返回(没有3 ton)。

SELECT customer_id,amount FROM payment WHERE customer_id REGEXP '[12]3’

字符集合也可以被否定,即,它们将匹配除指定字符外的任何东西。为否定一个字符集,在集合的开始处放置一个^即可。尽管[123]匹配字符1、2或3,但[^123]却匹配除这些字符外的任何东西。

为了匹配特殊字符,必须用\为前导。\-表示查找-,\.表示查找.。

第 10 章 创建计算字段

计算字段并不实际存在于数据库表中。计算字段是运行时在SELECT语句内创建的。

把两个列拼接起来。在MySQL的SELECT语句中,可使用Concat()函数来拼接两个列。

SQL支持列别名。别名(alias)是一个字段或值的替换名。别名用AS关键字赋予。

第 11 章 使用数据处理函数

使用Upper()函数 SELECT UPPER(last_name) FROM actor

无论你什么时候指定一个日期,不管是插入或更新表值还是用WHERE子句进行过滤,日期必须为格式yyyy-mm-dd。

SELECT customer_id,amount,payment_date FROM payment WHERE payment_date LIKE '2005-06-16%’

SELECT customer_id,amount,payment_date FROM payment WHERE Date(payment_date)='2005-06-16’

第 12 章 汇总数据

我们经常需要汇总数据而不用把它们实际检索出来,为此MySQL提供了专门的函数。使用这些函数,MySQL查询可用于检索数据,以便分析和报表生成。

确定表中行数(或者满足某个条件或包含某个特定值的行数)。 获得表中行组的和。 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值

聚集函数(aggregate function) 运行在行组上,计算和返回单个值的函数

**AVG()**通过对表中行数计数并计算特定列值之和,求得该列的平均值。AVG()可用来返回所有列的平均值,也可以用来返回特定列或行的平均值。

SELECT AVG(amount) AS avg_amount FROM payment WHERE DATE(payment_date)='2005-06-16’

**COUNT()**函数进行计数。可利用COUNT()确定表中行的数目或符合特定条件的行的数目

SELECT COUNT(*) AS count_amount FROM payment WHERE DATE(payment_date)='2005-06-16’

**MAX()**返回指定列中的最大值。MAX()要求指定列名

SELECT MAX(amount) AS max_amount FROM payment WHERE DATE(payment_date)='2005-06-16’

**MIN()**的功能正好与MAX()功能相反,它返回指定列的最小值。与MAX()一样,MIN()要求指定列名

**SUM()**用来返回指定列值的和(总计)。

第 13 章 分组数据

分组数据,以便能汇总表内容的子集。涉及两个新SELECT语句子句,分别是GROUP BY子句和HAVING子句

SELECT SUM(amount),DATE(payment_date) AS sum_amount FROM payment GROUP BY DATE(payment_date)

GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前

唯一的差别是WHERE过滤行,而HAVING过滤分组 HAVING支持所有WHERE操作符

WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。

Untitled

一般在使用GROUP BY子句时,应该也给出ORDER BY子句。

第 14 章 使用子查询

SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。

子查询最常见的使用是在WHERE子句的IN操作符中,以及用来填充计算列。

第 15 章 联结表

关键是,相同数据出现多次决不是一件好事,此因素是关系数据库设计的基础。关系表的设计就是要保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系设计中的关系(relational))互相关联。在这个例子中,可建立两个表,一个存储供应商信息,另一个存储产品信息。vendors表包含所有供应商信息,每个供应商占一行,每个供应商具有唯一的标识。此标识称为主键(primary key)(在第1章中首次提到),可以是供应商ID或任何其他唯一值。products表只存储产品信息,它除了存储供应商ID(vendors表的主键)外不存储其他供应商信息。vendors表的主键又叫作products的外键,它将vendors表与products表关联,利用供应商ID能从vendors表中找出相应供应商的详细信息。

外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。

这样做的好处如下:  供应商信息不重复,从而不浪费时间和空间;  如果供应商信息变动,可以只更新vendors表中的单个记录,相 关表中的数据不用改动;  由于数据无重复,显然数据是一致的,这使得处理数据更简单。 总之,关系数据可以有效地存储和方便地处理。因此,关系数据库的可伸缩性远比非关系数据库要好。

SELECT amount,payment_date,rental_date FROM payment,rental WHERE payment.customer_id = rental.customer_id

目前为止所用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内部联结。

此语句中的SELECT与前面的SELECT语句相同,但FROM子句不同。这里,两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出。传递给ON的实际条件与传递给WHERE的相同。

SELECT amount,payment_date,rental_date FROM payment INNER JOIN rental ON payment.customer_id = rental.customer_id

规范首选INNER JOIN语法

第 16 章 创建高级联结

表别名只用于WHERE子句。但是,表别名不仅能用于WHERE子句,它还可以用于SELECT的列表、ORDER BY子句以及语句的其他部分。

SELECT amount,payment_date,rental_date FROM payment AS P INNER JOIN rental AS R ON P.customer_id = R.customer_id

迄今为止,我们使用的只是称为内部联结或等值联结(equijoin)的简单联结。现在来看3种其他联结,它们分别是自联结自然联结外部联结

自然联结是这样一种联结,其中你只能选择那些唯一的列。这一般是通过对表使用通配符(SELECT *),对所有其他表的列使用明确的子集来完成的。自然联结排除多次出现,使每个列只返回一次。

联结包含了那些在相关表中没有关联行的行。这种类型的联结称为外部联结。

在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)

SELECT amount,payment_date,rental_date FROM payment AS P LEFT OUTER JOIN rental AS R ON P.customer_id = R.customer_id

第 17 章 组合查询

多数SQL查询都只包含从一个或多个表中返回数据的单条SELECT语句。MySQL也允许执行多个查询(多条SELECT语句),并将结果作为单个查询结果集返回。这些组合查询通常称为并(union)或复合查询(compound query)。

SELECT amount,customer_id FROM payment WHERE amount > 2 UNION SELECT payment_id,customer_id FROM payment WHERE customer_id > 10

UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个UNION关键字)。

UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)

列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。

在使用UNION时,重复的行被自动取消。这是UNION的默认行为,但是如果需要,可以改变它。事实上,如果想返回所有匹配行,可使用UNION ALL而不是UNION。

在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。

利用UNION,可把多条查询的结果作为一条组合查询返回,不管它们的结果中包含还是不包含重复。

第 18 章 全文本搜索

两个最常使用的引擎为MyISAM和InnoDB,前者支持全文本搜索,而后者不支持。

第 19 章 插入数据

INSERT是用来插入(或添加)行到数据库表的。插入可以用几种方式使用:  插入完整的行;  插入行的一部分;  插入多行;  插入某些查询的结果。

存储到每个表列中的数据在VALUES子句中给出,对每个列必须提供一个值。如果某个列没有值,应该使用NULL值(假定表允许对该列指定空值)

INSERT INTO actor VALUES(201,'SUN','BIUBIU',NULL)

第一列cust_id也为NULL。这是因为每次插入一个新行时,该列由MySQL自动增量

此例子完成与前一个INSERT语句完全相同的工作,但在表名后的括号里明确地给出了列名。在插入行时,MySQL将用VALUES列表中的相应值填入列表中的对应项。

因为提供了列名,VALUES必须以其指定的次序匹配指定的列名,不一定按各个列出现在实际表中的次序。其优点是,即使表的结构改变,此INSERT语句仍然能正确工作。

INSERT INTO actor (actor_id,first_name,last_name,last_update) VALUES(null,'SUN','BIUBIU',NULL)

如果数据检索是最重要的(通常是这样),则你可以通过在INSERT和INTO之间添加关键字LOW_PRIORITY,指示MySQL降低INSERT语句的优先级

可以使用多条INSERT语句,甚至一次提交它们,其中单条INSERT语句有多组值,每组值用一对圆括号括起来,用逗号分隔。

INSERT INTO actor (actor_id,first_name,last_name,last_update) VALUES(null,'SUN','BIUBIU3',NULL),(null,'SUN','BIUBIU4',NULL)

第 20 章 更新和删除数据

为了更新(修改)表中的数据,可使用UPDATE语句。可采用两种方式使用UPDATE:

 更新表中特定行;  更新表中所有行。

在使用UPDATE时一定要注意细心。因为稍不注意,就会更新表中所有行

UPDATE语句总是以要更新的表的名字开始。SET命令用来将新值赋给被更新的列。UPDATE语句以WHERE子句结束,它告诉MySQL更新哪一行。没有WHERE子句,MySQL将会用这个电子邮件地址更新表中所有行,这不是我们所希望的。

UPDATE actor SET first_name = 'swh' WHERE actor_id=202

在更新多个列时,只需要使用单个SET命令,每个“列=值”对之间用逗号分隔(最后一列之后不用逗号)

UPDATE actor SET first_name = 'swh',last_name = 'BiuB' WHERE actor_id=202

为了删除某个列的值,可设置它为NULL(假如表定义允许NULL值)。

为了从一个表中删除(去掉)数据,使用DELETE语句。可以两种方式使用DELETE:

 从表中删除特定的行;  从表中删除所有行。

在使用DELETE时一定要注意细心。因为稍不注意,就会错误地删除表中所有行

DELETE FROM要求指定从中删除数据的表名。WHERE子句过滤要删除的行。在这个例子中,只删除客户10006。如果省略WHERE子句,它将删除表中每个客户。 DELETE不需要列名或通配符。DELETE删除整行而不是删除列。为了删除指定的列,请使用UPDATE语句。

DELETE FROM actor WHERE actor_id = 204

DELETE语句从表中删除行,甚至是删除表中所有行。但是,DELETE不删除表本身。

如果想从表中删除所有行,不要使用DELETE。可使用TRUNCATE TABLE语句,它完成相同的工作,但速度更快(TRUNCATE实际是删除原来的表并重新创建一个表,而不是逐行删除表中的数据)。

第 21 章 创建和操纵表

为了用程序创建表,可使用SQL的CREATE TABLE语句。

为利用CREATE TABLE创建表,必须给出下列信息:  新表的名字,在关键字CREATE TABLE之后给出;  表列的名字和定义,用逗号分隔。

Untitled

CREATE TABLE Sun

(

id int NOT NULL AUTO_INCREMENT,

name char(50) NOT NULL,

university char(50),

PRIMARY KEY (id)

)ENGINE = InnoDB;

表名紧跟在CREATE TABLE关键字后面。实际的表定义(所有列)括在圆括号之中。各列之间用逗号分隔。这个表由9列组成。每列的定义以列名(它在表中必须是唯一的)开始,后跟列的数据类型(关于数据类型的解释,请参阅第1章。此外,附录D列出了MySQL支持的数据类型)。表的主键可以在创建表时用PRIMARY KEY关键字指定。这里,列cust_id指定作为主键列。整条语句由右圆括号后的分号结束。

如果你仅想在一个表不存在时创建它,应该在表名后给出IF NOT EXISTS。

如果在插入行时没有给出值,MySQL允许指定此时使用的默认值。默认值用CREATE TABLE语句的列定义中的DEFAULT关键字指定。

以下是几个需要知道的引擎:  InnoDB是一个可靠的事务处理引擎(参见第26章),它不支持全文本搜索;  MEMORY在功能等同于MyISAM,但由于数据存储在内存(不是磁盘)中,速度很快(特别适合于临时表);

 MyISAM是一个性能极高的引擎,它支持全文本搜索(参见第18章),但不支持事务处理。

为更新表定义,可使用ALTER TABLE语句。但是,理想状态下,当表中存储数据以后,该表就不应该再被更新。

为了使用ALTER TABLE更改表结构,必须给出下面的信息:  在ALTER TABLE之后给出要更改的表名(该表必须存在,否则将出错);

 所做更改的列表。

ALTER TABLE Sun2 ADD age INT

ALTER TABLE Sun2 DROP COLUMN age

ALTER TABLE的一种常见用途是定义外键。

Untitled

删除表(删除整个表而不是其内容)非常简单,使用DROP TABLE语句即可

使用RENAME TABLE语句可以重命名一个表:

RENAME TABLE Sun2 TO Sun3

删除表(删除整个表而不是其内容)非常简单,使用DROP TABLE语句即可:

DROP TABLE Sun3

第 22 章 使用视图

视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。它不包含表中应该有的任何列或数据,它包含的是一个SQL查询

下面是关于视图创建和使用的一些最常见的规则和限制。  与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)。  对于可以创建的视图数目没有限制。  为了创建视图,必须具有足够的访问权限。这些限制通常由数据库管理人员授予。  视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造一个视图。  ORDER BY可以用在视图中,但如果从该视图检索数据SELECT中也含有ORDER BY,那么该视图中的ORDER BY将被覆盖。  视图不能索引,也不能有关联的触发器或默认值。  视图可以和表一起使用。例如,编写一条联结表和视图的SELECT语句。

在理解什么是视图(以及管理它们的规则及约束)后,我们来看一下视图的创建。  视图用CREATE VIEW语句来创建。  使用SHOW CREATE VIEW viewname;来查看创建视图的语句。  用DROP删除视图,其语法为DROP VIEW viewname;。

 更新视图时,可以先用DROP再用CREATE,也可以直接用CREATE ORREPLACE VIEW。如果要更新的视图不存在,则第2条更新语句会创建一个视图;如果要更新的视图存在,则第2条更新语句会替换原有视图。

视图极大地简化了复杂SQL语句的使用。利用视图,可一次性编写基础的SQL,然后根据需要多次使用。视图的另一常见用途是重新格式化检索出的数据。

通常,视图是可更新的(即,可以对它们使用INSERT、UPDATE和DELETE)。更新一个视图将更新其基表(可以回忆一下,视图本身没有数据)。如果你对视图增加或删除行,实际上是对其基表增加或删除行。

如果视图定义中有以下操作,则不能进行视图的更新:

 分组(使用GROUP BY和HAVING);  联结;  子查询;  并;  聚集函数(Min()、Count()、Sum()等);  DISTINCT;  导出(计算)列。

小结:视图为虚拟的表。它们包含的不是数据而是根据需要检索数据的查询。视图提供了一种MySQL的SELECT语句层次的封装,可用来简化数据处理以及重新格式化基础数据或保护基础数据。

第 23 章 使用存储过程

存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件,虽然它们的作用不仅限于批处理。

MySQL执行存储过程的语句为CALL。CALL接受存储过程的名字以及需要传递给它的任意参数。

CREATE PROCEDURE avg_amount() BEGIN SELECT Avg(amount) AS avg_payment FROM payment; END;

第 24 章 使用游标

有时,需要在检索出来的行中前进或后退一行或多行。这就是使用游标的原因。游标(cursor)是一个存储在MySQL服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。

游标用OPEN CURSOR语句来打开:

在一个游标被打开后,可以使用FETCH语句分别访问它的每一行。FETCH指定检索什么数据(所需的列),检索出来的数据存储在什么地方。它还向前移动游标中的内部行指针,使下一条FETCH语句检索下一行(不重复读取同一行)。

第 25 章 使用触发器

触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):

 DELETE;  INSERT;  UPDATE。

在创建触发器时,需要给出4条信息:  唯一的触发器名;  触发器关联的表;  触发器应该响应的活动(DELETE、INSERT或UPDATE);  触发器何时执行(处理之前或之后)。

触发器用CREATE TRIGGER语句创建。

*第 26 章 管理事务处理

事务处理(transaction processing)可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行。

利用事务处理,可以保证一组操作不会中途停止,它们或者作为整体执行,或者完全不执行(除非明确指示)。如果没有错误发生,整组语句提交给(写到)数据库表。如果发生错误,则进行回退(撤销)以恢复数据库到某个已知且安全的状态。

 事务(transaction)指一组SQL语句;  回退(rollback)指撤销指定SQL语句的过程;  提交(commit)指将未存储的SQL语句结果写入数据库表;  保留点(savepoint)指事务处理中设置的临时占位符(placeholder),你可以对它发布回退(与回退整个事务处理不同)。

INSERT INTO sun VALUES(NULL,'SUN','Nankai');

SELECT* FROM sun; START TRANSACTION; DELETE FROM sun; SELECT * FROM sun; ROLLBACK; SELECT * FROM sun;

你不能回退CREATE或DROP操作。

但是,在事务处理块中,提交不会隐含地进行。为进行明确的提交,使用COMMIT语句。

为了支持回退部分事务处理,必须能在事务处理块中合适的位置放置占位符。这样,如果需要回退,可以回退到某个占位符。

这些占位符称为保留点。为了创建占位符,可如下使用SAVEPOINT语句:

SELECT* FROM sun; START TRANSACTION; SAVEPOINT save1; DELETE FROM sun; SELECT * FROM sun; ROLLBACK TO save1; SELECT * FROM sun; COMMIT;

为了创建一个新用户账号,使用CREATE USER语句,用IDENTIFIED BY 'p@$$wOrd'给出了口令。

CREATE USER BIUBIU IDENTIFIED BY '111111'; USE mysql; SELECT USER FROM USER;