板凳-------Mysql cookbook学习 (十一--------11)

14.4 从表中消除重复项 7/14/2025 9:19:12 PM

sql 复制代码
mysql> select * from catalog_list order by last_name, first_name;
+-----------+-------------+--------------------------+
| last_name | first_name  | street                   |
+-----------+-------------+--------------------------+
| Baxter    | Wallace     | 57 3rd Ave.              |
| BAXTER    | WALLACE     | 57 3rd Ave.              |
| Baxter    | Wallace     | 57 3rd Ave., Apt 102     |
| Baxter    | Wallace     | 57 3rd Ave.              |
| BAXTER    | WALLACE     | 57 3rd Ave.              |
| Baxter    | Wallace     | 57 3rd Ave., Apt 102     |
| Brown     | Bartholomew | 432 River Run            |
| Brown     | Bartholomew | 432 River Run            |
| Isaacson  | Jim         | 515 Fordam St., Apt. 917 |
| Isaacson  | Jim         | 515 Fordam St., Apt. 917 |
| McTavish  | Taylor      | 432 River Run            |
| McTavish  | Taylor      | 432 River Run            |
| Pinter    | Marlene     | 9 Sunset Trail           |
| Pinter    | Marlene     | 9 Sunset Trail           |
| Pinter    | Marlene     | 9 Sunset Trail           |
| Pinter    | Marlene     | 9 Sunset Trail           |
+-----------+-------------+--------------------------+
16 rows in set (0.00 sec)

mysql> create table tmpp7 like catalog_list;
Query OK, 0 rows affected (0.08 sec)

mysql> insert into tmpp7 select distinct * from catalog_list;
Query OK, 6 rows affected (0.01 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from tmpp7 order by last_name, first_name;
+-----------+-------------+--------------------------+
| last_name | first_name  | street                   |
+-----------+-------------+--------------------------+
| Baxter    | Wallace     | 57 3rd Ave.              |
| Baxter    | Wallace     | 57 3rd Ave., Apt 102     |
| Brown     | Bartholomew | 432 River Run            |
| Isaacson  | Jim         | 515 Fordam St., Apt. 917 |
| McTavish  | Taylor      | 432 River Run            |
| Pinter    | Marlene     | 9 Sunset Trail           |
+-----------+-------------+--------------------------+
6 rows in set (0.00 sec)

mysql> drop table catalog_list;
Query OK, 0 rows affected (0.04 sec)

mysql> rename table tmpp7 to catalog_list;
Query OK, 0 rows affected (0.04 sec)

mysql> create table tmpp7 like catalog_list;
Query OK, 0 rows affected (0.06 sec)

mysql> alter table tmpp7 add primary key (last_name, first_name);
Query OK, 0 rows affected (0.12 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert ignore into tmpp7 select * from catalog_list;
Query OK, 5 rows affected, 1 warning (0.01 sec)
Records: 6  Duplicates: 1  Warnings: 1

mysql> select * from tmpp7 order by last_name, first_name;
+-----------+-------------+--------------------------+
| last_name | first_name  | street                   |
+-----------+-------------+--------------------------+
| Baxter    | Wallace     | 57 3rd Ave.              |
| Brown     | Bartholomew | 432 River Run            |
| Isaacson  | Jim         | 515 Fordam St., Apt. 917 |
| McTavish  | Taylor      | 432 River Run            |
| Pinter    | Marlene     | 9 Sunset Trail           |
+-----------+-------------+--------------------------+
5 rows in set (0.00 sec)

mysql> drop table catalog_list;
Query OK, 0 rows affected (0.03 sec)

mysql> rename table tmpp7 to catalog_list;
Query OK, 0 rows affected (0.03 sec)

14.5 从自连接的结果中消除重复

sql 复制代码
mysql> select year(s1.statehood) as year,
    -> s1.name as name1, s1.statehood as statehood1,
    -> s2.name as name2, s2.statehood as statehood2
    -> from states as s1 inner join states as s2
    -> on year(s1.statehood) = year(s2.statehood) and s1.name = s2.name
    -> order by year, s1.name, s2.name;
+------+----------------+------------+----------------+------------+
| year | name1          | statehood1 | name2          | statehood2 |
+------+----------------+------------+----------------+------------+
| 1787 | Delaware       | 1787-12-07 | Delaware       | 1787-12-07 |
| 1787 | New Jersey     | 1787-12-18 | New Jersey     | 1787-12-18 |
| 1787 | Pennsylvania   | 1787-12-12 | Pennsylvania   | 1787-12-12 |
| 1788 | Connecticut    | 1788-01-09 | Connecticut    | 1788-01-09 |
| 1788 | Georgia        | 1788-01-02 | Georgia        | 1788-01-02 |
| 1788 | Maryland       | 1788-04-28 | Maryland       | 1788-04-28 |
| 1788 | Massachusetts  | 1788-02-06 | Massachusetts  | 1788-02-06 |
| 1788 | New Hampshire  | 1788-06-21 | New Hampshire  | 1788-06-21 |
| 1788 | New York       | 1788-07-26 | New York       | 1788-07-26 |
| 1788 | South Carolina | 1788-05-23 | South Carolina | 1788-05-23 |
| 1788 | Virginia       | 1788-06-25 | Virginia       | 1788-06-25 |
| 1789 | North Carolina | 1789-11-21 | North Carolina | 1789-11-21 |
| 1790 | Rhode Island   | 1790-05-29 | Rhode Island   | 1790-05-29 |
| 1791 | Vermont        | 1791-03-04 | Vermont        | 1791-03-04 |
| 1792 | Kentucky       | 1792-06-01 | Kentucky       | 1792-06-01 |
| 1796 | Tennessee      | 1796-06-01 | Tennessee      | 1796-06-01 |
| 1803 | Ohio           | 1803-03-01 | Ohio           | 1803-03-01 |
| 1812 | Louisiana      | 1812-04-30 | Louisiana      | 1812-04-30 |
| 1816 | Indiana        | 1816-12-11 | Indiana        | 1816-12-11 |
| 1817 | Mississippi    | 1817-12-10 | Mississippi    | 1817-12-10 |
| 1818 | Illinois       | 1818-12-03 | Illinois       | 1818-12-03 |
| 1819 | Alabama        | 1819-12-14 | Alabama        | 1819-12-14 |
| 1820 | Maine          | 1820-03-15 | Maine          | 1820-03-15 |
| 1821 | Missouri       | 1821-08-10 | Missouri       | 1821-08-10 |
| 1836 | Arkansas       | 1836-06-15 | Arkansas       | 1836-06-15 |
| 1837 | Michigan       | 1837-01-26 | Michigan       | 1837-01-26 |
| 1845 | Florida        | 1845-03-03 | Florida        | 1845-03-03 |
| 1845 | Texas          | 1845-12-29 | Texas          | 1845-12-29 |
| 1846 | Iowa           | 1846-12-28 | Iowa           | 1846-12-28 |
| 1848 | Wisconsin      | 1848-05-29 | Wisconsin      | 1848-05-29 |
| 1850 | California     | 1850-09-09 | California     | 1850-09-09 |
| 1858 | Minnesota      | 1858-05-11 | Minnesota      | 1858-05-11 |
| 1859 | Oregon         | 1859-02-14 | Oregon         | 1859-02-14 |
| 1861 | Kansas         | 1861-01-29 | Kansas         | 1861-01-29 |
| 1863 | West Virginia  | 1863-06-20 | West Virginia  | 1863-06-20 |
| 1864 | Nevada         | 1864-10-31 | Nevada         | 1864-10-31 |
| 1867 | Nebraska       | 1867-03-01 | Nebraska       | 1867-03-01 |
| 1876 | Colorado       | 1876-08-01 | Colorado       | 1876-08-01 |
| 1889 | Montana        | 1889-11-08 | Montana        | 1889-11-08 |
| 1889 | North Dakota   | 1889-11-02 | North Dakota   | 1889-11-02 |
| 1889 | South Dakota   | 1889-11-02 | South Dakota   | 1889-11-02 |
| 1889 | Washington     | 1889-11-11 | Washington     | 1889-11-11 |
| 1890 | Idaho          | 1890-07-03 | Idaho          | 1890-07-03 |
| 1890 | Wyoming        | 1890-07-10 | Wyoming        | 1890-07-10 |
| 1896 | Utah           | 1896-01-04 | Utah           | 1896-01-04 |
| 1907 | Oklahoma       | 1907-11-16 | Oklahoma       | 1907-11-16 |
| 1912 | Arizona        | 1912-02-14 | Arizona        | 1912-02-14 |
| 1912 | New Mexico     | 1912-01-06 | New Mexico     | 1912-01-06 |
| 1959 | Alaska         | 1959-01-03 | Alaska         | 1959-01-03 |
| 1959 | Hawaii         | 1959-08-21 | Hawaii         | 1959-08-21 |
+------+----------------+------------+----------------+------------+
50 rows in set (0.01 sec)

这个查询会:
1.	找出同一年加入联邦的州对
2.	按字母顺序排列每对州的名称(name1是字母顺序靠前的,name2是字母顺序靠后的)
3.	按照年份、name1和name2排序结果

mysql> SELECT YEAR(s1.statehood) AS year,
    ->        IF(s1.name < s2.name, s1.name, s2.name) AS name1,
    ->        IF(s1.name < s2.name, s1.statehood, s2.statehood) AS statehood1,
    ->        IF(s1.name < s2.name, s2.name, s1.name) AS name2,
    ->        IF(s1.name < s2.name, s2.statehood, s1.statehood) AS statehood2
    -> FROM states AS s1
    -> INNER JOIN states AS s2
    -> ON YEAR(s1.statehood) = YEAR(s2.statehood) AND s1.name != s2.name
    -> ORDER BY year, name1, name2;
+------+----------------+------------+----------------+------------+
| year | name1          | statehood1 | name2          | statehood2 |
+------+----------------+------------+----------------+------------+
| 1787 | Delaware       | 1787-12-07 | New Jersey     | 1787-12-18 |
| 1787 | Delaware       | 1787-12-07 | New Jersey     | 1787-12-18 |
| 1787 | Delaware       | 1787-12-07 | Pennsylvania   | 1787-12-12 |
| 1787 | Delaware       | 1787-12-07 | Pennsylvania   | 1787-12-12 |
| 1787 | New Jersey     | 1787-12-18 | Pennsylvania   | 1787-12-12 |
| 1787 | New Jersey     | 1787-12-18 | Pennsylvania   | 1787-12-12 |
| 1788 | Connecticut    | 1788-01-09 | Georgia        | 1788-01-02 |
| 1788 | Connecticut    | 1788-01-09 | Georgia        | 1788-01-02 |
| 1788 | Connecticut    | 1788-01-09 | Maryland       | 1788-04-28 |
| 1788 | Connecticut    | 1788-01-09 | Maryland       | 1788-04-28 |
| 1788 | Connecticut    | 1788-01-09 | Massachusetts  | 1788-02-06 |
| 1788 | Connecticut    | 1788-01-09 | Massachusetts  | 1788-02-06 |
| 1788 | Connecticut    | 1788-01-09 | New Hampshire  | 1788-06-21 |
| 1788 | Connecticut    | 1788-01-09 | New Hampshire  | 1788-06-21 |
| 1788 | Connecticut    | 1788-01-09 | New York       | 1788-07-26 |
| 1788 | Connecticut    | 1788-01-09 | New York       | 1788-07-26 |
| 1788 | Connecticut    | 1788-01-09 | South Carolina | 1788-05-23 |
| 1788 | Connecticut    | 1788-01-09 | South Carolina | 1788-05-23 |
| 1788 | Connecticut    | 1788-01-09 | Virginia       | 1788-06-25 |
| 1788 | Connecticut    | 1788-01-09 | Virginia       | 1788-06-25 |
| 1788 | Georgia        | 1788-01-02 | Maryland       | 1788-04-28 |
| 1788 | Georgia        | 1788-01-02 | Maryland       | 1788-04-28 |
| 1788 | Georgia        | 1788-01-02 | Massachusetts  | 1788-02-06 |
| 1788 | Georgia        | 1788-01-02 | Massachusetts  | 1788-02-06 |
| 1788 | Georgia        | 1788-01-02 | New Hampshire  | 1788-06-21 |
| 1788 | Georgia        | 1788-01-02 | New Hampshire  | 1788-06-21 |
| 1788 | Georgia        | 1788-01-02 | New York       | 1788-07-26 |
| 1788 | Georgia        | 1788-01-02 | New York       | 1788-07-26 |
| 1788 | Georgia        | 1788-01-02 | South Carolina | 1788-05-23 |
| 1788 | Georgia        | 1788-01-02 | South Carolina | 1788-05-23 |
| 1788 | Georgia        | 1788-01-02 | Virginia       | 1788-06-25 |
| 1788 | Georgia        | 1788-01-02 | Virginia       | 1788-06-25 |
| 1788 | Maryland       | 1788-04-28 | Massachusetts  | 1788-02-06 |
| 1788 | Maryland       | 1788-04-28 | Massachusetts  | 1788-02-06 |
| 1788 | Maryland       | 1788-04-28 | New Hampshire  | 1788-06-21 |
| 1788 | Maryland       | 1788-04-28 | New Hampshire  | 1788-06-21 |
| 1788 | Maryland       | 1788-04-28 | New York       | 1788-07-26 |
| 1788 | Maryland       | 1788-04-28 | New York       | 1788-07-26 |
| 1788 | Maryland       | 1788-04-28 | South Carolina | 1788-05-23 |
| 1788 | Maryland       | 1788-04-28 | South Carolina | 1788-05-23 |
| 1788 | Maryland       | 1788-04-28 | Virginia       | 1788-06-25 |
| 1788 | Maryland       | 1788-04-28 | Virginia       | 1788-06-25 |
| 1788 | Massachusetts  | 1788-02-06 | New Hampshire  | 1788-06-21 |
| 1788 | Massachusetts  | 1788-02-06 | New Hampshire  | 1788-06-21 |
| 1788 | Massachusetts  | 1788-02-06 | New York       | 1788-07-26 |
| 1788 | Massachusetts  | 1788-02-06 | New York       | 1788-07-26 |
| 1788 | Massachusetts  | 1788-02-06 | South Carolina | 1788-05-23 |
| 1788 | Massachusetts  | 1788-02-06 | South Carolina | 1788-05-23 |
| 1788 | Massachusetts  | 1788-02-06 | Virginia       | 1788-06-25 |
| 1788 | Massachusetts  | 1788-02-06 | Virginia       | 1788-06-25 |
| 1788 | New Hampshire  | 1788-06-21 | New York       | 1788-07-26 |
| 1788 | New Hampshire  | 1788-06-21 | New York       | 1788-07-26 |
| 1788 | New Hampshire  | 1788-06-21 | South Carolina | 1788-05-23 |
| 1788 | New Hampshire  | 1788-06-21 | South Carolina | 1788-05-23 |
| 1788 | New Hampshire  | 1788-06-21 | Virginia       | 1788-06-25 |
| 1788 | New Hampshire  | 1788-06-21 | Virginia       | 1788-06-25 |
| 1788 | New York       | 1788-07-26 | South Carolina | 1788-05-23 |
| 1788 | New York       | 1788-07-26 | South Carolina | 1788-05-23 |
| 1788 | New York       | 1788-07-26 | Virginia       | 1788-06-25 |
| 1788 | New York       | 1788-07-26 | Virginia       | 1788-06-25 |
| 1788 | South Carolina | 1788-05-23 | Virginia       | 1788-06-25 |
| 1788 | South Carolina | 1788-05-23 | Virginia       | 1788-06-25 |
| 1845 | Florida        | 1845-03-03 | Texas          | 1845-12-29 |
| 1845 | Florida        | 1845-03-03 | Texas          | 1845-12-29 |
| 1889 | Montana        | 1889-11-08 | North Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | North Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | South Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | South Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | Washington     | 1889-11-11 |
| 1889 | Montana        | 1889-11-08 | Washington     | 1889-11-11 |
| 1889 | North Dakota   | 1889-11-02 | South Dakota   | 1889-11-02 |
| 1889 | North Dakota   | 1889-11-02 | South Dakota   | 1889-11-02 |
| 1889 | North Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1889 | North Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1889 | South Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1889 | South Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1890 | Idaho          | 1890-07-03 | Wyoming        | 1890-07-10 |
| 1890 | Idaho          | 1890-07-03 | Wyoming        | 1890-07-10 |
| 1912 | Arizona        | 1912-02-14 | New Mexico     | 1912-01-06 |
| 1912 | Arizona        | 1912-02-14 | New Mexico     | 1912-01-06 |
| 1959 | Alaska         | 1959-01-03 | Hawaii         | 1959-08-21 |
| 1959 | Alaska         | 1959-01-03 | Hawaii         | 1959-08-21 |
+------+----------------+------------+----------------+------------+
82 rows in set (0.00 sec)

增加distinct 消除多余的拷贝
mysql> SELECT distinct YEAR(s1.statehood) AS year,
    ->        IF(s1.name < s2.name, s1.name, s2.name) AS name1,
    ->        IF(s1.name < s2.name, s1.statehood, s2.statehood) AS statehood1,
    ->        IF(s1.name < s2.name, s2.name, s1.name) AS name2,
    ->        IF(s1.name < s2.name, s2.statehood, s1.statehood) AS statehood2
    -> FROM states AS s1
    -> INNER JOIN states AS s2
    -> ON YEAR(s1.statehood) = YEAR(s2.statehood) AND s1.name != s2.name
    -> ORDER BY year, name1, name2;
+------+----------------+------------+----------------+------------+
| year | name1          | statehood1 | name2          | statehood2 |
+------+----------------+------------+----------------+------------+
| 1787 | Delaware       | 1787-12-07 | New Jersey     | 1787-12-18 |
| 1787 | Delaware       | 1787-12-07 | Pennsylvania   | 1787-12-12 |
| 1787 | New Jersey     | 1787-12-18 | Pennsylvania   | 1787-12-12 |
| 1788 | Connecticut    | 1788-01-09 | Georgia        | 1788-01-02 |
| 1788 | Connecticut    | 1788-01-09 | Maryland       | 1788-04-28 |
| 1788 | Connecticut    | 1788-01-09 | Massachusetts  | 1788-02-06 |
| 1788 | Connecticut    | 1788-01-09 | New Hampshire  | 1788-06-21 |
| 1788 | Connecticut    | 1788-01-09 | New York       | 1788-07-26 |
| 1788 | Connecticut    | 1788-01-09 | South Carolina | 1788-05-23 |
| 1788 | Connecticut    | 1788-01-09 | Virginia       | 1788-06-25 |
| 1788 | Georgia        | 1788-01-02 | Maryland       | 1788-04-28 |
| 1788 | Georgia        | 1788-01-02 | Massachusetts  | 1788-02-06 |
| 1788 | Georgia        | 1788-01-02 | New Hampshire  | 1788-06-21 |
| 1788 | Georgia        | 1788-01-02 | New York       | 1788-07-26 |
| 1788 | Georgia        | 1788-01-02 | South Carolina | 1788-05-23 |
| 1788 | Georgia        | 1788-01-02 | Virginia       | 1788-06-25 |
| 1788 | Maryland       | 1788-04-28 | Massachusetts  | 1788-02-06 |
| 1788 | Maryland       | 1788-04-28 | New Hampshire  | 1788-06-21 |
| 1788 | Maryland       | 1788-04-28 | New York       | 1788-07-26 |
| 1788 | Maryland       | 1788-04-28 | South Carolina | 1788-05-23 |
| 1788 | Maryland       | 1788-04-28 | Virginia       | 1788-06-25 |
| 1788 | Massachusetts  | 1788-02-06 | New Hampshire  | 1788-06-21 |
| 1788 | Massachusetts  | 1788-02-06 | New York       | 1788-07-26 |
| 1788 | Massachusetts  | 1788-02-06 | South Carolina | 1788-05-23 |
| 1788 | Massachusetts  | 1788-02-06 | Virginia       | 1788-06-25 |
| 1788 | New Hampshire  | 1788-06-21 | New York       | 1788-07-26 |
| 1788 | New Hampshire  | 1788-06-21 | South Carolina | 1788-05-23 |
| 1788 | New Hampshire  | 1788-06-21 | Virginia       | 1788-06-25 |
| 1788 | New York       | 1788-07-26 | South Carolina | 1788-05-23 |
| 1788 | New York       | 1788-07-26 | Virginia       | 1788-06-25 |
| 1788 | South Carolina | 1788-05-23 | Virginia       | 1788-06-25 |
| 1845 | Florida        | 1845-03-03 | Texas          | 1845-12-29 |
| 1889 | Montana        | 1889-11-08 | North Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | South Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | Washington     | 1889-11-11 |
| 1889 | North Dakota   | 1889-11-02 | South Dakota   | 1889-11-02 |
| 1889 | North Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1889 | South Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1890 | Idaho          | 1890-07-03 | Wyoming        | 1890-07-10 |
| 1912 | Arizona        | 1912-02-14 | New Mexico     | 1912-01-06 |
| 1959 | Alaska         | 1959-01-03 | Hawaii         | 1959-08-21 |
+------+----------------+------------+----------------+------------+
41 rows in set (0.00 sec)

mysql> SELECT YEAR(s1.statehood) AS year,
    ->        IF(s1.name < s2.name, s1.name, s2.name) AS name1,
    ->        IF(s1.name < s2.name, s1.statehood, s2.statehood) AS statehood1,
    ->        IF(s1.name < s2.name, s2.name, s1.name) AS name2,
    ->        IF(s1.name < s2.name, s2.statehood, s1.statehood) AS statehood2
    -> FROM states AS s1
    -> INNER JOIN states AS s2
    -> ON YEAR(s1.statehood) = YEAR(s2.statehood) AND s1.name < s2.name
    -> ORDER BY year, name1, name2;
+------+----------------+------------+----------------+------------+
| year | name1          | statehood1 | name2          | statehood2 |
+------+----------------+------------+----------------+------------+
| 1787 | Delaware       | 1787-12-07 | New Jersey     | 1787-12-18 |
| 1787 | Delaware       | 1787-12-07 | Pennsylvania   | 1787-12-12 |
| 1787 | New Jersey     | 1787-12-18 | Pennsylvania   | 1787-12-12 |
| 1788 | Connecticut    | 1788-01-09 | Georgia        | 1788-01-02 |
| 1788 | Connecticut    | 1788-01-09 | Maryland       | 1788-04-28 |
| 1788 | Connecticut    | 1788-01-09 | Massachusetts  | 1788-02-06 |
| 1788 | Connecticut    | 1788-01-09 | New Hampshire  | 1788-06-21 |
| 1788 | Connecticut    | 1788-01-09 | New York       | 1788-07-26 |
| 1788 | Connecticut    | 1788-01-09 | South Carolina | 1788-05-23 |
| 1788 | Connecticut    | 1788-01-09 | Virginia       | 1788-06-25 |
| 1788 | Georgia        | 1788-01-02 | Maryland       | 1788-04-28 |
| 1788 | Georgia        | 1788-01-02 | Massachusetts  | 1788-02-06 |
| 1788 | Georgia        | 1788-01-02 | New Hampshire  | 1788-06-21 |
| 1788 | Georgia        | 1788-01-02 | New York       | 1788-07-26 |
| 1788 | Georgia        | 1788-01-02 | South Carolina | 1788-05-23 |
| 1788 | Georgia        | 1788-01-02 | Virginia       | 1788-06-25 |
| 1788 | Maryland       | 1788-04-28 | Massachusetts  | 1788-02-06 |
| 1788 | Maryland       | 1788-04-28 | New Hampshire  | 1788-06-21 |
| 1788 | Maryland       | 1788-04-28 | New York       | 1788-07-26 |
| 1788 | Maryland       | 1788-04-28 | South Carolina | 1788-05-23 |
| 1788 | Maryland       | 1788-04-28 | Virginia       | 1788-06-25 |
| 1788 | Massachusetts  | 1788-02-06 | New Hampshire  | 1788-06-21 |
| 1788 | Massachusetts  | 1788-02-06 | New York       | 1788-07-26 |
| 1788 | Massachusetts  | 1788-02-06 | South Carolina | 1788-05-23 |
| 1788 | Massachusetts  | 1788-02-06 | Virginia       | 1788-06-25 |
| 1788 | New Hampshire  | 1788-06-21 | New York       | 1788-07-26 |
| 1788 | New Hampshire  | 1788-06-21 | South Carolina | 1788-05-23 |
| 1788 | New Hampshire  | 1788-06-21 | Virginia       | 1788-06-25 |
| 1788 | New York       | 1788-07-26 | South Carolina | 1788-05-23 |
| 1788 | New York       | 1788-07-26 | Virginia       | 1788-06-25 |
| 1788 | South Carolina | 1788-05-23 | Virginia       | 1788-06-25 |
| 1845 | Florida        | 1845-03-03 | Texas          | 1845-12-29 |
| 1889 | Montana        | 1889-11-08 | North Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | South Dakota   | 1889-11-02 |
| 1889 | Montana        | 1889-11-08 | Washington     | 1889-11-11 |
| 1889 | North Dakota   | 1889-11-02 | South Dakota   | 1889-11-02 |
| 1889 | North Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1889 | South Dakota   | 1889-11-02 | Washington     | 1889-11-11 |
| 1890 | Idaho          | 1890-07-03 | Wyoming        | 1890-07-10 |
| 1912 | Arizona        | 1912-02-14 | New Mexico     | 1912-01-06 |
| 1959 | Alaska         | 1959-01-03 | Hawaii         | 1959-08-21 |
+------+----------------+------------+----------------+------------+
41 rows in set (0.00 sec)

第15章:执行事务

15.0 引言

sql 复制代码
mysql> CREATE TABLE pilot (
    ->   pilot_id INT PRIMARY KEY,
    ->   name VARCHAR(50),
    ->   available ENUM('yes','no')
    -> );
Query OK, 0 rows affected (0.05 sec)

mysql> select @p_val := pilot_id from pilot where available = 'yes' limit 1;
Empty set, 1 warning (0.00 sec)

mysql> update pilot set available = 'no' where pilot_id = @p_val;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

mysql> update flight set pilot_id = @p_val where flight_id = 578;
ERROR 1146 (42S02): Table 'cookbook.flight' doesn't exist
mysql> INSERT INTO pilot (pilot_id, name, available) VALUES
    -> (1, 'John Smith', 'yes'),
    -> (2, 'Jane Doe', 'yes'),
    -> (3, 'Mike Johnson', 'no');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT @p_val := pilot_id FROM pilot WHERE available = 'yes' LIMIT 1;
+--------------------+
| @p_val := pilot_id |
+--------------------+
|                  1 |
+--------------------+
1 row in set, 1 warning (0.00 sec)

mysql> CREATE TABLE flight (
    ->   flight_id INT PRIMARY KEY,
    ->   pilot_id INT,
    ->   flight_date DATETIME,
    ->   -- 其他需要的列
    ->   FOREIGN KEY (pilot_id) REFERENCES pilot(pilot_id)
    -> );
Query OK, 0 rows affected (0.09 sec)

mysql>
mysql> -- 插入测试数据
mysql> INSERT INTO flight (flight_id, pilot_id, flight_date) VALUES
    -> (578, NULL, '2023-12-01 10:00:00');
Query OK, 1 row affected (0.01 sec)

15.1 使用事务存储引擎

sql 复制代码
mysql> show engines\g
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| FEDERATED          | YES     | Federated MySQL storage engine                                 | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| ndbinfo            | NO      | MySQL Cluster system information storage engine                | NULL         | NULL | NULL       |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| ndbcluster         | NO      | Clustered, fault-tolerant tables                               | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
11 rows in set (0.00 sec)

mysql> create table ttt1 (i int) engine = InnoDB;
Query OK, 0 rows affected (0.05 sec)

mysql> create table ttt2 (i int) engine = BDB;
ERROR 1286 (42000): Unknown storage engine 'BDB'
mysql> create table ttt2 (i int) engine = MyISAM;
Query OK, 0 rows affected (0.02 sec)

mysql> alter table ttt engine = InnoDB;
Query OK, 0 rows affected (0.26 sec)
Records: 0  Duplicates: 0  Warnings: 0

15.2 使用sql执行事务

sql 复制代码
mysql> DROP TABLE ttt;
Query OK, 0 rows affected (0.04 sec)

mysql> CREATE TABLE ttt (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (0.06 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO ttt (i) VALUES(1);
Query OK, 1 row affected (0.00 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.01 sec)

mysql>  INSERT INTO ttt (i) VALUES(2);
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from ttt;
+------+
| i    |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> insert into ttt (x) values(3);
ERROR 1054 (42S22): Unknown column 'x' in 'field list'
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from ttt;
+------+
| i    |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
•	作用:关闭自动提交模式(默认是 autocommit=1,即每条SQL语句自动提交)
•	效果:后续所有操作将在一个事务中,直到显式执行 COMMIT 或 ROLLBACK
•	类比:相当于打开了一个"编辑会话",所有修改不会立即生效

mysql> insert into ttt (i) values(3);
Query OK, 1 row affected (0.00 sec)

mysql> insert into ttt (i) values(4);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from ttt;
+------+
| i    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+
4 rows in set (0.00 sec)

mysql> set autocommit = 1;
Query OK, 0 rows affected (0.00 sec)
•	作用:重新开启自动提交模式
•	后续影响:
o	每条SQL语句将再次自动成为独立事务
o	不需要显式执行 COMMIT

在 MySQL 中,执行 DROP DATABASE 后无法通过 ROLLBACK 恢复数据库,这是由以下几个关键原因决定的:
1. DDL 语句的自动提交特性
•	所有 DDL(数据定义语言)语句(如 CREATE, ALTER, DROP)会自动提交当前事务,不受 autocommit 设置影响。
•	即使你设置了 SET autocommit=0,执行 DROP DATABASE 时:
sql
复制
下载
SET autocommit=0;
DROP DATABASE mydb;  -- 这条语句会立即提交
ROLLBACK;           -- 此时已无效
2. 事务日志不记录 DDL 操作
•	事务的回滚依赖于事务日志(undo log),但 DDL 操作:
o	直接修改数据字典(元数据)
o	不生成可回滚的事务日志
o	会隐式提交当前所有未提交的事务
3. 物理文件删除
•	DROP DATABASE 不仅删除元数据,还会直接删除磁盘上的数据文件(.ibd, .frm 等)
•	这种物理删除操作超出了事务系统的管理范围
对比示例
操作类型	是否可回滚	原因
INSERT/UPDATE	✅ 可以	生成 undo log,事务系统可回滚
DROP DATABASE	❌ 不可以	自动提交+无 undo log+物理文件删除
解决方案(如果误删数据库)
1.	从备份恢复:
bash
复制
下载
mysql -u root -p < backup.sql
2.	使用二进制日志(需提前开启):
sql
复制
下载
mysqlbinlog --start-datetime="2023-11-01 00:00:00" binlog.000123 | mysql -u root -p
3.	专业数据恢复工具(如 Percona Data Recovery Tool for InnoDB)
预防措施
sql
复制
下载
-- 重要操作前先备份
CREATE DATABASE mydb_backup;
USE mydb_backup;
CREATE TABLE ... SELECT * FROM original_db.*;  -- 快速克隆

-- 或使用 mysqldump
mysqldump -u root -p original_db > backup.sql
总结:DROP DATABASE 是设计上不可逆的操作,因其直接修改物理存储结构,这与事务系统的设计目标(管理数据修改而非结构变更)有本质区别。
相关推荐
小杨爱搞嵌入式9 分钟前
【STM32】GPIO的输入输出
c语言·笔记·stm32·单片机·学习
皮蛋sol周11 分钟前
嵌入式学习硬件(一)ARM体系架构
arm开发·学习·架构
神仙别闹1 小时前
基于Python+Vue+Mysql实现(物联网)智能大棚
vue.js·物联网·mysql
花途Jasmine2 小时前
MySQL中的DDL(一)
数据库·mysql
无名工程师2 小时前
浅谈RNN被Transformer 取代的必然性
rnn·学习·transformer
Virgil1394 小时前
【YOLO学习笔记】YOLOv8详解解读
笔记·学习·yolo
学习网安的doro4 小时前
3a服务器的基本功能1之身份认证
服务器·网络·学习·安全·身份认证·ac
Forever Nore6 小时前
Nginx 学习
运维·学习·nginx
五岁小孩吖7 小时前
Mysql 如何使用 binlog 日志回滚操作失误的数据
mysql
2301_801673017 小时前
ipv6学习
linux·服务器·学习