MySQL连接方式有哪些

47次阅读
没有评论

共计 11111 个字符,预计需要花费 28 分钟才能阅读完成。

这篇文章主要介绍“MySQL 连接方式有哪些”,在日常操作中,相信很多人在 MySQL 连接方式有哪些问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL 连接方式有哪些”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

一、连接

    使用如下两表来进行测试:
mysql desc users1;
+——-+———————+——+—–+———+——-+
| Field | Type                | Null | Key | Default | Extra |
+——-+———————+——+—–+———+——-+
| uid   | tinyint(3) unsigned | YES  |     | NULL    |       |
| uname | varchar(255)        | YES  |     | NULL    |       |
| gid   | tinyint(3) unsigned | YES  |     | NULL    |       |
+——-+———————+——+—–+———+——-+
3 rows in set (0.06 sec)

mysql desc groups1;
+——-+———————+——+—–+———+——-+
| Field | Type                | Null | Key | Default | Extra |
+——-+———————+——+—–+———+——-+
| gid   | tinyint(3) unsigned | YES  |     | NULL    |       |
| gname | varchar(255)        | YES  |     | NULL    |       |
+——-+———————+——+—–+———+——-+
2 rows in set (0.06 sec)

[@more@]mysql select * from users1;
+——+———-+——+
| uid  | uname    | gid  |
+——+———-+——+
|    0 | root     |    0 |
|  201 | yuegao   |  101 |
|  202 | fengsong |  102 |
|  201 | yuegao   |  200 |
+——+———-+——+
4 rows in set (0.00 sec)

mysql select * from groups1;
+——+——-+
| gid  | gname |
+——+——-+
|    0 | root  |
|  101 | dba   |
|  200 | guest |
+——+——-+
3 rows in set (0.00 sec)

 1. 交叉连接

mysql select * from users1 cross join groups1;
+——+———-+——+——+——-+
| uid  | uname    | gid  | gid  | gname |
+——+———-+——+——+——-+
|    0 | root     |    0 |    0 | root  |
|    0 | root     |    0 |  101 | dba   |
|    0 | root     |    0 |  200 | guest |
|  201 | yuegao   |  101 |    0 | root  |
|  201 | yuegao   |  101 |  101 | dba   |
|  201 | yuegao   |  101 |  200 | guest |
|  202 | fengsong |  102 |    0 | root  |
|  202 | fengsong |  102 |  101 | dba   |
|  202 | fengsong |  102 |  200 | guest |
|  201 | yuegao   |  200 |    0 | root  |
|  201 | yuegao   |  200 |  101 | dba   |
|  201 | yuegao   |  200 |  200 | guest |
+——+———-+——+——+——-+
12 rows in set (0.00 sec)

    或

mysql select * from users1, groups1;
+——+———-+——+——+——-+
| uid  | uname    | gid  | gid  | gname |
+——+———-+——+——+——-+
|    0 | root     |    0 |    0 | root  |
|    0 | root     |    0 |  101 | dba   |
|    0 | root     |    0 |  200 | guest |
|  201 | yuegao   |  101 |    0 | root  |
|  201 | yuegao   |  101 |  101 | dba   |
|  201 | yuegao   |  101 |  200 | guest |
|  202 | fengsong |  102 |    0 | root  |
|  202 | fengsong |  102 |  101 | dba   |
|  202 | fengsong |  102 |  200 | guest |
|  201 | yuegao   |  200 |    0 | root  |
|  201 | yuegao   |  200 |  101 | dba   |
|  201 | yuegao   |  200 |  200 | guest |
+——+———-+——+——+——-+
12 rows in set (0.00 sec)

 2. 内连接

mysql select * from users1 inner join groups1 on users1.gid = groups1.gid;
+——+——–+——+——+——-+
| uid  | uname  | gid  | gid  | gname |
+——+——–+——+——+——-+
|    0 | root   |    0 |    0 | root  |
|  201 | yuegao |  101 |  101 | dba   |
|  201 | yuegao |  200 |  200 | guest |
+——+——–+——+——+——-+
3 rows in set (0.00 sec)

    如果连接列名称相同,可以使用如下形式:

mysql select * from users1 inner join groups1 using(gid);
+——+——+——–+——-+
| gid  | uid  | uname  | gname |
+——+——+——–+——-+
|    0 |    0 | root   | root  |
|  101 |  201 | yuegao | dba   |
|  200 |  201 | yuegao | guest |
+——+——+——–+——-+
3 rows in set (0.00 sec)

    这样两个表的连接列只会显示一个。而最常用的形式:

mysql select * from users1, groups1 where users1.gid = groups1.gid;
+——+——–+——+——+——-+
| uid  | uname  | gid  | gid  | gname |
+——+——–+——+——+——-+
|    0 | root   |    0 |    0 | root  |
|  201 | yuegao |  101 |  101 | dba   |
|  201 | yuegao |  200 |  200 | guest |
+——+——–+——+——+——-+
3 rows in set (0.00 sec)

 3. 外连接

    左外连接:

mysql select * from users1 left join groups1 on users1.gid = groups1.gid;
+——+———-+——+——+——-+
| uid  | uname    | gid  | gid  | gname |
+——+———-+——+——+——-+
|    0 | root     |    0 |    0 | root  |
|  201 | yuegao   |  101 |  101 | dba   |
|  202 | fengsong |  102 | NULL | NULL  |
|  201 | yuegao   |  200 |  200 | guest |
+——+———-+——+——+——-+
4 rows in set (0.00 sec)

    如果连接列名称相同,可以使用如下形式:

mysql select * from users1 left join groups1 using(gid);
+——+——+———-+——-+
| gid  | uid  | uname    | gname |
+——+——+———-+——-+
|    0 |    0 | root     | root  |
|  101 |  201 | yuegao   | dba   |
|  102 |  202 | fengsong | NULL  |
|  200 |  201 | yuegao   | guest |
+——+——+———-+——-+
4 rows in set (0.00 sec)

    这样只会显示左侧表的连接列。

    右外连接:

mysql select * from users1 right join groups1 on users1.gid = groups1.gid;
+——+——–+——+——+——-+
| uid  | uname  | gid  | gid  | gname |
+——+——–+——+——+——-+
|    0 | root   |    0 |    0 | root  |
|  201 | yuegao |  101 |  101 | dba   |
|  201 | yuegao |  200 |  200 | guest |
+——+——–+——+——+——-+
3 rows in set (0.00 sec)

    如果连接列名称相同,可以使用如下形式:

mysql select * from users1 right join groups1 using(gid);
+——+——-+——+——–+
| gid  | gname | uid  | uname  |
+——+——-+——+——–+
|    0 | root  |    0 | root   |
|  101 | dba   |  201 | yuegao |
|  200 | guest |  201 | yuegao |
+——+——-+——+——–+
3 rows in set (0.00 sec)

    这样只会显示右侧表的连接列。

    外连接与分组结合使用,列出每个成员所属的组和每个组包含的成员:

mysql select u.uname, group_concat(g.gname separator ,) from users1 as u left join groups1 as g u
sing(gid) group by u.uid;
+———-+————————————-+
| uname    | group_concat(g.gname separator ,) |
+———-+————————————-+
| root     | root                                |
| yuegao   | dba,guest                           |
| fengsong | NULL                                |
+———-+————————————-+
3 rows in set (0.00 sec)

mysql select g.gname, group_concat(u.uname separator ,) from users1 as u right join groups1 as g
using(gid) group by g.gid;
+——-+————————————-+
| gname | group_concat(u.uname separator ,) |
+——-+————————————-+
| root  | root                                |
| dba   | yuegao                              |
| guest | yuegao                              |
+——-+————————————-+
3 rows in set (0.00 sec)

 4. 自连接

mysql select * from processes1;
+——+——————+——+
| pid  | pname            | ppid |
+——+——————+——+
|    1 | init             |    0 |
| 2915 | crond            |    1 |
| 3020 | hald             |    1 |
| 3021 | hald-runner      | 3020 |
| 4707 | gnome-terminal   |    1 |
| 4709 | gnome-pty-helper | 4707 |
| 4710 | bash             | 4707 |
+——+——————+——+
7 rows in set (0.00 sec)

    对上表进行自连接查询,返回进程名和其父进程名:

mysql select a.pname as pname, b.pname as ppname from processes1 as a, processes1 as b where a.ppid
= b.pid;
+——————+—————-+
| pname            | ppname         |
+——————+—————-+
| crond            | init           |
| hald             | init           |
| gnome-terminal   | init           |
| hald-runner      | hald           |
| gnome-pty-helper | gnome-terminal |
| bash             | gnome-terminal |
+——————+—————-+
6 rows in set (0.00 sec)

mysql select a.pname as pname, b.pname as ppname from processes1 as a left join processes1 as b on
a.ppid = b.pid;
+——————+—————-+
| pname            | ppname         |
+——————+—————-+
| init             | NULL           |
| crond            | init           |
| hald             | init           |
| hald-runner      | hald           |
| gnome-terminal   | init           |
| gnome-pty-helper | gnome-terminal |
| bash             | gnome-terminal |
+——————+—————-+
7 rows in set (0.00 sec)

二、联合

mysql select * from groups1;
+——+——-+
| gid  | gname |
+——+——-+
|    0 | root  |
|  101 | dba   |
|  200 | guest |
+——+——-+
3 rows in set (0.02 sec)

mysql create table groups2 as select * from groups1 where 0 = 1;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql insert into groups2 values (102, vip
Query OK, 1 row affected (0.00 sec)

    对 groups1 和 groups2 进行联合查询:

mysql select * from groups1 union select * from groups2;
+——+——-+
| gid  | gname |
+——+——-+
|    0 | root  |
|  101 | dba   |
|  200 | guest |
|  102 | vip   |
+——+——-+
4 rows in set (0.00 sec)

mysql select * from groups1 where gid 0 union select * from groups2;
+——+——-+
| gid  | gname |
+——+——-+
|  101 | dba   |
|  200 | guest |
|  102 | vip   |
+——+——-+
3 rows in set (0.00 sec)

    进行联合必须满足两个基本条件:

1   每个查询返回的字段的数量必须相同。
2   每个查询返回的字段的数据类型必须相互符合。

   UNION 运算符会自动消除联合中的重复记录,包括同一个表中的重复记录:

mysql insert into groups1 values (0, root
Query OK, 1 row affected (0.00 sec)

mysql insert into groups2 values (0, root
Query OK, 1 row affected (0.00 sec)

mysql select * from groups1 union select * from groups2;
+——+——-+
| gid  | gname |
+——+——-+
|    0 | root  |
|  101 | dba   |
|  200 | guest |
|  102 | vip   |
+——+——-+
4 rows in set (0.00 sec)

    要返回联合中的所有记录,可以使用 UNION ALL:

mysql select * from groups1 union all select * from groups2;
+——+——-+
| gid  | gname |
+——+——-+
|    0 | root  |
|  101 | dba   |
|  200 | guest |
|    0 | root  |
|  102 | vip   |
|    0 | root  |
+——+——-+
6 rows in set (0.00 sec)

三、子查询

    子查询有不同的使用方法:

1   在一个 WHERE 或者 HAVING 子句中使用。
2   与比较和逻辑操作符一起使用。
3   与 IN 成员测试仪器使用。
4   与 EXISTS 布尔测试一起使用。
5   在一个 FROM 子句中使用。
6   与连接一起使用。
7   与 UPDATE 和 DELETE 查询一起使用。

   MySQL 不允许在使用子查询读数据的同时删除或者更新相同的表数据:

mysql update users1 set gid = 200 where gid in (select users1.gid from users1 left join groups1 usi
ng(gid) where groups1.gname is null);
ERROR 1093 (HY000): You can t specify target table users1 for update in FROM clause

    子查询的主要优点:

1   使查询结构化,将语句的各部分隔离。
2   提供另一种方法来执行那些需要复杂的连接和联合的操作。
3   在很多人的观念中,子查询比连接或联合更具有可读性。

    但是,子查询可能导致 RDBMS 负荷过大,大幅地降低性能,特别是外部参照的情况(),应谨慎使用。
    大多数情况下,子查询可以转换成连接,如下例(用的是 oracle 中查看表空间使用率的语句,只是为了说明问题):

select
a.tablespace_name tsname,
round(a.bytes,2)                Total_Mb,
round(a.MAXsize,2)              MAXSIZE_Gb,
round(b.bytes,2)                Free_Mb,
(1 – (b.bytes/a.bytes))*100     Pct_used
from
(
select tablespace_name,sum(MAXBYTES/1024/1024/1024) MAXsize,sum(bytes)/1024/1024 bytes
from dba_data_files
group by tablespace_name
) a,
(
select tablespace_name,sum(bytes)/1024/1024 bytes
from dba_free_space
group by tablespace_name
) b
where a.tablespace_name = b.tablespace_name
order by Pct_used;

    可以转换为:

select
a.tablespace_name tsname,
round(sum(a.bytes)/1024/1024,2)                Total_Mb,
round(sum(a.maxbytes/1024/1024/1024),2)              MAXSIZE_Gb,
round(sum(b.bytes)/1024/1024,2)                Free_Mb,
(1 – (sum(b.bytes)/sum(a.bytes)))*100          Pct_used
from dba_data_files a, dba_free_space b where a.tablespace_name = b.tablespace_name
group by a.tablespace_name order by Pct_used;

四、事务

 1. 事务相关语句

   START TRANSACTION 语句用于初始化一个事务,也可以使用 BEGIN 或 BEGIN WORK 语句。
    使用 COMMIT 语句确认所有的变化,或使用 ROLLBACK 语句撤销所有的变化。
   MySQL 使用一个平面事务模型:嵌套的事务时不允许的,开始新的事务会自动提交之前的事务。其它的一些语句也会隐藏执行一个 COMMIT 命令:

1  DROP DATABASE/DROP TABLE
2  CREATE INDEX/DROP INDEX
3  ALTER TABLE/RENAME TABLE
4  LOCK TABLES/UNLOCK TABLES
5  SET AUTOCOMMIT=1

  另外,MySQL 也支持 savepoints,这里不再赘述。

 2. 控制事务行为

   AUTOCOMMIT 变量指定是否开启自动提交模式。默认值为 1,MySQL 把每个语句作为一个单语句事务来处理。

mysql select @@autocommit;
+————–+
| @@autocommit |
+————–+
|            1 |
+————–+
1 row in set (0.03 sec)

   TRANSACTION ISOLATION LEVEL 变量指定事务的隔离等级。默认值为 REPEATABLE READ。

mysql select @@tx_isolation;
+—————–+
| @@tx_isolation  |
+—————–+
| REPEATABLE-READ |
+—————–+
1 row in set (0.00 sec)

    可以设置的四个不同级别依照严格程度由高到低依次为:

1  SERIALIZABLE(序列化)
2  REPEATABLE READ(可重复读)
3  READ COMMITTED(提交的读)
4  READ UNCOMMITTED(未提交的读)

    设置该变量的方法如下:

mysql set transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.05 sec)

mysql select @@tx_isolation;
+——————+
| @@tx_isolation   |
+——————+
| READ-UNCOMMITTED |
+——————+
1 row in set (0.00 sec)

    也可以直接修改 tx_isolation 变量的值:

mysql set tx_isolation= REPEATABLE-READ
Query OK, 0 rows affected (0.00 sec)

mysql select @@tx_isolation;
+—————–+
| @@tx_isolation  |
+—————–+
| REPEATABLE-READ |
+—————–+
1 row in set (0.00 sec)

 3. 事务和性能

    在使用事务表类型时,需要通过一些方法减小对数据库性能的影响。

 1) 使用小事务

   KISS 原则-Keep It Simple, Stupid!

    使事务尽可能地小,且快速地变化和退出,这样其它队列中的事务就不会被过度地延迟:

1   在发出 START TRANSACTION 命令之前,确保要求的用户输入都已完成。
    也就是说,不要在事务开始后因为等待用户输入而造成不必要的延迟。

2   尝试把大的事务分成小的事务然后分别执行。

 2) 选择合适的隔离等级

    隔离等级越高(严格),性能受到的影响越大。选择哪个隔离等级是基于对应用程序容错能力以及潜在数据错误的影响的判断,默认的 REPEATABLE READ 对于大多数情况都是适用的。

 3) 避免死锁

   InnoDB 表处理程序具有检查死锁情况的内建智能,当发现死锁时会撤销其中的一个事务(或释放锁定)来解决死锁。
    开发者在应用程序层面可以做很多事情来避免死锁:在会话初期获得需要的所有锁定;一直以相同的顺序处理表;如果 RDBMS 在解决死锁时撤销了事务,要使用内建的恢复程序来重新执行事务。

到此,关于“MySQL 连接方式有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-18发表,共计11111字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)