MySQL Cookbook 学习笔记-04
2011-08-31 11:41
417 查看
1、处理重复
<a>、创建表包含 primary key 或 unique index,阻止重复数据写入
<b>、联合 <a>,使用 INSERT IGNORE 或 REPLACE
<c>、检查表是否有重复行的方法,通过 group by 和 count( x ) 来统计
<d>、通过 SELECT DISTINCT 来过滤重复
a——示例
b——示例
一般情况下,插入重复 primary key 或 union index 会报错
(Recipe 14.4. Eliminating Duplicates from a Table)
<a>、Removing duplicates using table replacement
<b>、Removing duplicates by adding an index
<c>、Removing duplicates of a particular row
a——示例
3、删除“语义重复”但行数据不重复的行
(Recipe 14.5. Eliminating Duplicates from a Self-Join Result)
1787年有3个州(Delaware,New Jersey,Pennsylvania),两两配对应该是3个才对。
但是这里却又6条数据,一半重复(语义上)!
将“语义重复”调整为“行数据重复”
如果,name1 < name2,成立保持不变
如果,name1 < name2,不成立。name1 与 name2 互换;statehood1 与 statehood2 互换。
4、选择支持事务的存储引擎
(Recipe 15.1. Choosing a Transactional Storage Engine)
(Recipe 15.2. Performing Transactions Using SQL)
7、存储过程
Navicat 中创建存储过程注意事项:
<a>、在Navicat里面不需要写头,直接从BEGIN开始即可。
<b>、过程名将在保存的时候填写,参数则可以填在代码定义框下面的参数输入框中,如果要使用返回值,则可以设定类型为FUNCTION,回传框即可填写。
<a>、创建表包含 primary key 或 unique index,阻止重复数据写入
<b>、联合 <a>,使用 INSERT IGNORE 或 REPLACE
<c>、检查表是否有重复行的方法,通过 group by 和 count( x ) 来统计
<d>、通过 SELECT DISTINCT 来过滤重复
a——示例
CREATE TABLE person ( last_name CHAR(20) NOT NULL, first_name CHAR(20) NOT NULL, address CHAR(40), PRIMARY KEY (last_name, first_name) );
CREATE TABLE person ( last_name CHAR(20) NOT NULL, first_name CHAR(20) NOT NULL, address CHAR(40), UNIQUE (last_name, first_name) );
b——示例
一般情况下,插入重复 primary key 或 union index 会报错
mysql> INSERT INTO person (last_name, first_name) -> VALUES('X1','Y1'); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO person (last_name, first_name) -> VALUES('X1','Y1'); ERROR 1062 (23000): Duplicate entry 'X1-Y1' for key 1使用 INSERT IGNORE
mysql> INSERT IGNORE INTO person (last_name, first_name) -> VALUES('X2','Y2'); Query OK, 1 row affected (0.00 sec) mysql> INSERT IGNORE INTO person (last_name, first_name) -> VALUES('X2','Y2'); Query OK, 0 rows affected (0.00 sec)使用 REPLACE
mysql> REPLACE INTO person (last_name, first_name) -> VALUES('X3','Y3'); Query OK, 1 row affected (0.00 sec) mysql> REPLACE INTO person (last_name, first_name) -> VALUES('X3','Y3'); Query OK, 2 rows affected (0.00 sec)使用 INSERT ... ON DUPLICATE KEY UPDATE
CREATE TABLE poll_vote ( poll_id INT UNSIGNED NOT NULL AUTO_INCREMENT, candidate_id INT UNSIGNED, vote_count INT UNSIGNED, PRIMARY KEY (poll_id, candidate_id) ); mysql> SELECT * FROM poll_vote; Empty set (0.01 sec) mysql> INSERT INTO poll_vote (poll_id,candidate_id,vote_count) VALUES(14,2,1) -> ON DUPLICATE KEY UPDATE vote_count = vote_count + 1; Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM poll_vote; +---------+--------------+------------+ | poll_id | candidate_id | vote_count | +---------+--------------+------------+ | 14 | 2 | 1 | +---------+--------------+------------+ 1 row in set (0.01 sec) mysql> INSERT INTO poll_vote (poll_id,candidate_id,vote_count) VALUES(14,2,1) -> ON DUPLICATE KEY UPDATE vote_count = vote_count + 1; Query OK, 2 rows affected (0.00 sec) mysql> SELECT * FROM poll_vote; +---------+--------------+------------+ | poll_id | candidate_id | vote_count | +---------+--------------+------------+ | 14 | 2 | 2 | +---------+--------------+------------+ 1 row in set (0.00 sec)c——示例
mysql> SELECT * FROM catalog_list; +-----------+-------------+--------------------------+ | last_name | first_name | street | +-----------+-------------+--------------------------+ | Isaacson | Jim | 515 Fordam St., Apt. 917 | | Baxter | Wallace | 57 3rd Ave. | | McTavish | Taylor | 432 River Run | | Pinter | Marlene | 9 Sunset Trail | | BAXTER | WALLACE | 57 3rd Ave. | | Brown | Bartholomew | 432 River Run | | Pinter | Marlene | 9 Sunset Trail | | Baxter | Wallace | 57 3rd Ave., Apt 102 | +-----------+-------------+--------------------------+ mysql> select count(*) as total_rows, -> count(distinct last_name, first_name) as distince_names, -> count(*) - count(distinct last_name, first_name) as duplicate_names -> from catalog_list; +------------+----------------+-----------------+ | total_rows | distince_names | duplicate_names | +------------+----------------+-----------------+ | 8 | 5 | 3 | +------------+----------------+-----------------+查询出重复的行:
mysql> select count(*) as repetitions, last_name, first_name -> from catalog_list -> group by last_name, first_name -> having repetitions > 1; +-------------+-----------+------------+ | repetitions | last_name | first_name | +-------------+-----------+------------+ | 3 | Baxter | Wallace | | 2 | Pinter | Marlene | +-------------+-----------+------------+2、从表中删除重复
(Recipe 14.4. Eliminating Duplicates from a Table)
<a>、Removing duplicates using table replacement
<b>、Removing duplicates by adding an index
<c>、Removing duplicates of a particular row
a——示例
mysql> CREATE TABLE tmp LIKE catalog_list; mysql> ALTER TABLE tmp ADD PRIMARY KEY (last_name, first_name); mysql> INSERT IGNORE INTO tmp SELECT * FROM catalog_list; mysql> SELECT * FROM tmp 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 | +-----------+-------------+--------------------------+ mysql> DROP TABLE catalog_list; mysql> RENAME TABLE tmp TO catalog_list;b——示例
mysql> ALTER IGNORE TABLE catalog_list -> ADD PRIMARY KEY (last_name, first_name); mysql> SELECT * FROM catalog_list 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 | +-----------+-------------+--------------------------+c——示例
+-------+ | color | +-------+ | blue | | green | | blue | | blue | | red | | green | | red | +-------+ mysql> DELETE FROM t WHERE color = 'blue' LIMIT 2; mysql> DELETE FROM t WHERE color = 'green' LIMIT 1; mysql> DELETE FROM t WHERE color = 'red' LIMIT 1; mysql> SELECT * FROM t; +-------+ | color | +-------+ | blue | | green | | red | +-------+
3、删除“语义重复”但行数据不重复的行
(Recipe 14.5. Eliminating Duplicates from a Self-Join Result)
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 | New Jersey | 1787-12-18 | | 1787 | Delaware | 1787-12-07 | Pennsylvania | 1787-12-12 | | 1787 | New Jersey | 1787-12-18 | Delaware | 1787-12-07 | | 1787 | New Jersey | 1787-12-18 | Pennsylvania | 1787-12-12 | | 1787 | Pennsylvania | 1787-12-12 | Delaware | 1787-12-07 | | 1787 | Pennsylvania | 1787-12-12 | New Jersey | 1787-12-18 | ... | 1912 | Arizona | 1912-02-14 | New Mexico | 1912-01-06 | | 1912 | New Mexico | 1912-01-06 | Arizona | 1912-02-14 | | 1959 | Alaska | 1959-01-03 | Hawaii | 1959-08-21 | | 1959 | Hawaii | 1959-08-21 | Alaska | 1959-01-03 | +------+----------------+------------+----------------+------------+由上数据分析:
1787年有3个州(Delaware,New Jersey,Pennsylvania),两两配对应该是3个才对。
但是这里却又6条数据,一半重复(语义上)!
将“语义重复”调整为“行数据重复”
+------+----------------+------------+----------------+------------+ | year | name1 | statehood1 | name2 | statehood2 | +------+----------------+------------+----------------+------------+ | 1787 | Delaware | 1787-12-07 | New Jersey | 1787-12-18 | | 1787 | New Jersey | 1787-12-18 | Delaware | 1787-12-07 |也就是:
如果,name1 < name2,成立保持不变
如果,name1 < name2,不成立。name1 与 name2 互换;statehood1 与 statehood2 互换。
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 | ... | 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 | +------+----------------+------------+----------------+------------+再用 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 | ... | 1912 | Arizona | 1912-02-14 | New Mexico | 1912-01-06 | | 1959 | Alaska | 1959-01-03 | Hawaii | 1959-08-21 | +------+----------------+------------+----------------+------------+
4、选择支持事务的存储引擎
(Recipe 15.1. Choosing a Transactional Storage Engine)
mysql> SHOW ENGINES\G *************************** 1. row *************************** Engine: MyISAM Support: DEFAULT Comment: Default engine as of MySQL 3.23 with great performance *************************** 2. row *************************** Engine: MEMORY Support: YES Comment: Hash based, stored in memory, useful for temporary tables *************************** 3. row *************************** Engine: InnoDB Support: YES Comment: Supports transactions, row-level locking, and foreign keys *************************** 4. row *************************** Engine: BerkeleyDB Support: YES Comment: Supports transactions and page-level locking ...创建表:
CREATE TABLE t1 (i INT) ENGINE = InnoDB; CREATE TABLE t2 (i INT) ENGINE = BDB;修改表:
ALTER TABLE t ENGINE = InnoDB;5、使用 SQL 执行事务
(Recipe 15.2. Performing Transactions Using SQL)
mysql> CREATE TABLE t (i INT) ENGINE = InnoDB; mysql> START TRANSACTION; mysql> INSERT INTO t (i) VALUES(1); mysql> INSERT INTO t (i) VALUES(2); mysql> COMMIT; mysql> SELECT * FROM t; +------+ | i | +------+ | 1 | | 2 | +------+关闭自动提交:
mysql> CREATE TABLE t (i INT) ENGINE = InnoDB; mysql> SET autocommit = 0; mysql> INSERT INTO t (i) VALUES(1); mysql> INSERT INTO t (i) VALUES(2); mysql> COMMIT; mysql> SELECT * FROM t; +------+ | i | +------+ | 1 | | 2 | +------+开启自动提交:
mysql> SET autocommit = 1;6、在程序中使用事务(Java 示例)
try { conn.setAutoCommit (false); Statement s = conn.createStatement (); // move some money from one person to the other s.executeUpdate ("UPDATE money SET amt = amt - 6 WHERE name = 'Eve'"); s.executeUpdate ("UPDATE money SET amt = amt + 6 WHERE name = 'Ida'"); s.close (); conn.commit (); conn.setAutoCommit (true); } catch (SQLException e) { System.err.println ("Transaction failed, rolling back."); Cookbook.printErrorMessage (e); // empty exception handler in case rollback fails try { conn.rollback (); conn.setAutoCommit (true); } catch (Exception e2) { } }
7、存储过程
Navicat 中创建存储过程注意事项:
<a>、在Navicat里面不需要写头,直接从BEGIN开始即可。
<b>、过程名将在保存的时候填写,参数则可以填在代码定义框下面的参数输入框中,如果要使用返回值,则可以设定类型为FUNCTION,回传框即可填写。
相关文章推荐
- Mysql Cookbook学习笔记第二章
- MySQL Cookbook 学习笔记-02
- MySQL CookBook 学习笔记-01
- MySQL CookBook 学习笔记-07排序查询结果
- MySQL CookBook 学习笔记-01
- MySQL Cookbook 学习笔记-03
- MySQL Cookbook学习笔记第一章
- MySQL Cookbook学习笔记第四章
- MySQL CookBook 学习笔记-12使用多重表
- javascript 学习笔记 《JavaScript And DHTML Cookbook》2
- python cookbook第三版学习笔记十六:抽象基类
- python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法
- python cookbook 学习笔记 -- 1.6 合并字符串
- python cookbook第三版学习笔记四:文本以及字符串令牌解析
- MySQL学习笔记-04_Server_Config
- oracle开发之<<SQL Cookbook>>学习笔记整理:第二章 查询结果排序
- python cookbook第三版学习笔记六:迭代器与生成器
- python cookbook 学习笔记 -- 1.8 检查字符串中是否包含某字符集合中的字符
- python cookbook第三版学习笔记十二:类和对象(三)创建新的类或实例属性
- MySQL学习笔记-04_Server_Config(mysqld --verbose --help)