MariaDB [test]> select * from productnotes; +---------+---------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ | note_id | prod_id | note_date | note_text | +---------+---------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ | 101 | TNT2 | 2005-08-17 00:00:00 | Customer complaint: Sticks not individually wrapped, too easy to mistakenly detonate all at once. Recommend individual wrapping. | | 102 | OL1 | 2005-08-18 00:00:00 | Can shipped full, refills not available. Need to order new can if refill needed. | | 103 | SAFE | 2005-08-18 00:00:00 | Safe is combination locked, combination not provided with safe. This is rarely a problem as safes are typically blown up or dropped by customers. | | 104 | FC | 2005-08-19 00:00:00 | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | | 105 | TNT2 | 2005-08-20 00:00:00 | Included fuses are short and have been known to detonate too quickly for some customers. Longer fuses are available (item FU1) and should be recommended. | | 106 | TNT2 | 2005-08-22 00:00:00 | Matches not included, recommend purchase of matches or detonator (item DTNTR). | | 107 | SAFE | 2005-08-23 00:00:00 | Please note that no returns will be accepted if safe opened using explosives. | | 108 | ANV01 | 2005-08-25 00:00:00 | Multiple customer returns, anvils failing to drop fast enough or falling backwards on purchaser. Recommend that customer considers using heavier anvils. | | 109 | ANV03 | 2005-09-01 00:00:00 | Item is extremely heavy. Designed for dropping, not recommended for use with slings, ropes, pulleys, or tightropes. | | 110 | FC | 2005-09-01 00:00:00 | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | | 111 | SLING | 2005-09-02 00:00:00 | Shipped unassembled, requires common tools (including oversized hammer). | | 112 | SAFE | 2005-09-02 00:00:00 | Customer complaint: Circular hole in safe floor can apparently be easily cut with handsaw. | | 113 | ANV01 | 2005-09-05 00:00:00 | Customer complaint: Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead. | | 114 | SAFE | 2005-09-07 00:00:00 | Call from individual trapped in safe plummeting to the ground, suggests an escape hatch be added. Comment forwarded to vendor. | +---------+---------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ 14 rows in set (0.00 sec)
MariaDB [test]> select note_text from productnotes where note_text regexp 'rabbit'; +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | +----------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
MariaDB [test]> select note_text from productnotes where match(note_text) against('rabbit'); +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | +----------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
MariaDB [test]> select note_text from productnotes where note_text like '%rabbit%'; +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | +----------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
这条 SELECT 语句同样检索出两行,但次序不同(虽然并不总是出现这种情况)。
上述两条 SELECT 语句都不包含 ORDER BY 子句。后者(使用 LIKE )以不特别有用的顺序返回数据。前者(使用全文本搜索)返回以文本匹配的良好程度排序的数据。两个行都包含词 rabbit ,但包含词 rabbit 作为第3个词的行的等级比作为第20个词的行高。这很重要。全文本搜索的一个重要部分就是对结果排序。具有较高等级的行先返回(因为这些行很可能是你真正想要的行)。
为演示排序如何工作,请看以下例子:
MariaDB [test]> select note_text,match(note_text) against('rabbit') as rank from productnotes; +-----------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ | note_text | rank | +-----------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ | Customer complaint: Sticks not individually wrapped, too easy to mistakenly detonate all at once. Recommend individual wrapping. | 0 | | Can shipped full, refills not available. Need to order new can if refill needed. | 0 | | Safe is combination locked, combination not provided with safe. This is rarely a problem as safes are typically blown up or dropped by customers. | 0 | | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | 1.5905543565750122 | | Included fuses are short and have been known to detonate too quickly for some customers. Longer fuses are available (item FU1) and should be recommended. | 0 | | Matches not included, recommend purchase of matches or detonator (item DTNTR). | 0 | | Please note that no returns will be accepted if safe opened using explosives. | 0 | | Multiple customer returns, anvils failing to drop fast enough or falling backwards on purchaser. Recommend that customer considers using heavier anvils. | 0 | | Item is extremely heavy. Designed for dropping, not recommended for use with slings, ropes, pulleys, or tightropes. | 0 | | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | 1.6408053636550903 | | Shipped unassembled, requires common tools (including oversized hammer). | 0 | | Customer complaint: Circular hole in safe floor can apparently be easily cut with handsaw. | 0 | | Customer complaint: Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead. | 0 | | Call from individual trapped in safe plummeting to the ground, suggests an escape hatch be added. Comment forwarded to vendor. | 0 | +-----------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ 14 rows in set (0.00 sec)
这里,在 SELECT 而不是 WHERE 子句中使用 Match() 和 Against() 。这使所有行都被返回(因为没有 WHERE 子句)。 Match() 和 Against()用来建立一个计算列(别名为 rank ),此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。正如所见,不包含词 rabbit 的行等级为0(因此不被前一例子中的 WHERE 子句选择)。确实包含词 rabbit的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的行的等级值高。
MariaDB [test]> select note_text from productnotes where match(note_text) against('anvils'); +----------------------------------------------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------------------------------------------+ | Multiple customer returns, anvils failing to drop fast enough or falling backwards on purchaser. Recommend that customer considers using heavier anvils. | +----------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
只有一行包含词 anvils ,因此只返回一行。
下面是相同的搜索,这次使用查询扩展:
MariaDB [test]> select note_text from productnotes where match(note_text) against('anvils' with query expansion); +----------------------------------------------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------------------------------------------+ | Multiple customer returns, anvils failing to drop fast enough or falling backwards on purchaser. Recommend that customer considers using heavier anvils. | | Customer complaint: Sticks not individually wrapped, too easy to mistakenly detonate all at once. Recommend individual wrapping. | | Customer complaint: Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead. | | Please note that no returns will be accepted if safe opened using explosives. | | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | | Customer complaint: Circular hole in safe floor can apparently be easily cut with handsaw. | | Matches not included, recommend purchase of matches or detonator (item DTNTR). | +----------------------------------------------------------------------------------------------------------------------------------------------------------+ 7 rows in set (0.00 sec)
MariaDB [test]> select note_text from productnotes where match(note_text) against('heavy' in boolean mode); +---------------------------------------------------------------------------------------------------------------------------------------------------------+ | note_text | +---------------------------------------------------------------------------------------------------------------------------------------------------------+ | Item is extremely heavy. Designed for dropping, not recommended for use with slings, ropes, pulleys, or tightropes. | | Customer complaint: Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead. | +---------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
此全文本搜索检索包含词 heavy 的所有行(有两行)。其中使用了关键字 IN BOOLEAN MODE ,但实际上没有指定布尔操作符,因此,其结果与没有指定布尔方式的结果相同。
IN BOOLEAN MODE 的行为差异 虽然这个例子的结果与没有IN BOOLEAN MODE 的相同,但其行为有一个重要的差别(即使在这个特殊的例子没有表现出来)。
为了匹配包含 heavy 但不包含任意以 rope 开始的词的行,可使用以下查询:
MariaDB [test]> select note_text from productnotes where match(note_text) against('heavy -rope*' in boolean mode); +---------------------------------------------------------------------------------------------------------------------------------------------------------+ | note_text | +---------------------------------------------------------------------------------------------------------------------------------------------------------+ | Customer complaint: Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead. | +---------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
MariaDB [test]> select note_text from productnotes where match(note_text) against('+rabbit +bait' in boolean mode); +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | +----------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
搜索匹配包含 rabbit 和 bait 中的至少一个词的行。
MariaDB [test]> select note_text from productnotes where match(note_text) against('rabbit bait' in boolean mode); +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | +----------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
搜索匹配短语 rabbit bait 而不是匹配两个词 rabbit 和 bait 。
MariaDB [test]> select note_text from productnotes where match(note_text) against('"rabbit bait"' in boolean mode); +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | +----------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
搜索匹配 rabbit 和 carrot ,增加前者的等级,降低后者的等级。
MariaDB [test]> select note_text from productnotes where match(note_text) against('>rabbit <carrot' in boolean mode); +----------------------------------------------------------------------------------------------------------------------+ | note_text | +----------------------------------------------------------------------------------------------------------------------+ | Quantity varies, sold by the sack load. All guaranteed to be bright and orange, and suitable for use as rabbit bait. | | Customer complaint: rabbit has been able to detect trap, food apparently less effective now. | +----------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)
搜索匹配词 safe 和 combination ,降低后者的等级。
MariaDB [test]> select note_text from productnotes where match(note_text) against('+safe +(<combination)' in boolean mode); +---------------------------------------------------------------------------------------------------------------------------------------------------+ | note_text | +---------------------------------------------------------------------------------------------------------------------------------------------------+ | Safe is combination locked, combination not provided with safe. This is rarely a problem as safes are typically blown up or dropped by customers. | +---------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
处理现有的表 在创建新表时,指定的表名必须不存在,否则将出错。如果要防止意外覆盖已有的表,SQL要求首先手工删除该表,然后再重建它,而不是简单地用创建表语句覆盖它。如果你仅想在一个表不存在时创建它,应该在表名后给出 IF NOT EXISTS 。这样做不检查已有表的模式是否与你打算创建的表模式相匹配。它只是查看表名是否存在,并且仅在表名不存在时创建它。
DROP TABLE IF EXISTS columns_priv; CREATE TABLE columns_priv ( Host char(60) COLLATE utf8_bin NOT NULL DEFAULT '', Db char(64) COLLATE utf8_bin NOT NULL DEFAULT '', User char(16) COLLATE utf8_bin NOT NULL DEFAULT '', Table_name char(64) COLLATE utf8_bin NOT NULL DEFAULT '', Column_name char(64) COLLATE utf8_bin NOT NULL DEFAULT '', Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges';
CREATE TABLE orderitems ( order_num int NOT NULL, order_item int NOT NULL, prod_id char(10) NOT NULL, quantity int NOT NULL, item_price decimal(8,2) NOT NULL, PRIMARY KEY (order_num,order_item), ) ENGINE=InnoDB;
CREATE TABLE orderitems ( order_num int NOT NULL, order_item int NOT NULL, prod_id char(10) NOT NULL, quantity int NOT NULL default 1, item_price decimal(8,2) NOT NULL, PRIMARY KEY (order_num,order_item), ) ENGINE=InnoDB;
MariaDB [test]> select * from customers; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | The Fudds | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | | 20001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 20002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 20003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 20004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 20005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 20006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 15 rows in set (0.00 sec)
MariaDB [test]> insert into customers values(null,'Pep E. Lapew','100 Main Street','Los Angeles','CA','90046','USA',null,null); Query OK, 1 row affected (0.02 sec)
MariaDB [test]> select * from customers; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 6 rows in set (0.00 sec)
MariaDB [test]> insert into customers(cust_name,cust_address,cust_city,cust_state,cust_zip,cust_country,cust_contact,cust_email) -> values (null,'Pep E. Lapew','100 Main Street','Los Angeles','CA','90046','USA',null,null);
MariaDB [test]> insert into customers(cust_contact,cust_email,cust_address,cust_city,cust_state,cust_zip,cust_country) -> values ('Pep E. Lapew',null,null,'100 Main Street','Los Angeles','CA','90046','USA');
MariaDB [test]> select * from customers; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+
MariaDB [test]> select * from custnew; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 8 rows in set (0.00 sec)
MariaDB [test]> select * from custnew; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 8 rows in set (0.00 sec)
MariaDB [test]> select * from custnew; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 20001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 20002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 20003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 20004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 20005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 20006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 8 rows in set (0.00 sec) # 将custnew表中的数据导入customers表
MariaDB [test]> select * from customers; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | | 20001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 20002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 20003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 20004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 20005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 20006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 16 rows in set (0.00 sec)
MariaDB [test]> delete from customers where cust_id = 10006; Query OK, 1 row affected (0.04 sec)
MariaDB [test]> select * from customers; +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | cust_id | cust_name | cust_address | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ | 10001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 10002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 10003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 10004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 10005 | The Fudds | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 10007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 10008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | | 20001 | Coyote Inc. | 200 Maple Lane | Detroit | MI | 44444 | USA | Y Lee | ylee@coyote.com | | 20002 | Mouse House | 333 Fromage Lane | Columbus | OH | 43333 | USA | Jerry Mouse | NULL | | 20003 | Wascals | 1 Sunny Place | Muncie | IN | 42222 | USA | Jim Jones | rabbit@wascally.com | | 20004 | Yosemite Place | 829 Riverside Drive | Phoenix | AZ | 88888 | USA | Y Sam | sam@yosemite.com | | 20005 | E Fudd | 4545 53rd Street | Chicago | IL | 54545 | USA | E Fudd | NULL | | 20006 | Pep E. Lapew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20007 | Pep E. LaPew | 100 Main Street | Los Angeles | CA | 90046 | USA | NULL | NULL | | 20008 | M. Martian | 42 Galaxy Way | New York | NY | 11213 | USA | NULL | NULL | +---------+----------------+---------------------+-------------+------------+----------+--------------+--------------+---------------------+ 15 rows in set (0.00 sec)
这条语句很容易理解。 DELETE FROM 要求指定从中删除数据的表名。WHERE 子句过滤要删除的行。在这个例子中,只删除客户 10006。如果省略 WHERE 子句,它将删除表中每个客户。
需要MySQL 5 MySQL 5添加了对视图的支持。因此,本章内容适用于MySQL 5及以后的版本。
视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。
理解视图的最好方法是看一个例子。用下面的 SELECT 语句从3个表中检索数据:
MariaDB [test]> select cust_name,cust_contact from customers,orders,orderitems -> where customers.cust_id=orders.cust_id and orderitems.order_num = orders.order_num -> and prod_id='TNT2'; +----------------+--------------+ | cust_name | cust_contact | +----------------+--------------+ | Coyote Inc. | Y Lee | | Yosemite Place | Y Sam | +----------------+--------------+ 2 rows in set (0.00 sec)
此查询用来检索订购了某个特定产品的客户。任何需要这个数据的人都必须理解相关表的结构,并且知道如何创建查询和对表进行联结。为了检索其他产品(或多个产品)的相同数据,必须修改最后的 WHERE 子句。
现在,假如可以把整个查询包装成一个名为 productcustomers 的虚 拟表,则可以如下轻松地检索出相同的数据:select cust_name,cust_contact from productcustomers where prod_id = 'TNT2';
创建一个名为 productcustomers 的视图,它联结三个表,以返回已订购了任意产品的所有客户的列表。如果执行SELECT * FROM productcustomers ,将列出订购了任意产品的客户。
MariaDB [test]> create view productcustomers as select cust_name,cust_contact,prod_id from customers,orders,orderitems where customers.cust_id=orders.cust_id and orderitems.order_num = orders.order_num ; Query OK, 0 rows affected (0.06 sec)
MariaDB [test]> select * from productcustomers; +----------------+--------------+---------+ | cust_name | cust_contact | prod_id | +----------------+--------------+---------+ | Coyote Inc. | Y Lee | ANV01 | | Coyote Inc. | Y Lee | ANV02 | | Coyote Inc. | Y Lee | TNT2 | | Coyote Inc. | Y Lee | FB | | Coyote Inc. | Y Lee | FB | | Coyote Inc. | Y Lee | OL1 | | Coyote Inc. | Y Lee | SLING | | Coyote Inc. | Y Lee | ANV03 | | Wascals | Jim Jones | JP2000 | | Yosemite Place | Y Sam | TNT2 | | The Fudds | E Fudd | FC | +----------------+--------------+---------+ 11 rows in set (0.00 sec)
检索订购了产品 TNT2 的客户
MariaDB [test]> select cust_name,cust_contact from productcustomers where prod_id='TNT2'; +----------------+--------------+ | cust_name | cust_contact | +----------------+--------------+ | Coyote Inc. | Y Lee | | Yosemite Place | Y Sam | +----------------+--------------+ 2 rows in set (0.00 sec)
这条语句通过 WHERE 子句从视图中检索特定数据。在MySQL处理此查询时,它将指定的 WHERE 子句添加到视图查询中的已有WHERE 子句中,以便正确过滤数据。
MariaDB [test]> create view customeremaillist as -> select cust_id,cust_name,cust_email -> from customers -> where cust_email is not null; Query OK, 0 rows affected (0.05 sec)
MariaDB [test]> select * from customeremaillist; +---------+----------------+---------------------+ | cust_id | cust_name | cust_email | +---------+----------------+---------------------+ | 10001 | Coyote Inc. | ylee@coyote.com | | 10003 | Wascals | rabbit@wascally.com | | 10004 | Yosemite Place | sam@yosemite.com | | 20001 | Coyote Inc. | ylee@coyote.com | | 20003 | Wascals | rabbit@wascally.com | | 20004 | Yosemite Place | sam@yosemite.com | +---------+----------------+---------------------+ 6 rows in set (0.00 sec)
在发送电子邮件到邮件列表时,需要排除没有电子邮件地址的用户。这里的 WHERE 子句过滤了 cust_email 列中具有NULL 值的那些行,使他们不被检索出来。
WHERE 子句与 WHERE 子句 如果从视图检索数据时使用了一条WHERE 子句,则两组子句(一组在视图中,另一组是传递给视图的)将自动组合。
MariaDB [test]> create procedure productpricing() begin select avg(prod_price) as priceaverage from products; end; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'end' at line 1
MariaDB [test]> delimiter // MariaDB [test]> create procedure productpricing() begin select avg(prod_price) as priceaverage from products; end // Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> delimiter ;
我们稍后介绍第一条和最后一条语句。此存储过程名为productpricing ,用 CREATE PROCEDURE productpricing() 语句定义。如果存储过程接受参数,它们将在 () 中列举出来。此存储过程没有参数,但后跟的 () 仍然需要。 BEGIN 和 END 语句用来限定存储过程体,过程体本身仅是一个简单的 SELECT 语句。
MariaDB [test]> delimiter // MariaDB [test]> create procedure productpricing(out pl decimal (8,2),out ph decimal(8,2),out pa decimal(8,2)) begin select min(prod_price) into pl from products;select max(prod_price) into ph from products;select avg(prod_price) into pa from products; end// Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> delimiter ;
此存储过程接受3个参数: pl 存储产品最低价格, ph 存储产品最高价格, pa 存储产品平均价格。每个参数必须具有指定的类型,这里使用十进制值。关键字 OUT 指出相应的参数用来从存储过程传出一个值(返回给调用者)。MySQL支持 IN (传递给存储过程)、 OUT (从存储过程传出,如这里所用)和 INOUT (对存储过程传入和传出)类型的参数。存储过程的代码位于 BEGIN 和 END 语句内,如前所见,它们是一系列SELECT 语句,用来检索值,然后保存到相应的变量(通过指定 INTO 关键字)。
MariaDB [test]> delimiter // MariaDB [test]> create procedure ordertotal( -> in onumber int, -> in taxable boolean, -> out ototal decimal(8,2)) comment 'Obtain order total, optionally adding tax' -> begin -> declare total decimal(8,2); -> declare taxrate int default 6; -> select sum(item_price*quantity) -> from orderitems -> where order_num = onumber -> into total; -> if taxable then -> select total+(total/100*taxrate) into total; -> end if; -> select total into ototal; -> end // Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> delimiter ;
[root@mastera0 ~]# vi procedure.mysql [root@mastera0 ~]# mysql -uroot -puplooking < procedure.mysql [root@mastera0 ~]# cat procedure.mysql use test; delimiter // create procedure ordertotal( in onumber int, in taxable boolean, out ototal decimal(8,2) )
begin declare total decimal(8,2); declare taxrate int default 6;
select sum(item_price*quantity) from orderitems where order_num = onumber into total;
if taxable then select total+(total/100*taxrate) into total; end if;
select total into ototal; end // delimiter ;
此存储过程有很大的变动。首先,增加了注释(前面放置 --)。在存储过程复杂性增加时,这样做特别重要。添加了另外一个参数 taxable ,它是一个布尔值(如果要增加税则为真,否则为假)。在存储过程体中,用 DECLARE语句定义了两个局部变量。 DECLARE 要求指定变量名和数据类型,它也支持可选的默认值(这个例子中的 taxrate 的默认被设置为 6% )。 SELECT 语句已经改变,因此其结果存储到 total (局部变量)而不是 ototal 。 IF 语句检查 taxable 是否为真,如果为真,则用另一 SELECT语句增加营业税到局部变量 total 。最后,用另一 SELECT 语句将total (它增加或许不增加营业税)保存到 ototal。
COMMENT 关键字 本例子中的存储过程在 CREATE PROCEDURE语句中包含了一个 COMMENT 值。它不是必需的,但如果给出,将在 SHOW PROCEDURE STATUS 的结果中显示。
IF 语句 这个例子给出了MySQL的 IF 语句的基本用法。 IF 语句还支持 ELSEIF 和 ELSE 子句(前者还使用 THEN 子句,后者不使用)。在以后章节中我们将会看到 IF 的其他用法(以及其他流控制语句)。
6.检查存储过程
为显示用来创建一个存储过程的 CREATE 语句,使用 SHOW CREATE PROCEDURE 语句:
MariaDB [test]> show create procedure ordertotal\G; *************************** 1. row *************************** Procedure: ordertotal sql_mode: Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `ordertotal`( in onumber int, in taxable boolean, out ototal decimal(8,2)) COMMENT 'Obtain order total, optionally adding tax' begin declare total decimal(8,2); declare taxrate int default 6; select sum(item_price*quantity) from orderitems where order_num = onumber into total; if taxable then select total+(total/100*taxrate) into total; end if; select total into ototal; end character_set_client: utf8 collation_connection: utf8_general_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec)
为了获得包括何时、由谁创建等详细信息的存储过程列表,使用 SHOWPROCEDURE STATUS 。
限制过程状态结果SHOW PROCEDURE STATUS列出所有存储过程。为限制其输出,可使用 LIKE 指定一个过滤模式,例如:show procedure status like 'ordertotal';
MariaDB [test]> delimiter // MariaDB [test]> create procedure processorders() begin declare o int;declare ordernumbers cursor for select order_num from orders; -> open ordernumbers; -> fetch ordernumbers into o; -> close ordernumbers; -> end // Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> delimiter ;
其中 FETCH用来检索当前行的 order_num 列(将自动从第一行开始)到一个名为 o 的局部声明的变量中。对检索出的数据不做任何处理。
在下一个例子中,循环检索数据,从第一行到最后一行:
MariaDB [test]> delimiter // MariaDB [test]> create procedure processorders() begin declare done boolean default 0;declare o int;declare ordernumbers cursor for select order_num from orders;declare continue handler for sqlstate '02000' set done=1; open ordernumbers;repeat fetch ordernumbers into o;until done end repeat; close ordernumbers; end// Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> delimiter ;
与前一个例子一样,这个例子使用 FETCH检索当前 order_num到声明的名为 o 的变量中。但与前一个例子不一样的是,这个例子中的 FETCH 是在 REPEAT 内,因此它反复执行直到 done 为真(由 UNTIL done END REPEAT; 规定)。
MariaDB [test]> delimiter // MariaDB [test]> create procedure processorders() begin declare done boolean default 0;declare o int;declare t decimal(8,2);declare ordernumbers cursor for select order_num from orders;declare continue handler for sqlstate '02000' set done=1; create table if not exists ordertotals (order_num int,total decimal(8,2)); open ordernumbers;repeat fetch ordernumbers into o;call ordertotal(o,1,t);insert into ordertotals(order_num,total) values (o,t);until done end repeat; close ordernumbers; end// Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> delimiter ;
在这个例子中,我们增加了另一个名为 t 的变量(存储每个订单的合计)。此存储过程还在运行中创建了一个新表(如果它不存在的话),名为 ordertotals 。这个表将保存存储过程生成的结果。 FETCH像以前一样取每个 order_num ,然后用 CALL执行另一个存储过程(我们在前一章中创建)来计算每个订单的带税的合计(结果存储到 t )。最后,用 INSERT 保存每个订单的订单号和合计。
BEFORE 或 AFTER ? 通常,将 BEFORE 用于数据验证和净化(目的是保证插入表中的数据确实是需要的数据)。本提示也适用于 UPDATE 触发器。
2.DELETE 触发器
DELETE 触发器在 DELETE 语句执行之前或之后执行。需要知道以下两点:
在 DELETE 触发器代码内,你可以引用一个名为 OLD 的虚拟表,访问被删除的行;
OLD 中的值全都是只读的,不能更新。
下面的例子演示使用 OLD 保存将要被删除的行到一个存档表中:
MariaDB [test]> delimiter //
MariaDB [test]> create trigger deleteorder before delete on orders for each row begin insert into archive_orders(order_num,order_date,cust_id) values (OLD.order_num,OLD.order_date,OLD.cust_id); end// Query OK, 0 rows affected (0.07 sec)
MariaDB [test]> delimiter ;
在任意订单被删除前将执行此触发器。它使用一条 INSERT语句将 OLD 中的值(要被删除的订单)保存到一个名为 archive_orders 的存档表中(为实际使用这个例子,你需要用与 orders 相同的列创建一个名为 archive_orders 的表)。
使用 BEFORE DELETE 触发器的优点(相对于 AFTER DELETE 触发器来说)为,如果由于某种原因,订单不能存档, DELETE 本身将被放弃。
多语句触发器 正如所见,触发器 deleteorder 使用 BEGIN 和END 语句标记触发器体。这在此例子中并不是必需的,不过也没有害处。使用 BEGIN END 块的好处是触发器能容纳多条SQL语句(在 BEGIN END块 中一条挨着一条)。
3.UPDATE 触发器
UPDATE 触发器在 UPDATE 语句执行之前或之后执行。需要知道以下几点:
在 UPDATE 触发器代码中,你可以引用一个名为 OLD 的虚拟表访问以前( UPDATE 语句前)的值,引用一个名为 NEW 的虚拟表访问新更新的值;
在 BEFORE UPDATE 触发器中, NEW 中的值可能也被更新(允许更改将要用于 UPDATE 语句中的值);
MariaDB [test]> create trigger updatevendor before update on vendors for each row set New.vend_state = Upper(new.vend_state); Query OK, 0 rows affected (0.35 sec)
MariaDB [test]> show variables like '%autocommit%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec)
MariaDB [test]> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+ 1 row in set (0.00 sec)
校对为什么重要 排序英文正文很容易,对吗?或许不。考虑词APE、apex和Apple。它们处于正确的排序顺序吗?这有赖于你是否想区分大小写。使用区分大小写的校对顺序,这些词有一种排序方式,使用不区分大小写的校对顺序有另外一种排序方式。这不仅影响排序(如用 ORDER BY 排序数据),还影响搜索(例如,寻找apple的WHERE子句是否能找到APPLE)。在使用诸如法文à或德文ö这样的字符时,情况更复杂,在使用不基于拉丁文的字符集(日文、希伯来文、俄文等)时,情况更为复杂。
MariaDB [test]> select * from db1.t2; +------+ | name | +------+ | a | | b | | A | | B | +------+ 4 rows in set (0.00 sec)
MariaDB [test]> select * from db1.t2 order by name collate latin1_general_cs; +------+ | name | +------+ | A | | a | | B | | b | +------+ 4 rows in set (0.00 sec)
MariaDB [test]> select * from db1.t2 order by name; +------+ | name | +------+ | a | | A | | b | | B | +------+ 4 rows in set (0.00 sec)
MySQL用户账号和信息存储在名为 mysql 的MySQL数据库中。一般不需要直接访问 mysql 数据库和表(你稍后会明白这一点),但有时需要直接访问。需要直接访问它的时机之一是在需要获得所有用户账号列表时。为此,可使用以下代码:
MariaDB [test]> use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A
Database changed MariaDB [mysql]> select user from user; +------+ | user | +------+ | root | | root | | root | | | | root | | | | root | +------+ 7 rows in set (0.00 sec)
mysql 数据库有一个名为 user 的表,它包含所有用户账号。 user表有一个名为 user 的列,它存储用户登录名。新安装的服务器可能只有一个用户(如这里所示),过去建立的服务器可能具有很多用户。
用多个客户机进行试验 试验对用户账号和权限进行更改的最好办法是打开多个数据库客户机(如 mysql 命令行实用程序的多个副本),一个作为管理登录,其他作为被测试的用户登录。
1.创建用户账号
为了创建一个新用户账号,使用 CREATE USER 语句,如下所示:
MariaDB [mysql]> create user superman identified by 'p@$$w0rd'; Query OK, 0 rows affected (0.00 sec)
CREATE USER 创建一个新用户账号。在创建用户账号时不一定需要口令,不过这个例子用 IDENTIFIED BY 'p@$$wOrd' 给出了一个口令。
如果你再次列出用户账号,将会在输出中看到新账号。指定散列口令 IDENTIFIED BY 指定的口令为纯文本, MySQL将在保存到 user 表之前对其进行加密。为了作为散列值指定口令,使用 IDENTIFIED BY PASSWORD 。
使用 GRANT 或 INSERT GRANT 语句(稍后介绍)也可以创建用户账号,但一般来说 CREATE USER 是最清楚和最简单的句子。此外,也可以通过直接插入行到 user 表来增加用户,不过为安全起见,一般不建议这样做。MySQL用来存储用户账号信息的表(以及表模式等)极为重要,对它们的任何毁坏都可能严重地伤害到MySQL服务器。因此,相对于直接处理来说,最好是用标记和函数来处理这些表。
为重新命名一个用户账号,使用 RENAME USER 语句,如下所示:
MariaDB [mysql]> rename user superman@'%' to batman; Query OK, 0 rows affected (0.00 sec) MariaDB [mysql]> rename user batman@'%' to superman@'%'; Query OK, 0 rows affected (0.00 sec)
MySQL 5之前 仅MySQL 5或之后的版本支持 RENAME USER 。为了在以前的MySQL中重命名一个用户,可使用 UPDATE直接更新 user 表。
2.删除用户账号
为了删除一个用户账号(以及相关的权限),使用 DROP USER 语句,如下所示:
MariaDB [mysql]> drop user superman; Query OK, 0 rows affected (0.00 sec)
MySQL 5之前 自MySQL 5以来, DROP USER 删除用户账号和所有相关的账号权限。在MySQL 5以前, DROP USER 只能用来删除用户账号,不能删除相关的权限。因此,如果使用旧版本的MySQL,需要先用 REVOKE 删除与账号相关的权限,然后再用 DROP USER 删除账号。
MariaDB [mysql]> show grants for 'wonderwoman'@'172.25.0.12'; +---------------------------------------------------+ | Grants for wonderwoman@172.25.0.12 | +---------------------------------------------------+ | GRANT USAGE ON *.* TO 'wonderwoman'@'172.25.0.12' | +---------------------------------------------------+ 1 row in set (0.00 sec)
输出结果显示用户 wonderwoman 有一个权限 USAGE ON *.* 。USAGE 表示根本没有权限(我知道,这不很直观),所以,此结果表示在任意数据库和任意表上对任何东西没有权限。
MariaDB [mysql]> grant select on db1.* to 'wonderwoman'@'172.25.0.12'; Query OK, 0 rows affected (0.00 sec)
MariaDB [mysql]> show grants for 'wonderwoman'@'172.25.0.12'; +--------------------------------------------------------+ | Grants for wonderwoman@172.25.0.12 | +--------------------------------------------------------+ | GRANT USAGE ON *.* TO 'wonderwoman'@'172.25.0.12' | | GRANT SELECT ON `db1`.* TO 'wonderwoman'@'172.25.0.12' | +--------------------------------------------------------+ 2 rows in set (0.00 sec)
MariaDB [mysql]> revoke select on db1.* from 'wonderwoman'@'172.25.0.12'; Query OK, 0 rows affected (0.00 sec)
MariaDB [mysql]> show grants for 'wonderwoman'@'172.25.0.12'; +---------------------------------------------------+ | Grants for wonderwoman@172.25.0.12 | +---------------------------------------------------+ | GRANT USAGE ON *.* TO 'wonderwoman'@'172.25.0.12' | +---------------------------------------------------+ 1 row in set (0.00 sec)
MariaDB [mysql]> set password for bforta = password('uplooking'); Query OK, 0 rows affected (0.00 sec)
SET PASSWORD 更新用户口令。新口令必须传递到 Password() 函数进行加密。
SET PASSWORD 还可以用来设置你自己的口令:set password = password('uplooking');
在不指定用户名时, SET PASSWORD 更新当前登录用户的口令。
小结
本章学习了通过赋予用户特殊的权限进行访问控制和保护MySQL服务器。
其他
MySQL语句的语法
通过帮助可以查看mysql的语法
MariaDB [mysql]> help;
General information about MariaDB can be found at http://mariadb.org
List of all MySQL commands: Note that all text commands must be first on line and end with ';' ? (\?) Synonym for `help'. clear (\c) Clear the current input statement. connect (\r) Reconnect to the server. Optional arguments are db and host. delimiter (\d) Set statement delimiter. edit (\e) Edit command with $EDITOR. ego (\G) Send command to mysql server, display result vertically. exit (\q) Exit mysql. Same as quit. go (\g) Send command to mysql server. help (\h) Display this help. nopager (\n) Disable pager, print to stdout. notee (\t) Don't write into outfile. pager (\P) Set PAGER [to_pager]. Print the query results via PAGER. print (\p) Print current command. prompt (\R) Change your mysql prompt. quit (\q) Quit mysql. rehash (#) Rebuild completion hash. rehash (#) Rebuild completion hash. source (\.) Execute an SQL script file. Takes a file name as an argument. status (\s) Get status information from the server. system (\!) Execute a system shell command. tee (\T) Set outfile [to_outfile]. Append everything into given outfile. use (\u) Use another database. Takes database name as argument. charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets. warnings (\W) Show warnings after every statement. nowarning (\w) Don't show warnings after every statement.
For server side help, type 'help contents'
查看create和create database的帮助
MariaDB [mysql]> help create; Many help items for your request exist. To make a more specific request, please type 'help <item>', where <item> is one of the following topics: CREATE DATABASE CREATE EVENT CREATE FUNCTION CREATE FUNCTION UDF CREATE INDEX CREATE PROCEDURE CREATE SERVER CREATE TABLE CREATE TABLESPACE CREATE TRIGGER CREATE USER CREATE VIEW SHOW SHOW CREATE DATABASE SHOW CREATE EVENT SHOW CREATE FUNCTION SHOW CREATE PROCEDURE SHOW CREATE TABLE SPATIAL
MariaDB [mysql]> help create database; Name: 'CREATE DATABASE' Description: Syntax: CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [create_specification] ...
create_specification: [DEFAULT] CHARACTER SET [=] charset_name | [DEFAULT] COLLATE [=] collation_name
CREATE DATABASE creates a database with the given name. To use this statement, you need the CREATE privilege for the database. CREATE SCHEMA is a synonym for CREATE DATABASE.
create database [dbname]; drop database [dbname]; create table [tbname] (col1 type,col2 type,col3....); drop table [tbname];
DML 数据库操作语言 insert into\delete from\update insert into [tbname] set col1=value,col2=value,col3=value; insert into [tbname] values (1,'booboo'),(2,'batman'),(3,'superman'); insert into [tbname] (name,id) values (); delete from [tbname] where id=1 and name='booboo'; update [tbname] set col='superman' where id=2;
DCL 数据库控制语言 grant revoke 认证 + 授权 grant all on *.* to booboo@'172.25.0.11' identified by 'uplooking'; all 权限 *.* 库.表 flush privileges; 刷新授权表 revoke [权限] on [库].[表] from booboo@'172.25.0.11';
DQL 数据库查询语言 show databases; use mysql; show tables; desc mysql.user; select * from db1.t1;
定长串接受长度固定的字符串,其长度是在创建表时指定的。例如,名字列可允许30个字符,而社会安全号列允许11个字符(允许的字符数目中包括两个破折号)。定长列不允许多于指定的字符数目。它们分配的存储空间与指定的一样多。因此,如果串 Ben 存储到30个字符的名字字段,则存储的是30个字符, CHAR 属于定长串类型。
变长串存储可变长度的文本。有些变长数据类型具有最大的定长,而有些则是完全变长的。不管是哪种,只有指定的数据得到保存(额外的数据不保存) TEXT 属于变长串类型。
MariaDB [mysql]> delete from mysql.user where user=' ' or password=' '; Query OK, 5 rows affected (0.00 sec)
MariaDB [mysql]> select host,user,password from mysql.user; +-----------+------+-------------------------------------------+ | host | user | password | +-----------+------+-------------------------------------------+ | localhost | root | *6FF883623B8639D08083FF411D20E6856EB7D2BF | +-----------+------+-------------------------------------------+ 1 row in set (0.00 sec)
实战项目3:完成数据库用户权限操作项目
要求:添加授权用户测试客户机优先使用的哪个密码(X为学生机号)
user1@’172.25.X.%’ uplooking
user1@’172.25.X.12’ uplooking123
# mastera:
MariaDB [mysql]> grant all on *.* to user1@"172.25.0.%" identified by "uplooking"; Query OK, 0 rows affected (0.00 sec) MariaDB [mysql]> grant all on *.* to user1@"172.25.0.12" identified by "uplooking123"; Query OK, 0 rows affected (0.00 sec) MariaDB [mysql]> flush privileges; Query OK, 0 rows affected (0.01 sec) MariaDB [mysql]> \q Bye # masterb: # 第一次输入密码为: uplooking [root@serverb ~]# mysql -uuser1 -h172.25.0.11 -p'uplooking' ERROR 1045 (28000): Access denied for user 'user1'@'mastera0.example.com' (using password:YES) #第二次输入密码为:uplooking123 [root@serverb ~]# mysql -uuser1 -h172.25.0.11 -p'uplooking123' Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 7 Server version: 5.5.41-MariaDB MariaDB Server Copyright (c) 2000, 2014, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>
实验结论:uplooking2 密码进去了 授权越精确越优先
实战项目4: 破解 MariaDB 5.5 的 root 密码
停止服务 systemctl stop mariadb
跳过授权表启动服务 mysqld_safe --skip-grant-tables &
修改root密码 update mysql.user set password=password('uplooking') where user='root';
停止跳过授权表启动服务 kill -9
启动服务 systemctl start mariadb
# rhel7 mariadb5.5 [root@serverg ~]# systemctl stop mariadb [root@serverg ~]# mysqld_safe --skip-grant-tables & [1] 3078 [root@serverg ~]# 160304 18:36:15 mysqld_safe Logging to '/var/log/mariadb/mariadb.log'. 160304 18:36:15 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql [root@serverg ~]# mysql -uxxx Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 1 Server version: 5.5.41-MariaDB MariaDB Server Copyright (c) 2000, 2014, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed MariaDB [mysql]> update user set password=password("redhat") where user="root" and host="localhost"; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [mysql]> \q Bye [root@serverg ~]# ps -ef |grep mysql mysql 3221 1 0 18:36 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --skip-grant-tables --log- error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock root 3287 3256 0 18:40 pts/0 00:00:00 grep --color=auto mysql [root@serverg ~]# kill -9 3221 [root@serverg ~]# systemctl start mariadb [root@serverg ~]# mysql -uroot -predhat Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 3 Server version: 5.5.41-MariaDB MariaDB Server Copyright (c) 2000, 2014, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>