zoukankan      html  css  js  c++  java
  • 《MySQL必知必会》笔记(SQL练习+建表语句)

    站在巨人的肩上
    Standing On Shoulders Of Giants
    部分转自:https://www.jianshu.com/p/294502893128
    https://blog.csdn.net/qq_33704186/article/details/81909168


    大概目录:
    1.SQL语句学习
    2.本书练习SQL案例
    3.类似Oracle中的经典SQL练习案例


    《MySQL必知必会》学习笔记
    后面有联系SQL建表语句
    学习MySQL, 便把书本中的代码练习了一遍, 以此文留个记录(图片引自豆瓣),
    此书配套资料在http://forta.com/books/0672327120/网站下载





    目录 · · · · · ·
    第1章 了解SQL
    第2章 MySQL简介
    ...
    ...
    第21章 创建和操纵表
    第22章 使用视图
    第23章 使用存储过程
    第24章 使用游标
    第25章 使用触发器
    第26章 管理事务处理
    第27章 全球化和本地化
    第28章 安全管理
    第29章 数据库维护
    第30章 改善性能
    《MySQL必知必会》SQL文件

    第3章 使用MySQL

    # 使用指定的数据库
    use mysql_need_know;
    
    # 显示所有的数据库
    show databases;
    
    # 显示所有数据库中的所有表
    show tables;
    
    # 显示指定表的所有列信息
    show columns from customers;
    desc customers;
    describe customers;
    
    # 显示mysql服务状态信息
    show status;
    
    # 显示指定的数据库或者数据表的创建SQL语句
    SHOW CREATE DATABASE mysql_need_know;
    SHOW CREATE TABLE customers;
    
    # 显示授予用户的安全权限
    SHOW GRANTS;
    
    # 显示错误信息
    SHOW ERRORS;
    
    # 显示警告信息
    SHOW WARNINGs;
    

    第4章 检索数据

     # 从指定表中查询所有的列的信息
    SELECT prod_name FROM products;
    
    # 从指定表中查询指定列的信息
    SELECT prod_name FROM products;
    
    # 从指定表中查询多个列的信息
    SELECT prod_id, prod_name, prod_price FROM products;
    
    # 去重(会应用于所有的列, 而不是只有第一列)
    SELECT DISTINCT vend_id, prod_price FROM products;
    
    # 限制查询返回的行数(一个参数为返回的行数)
    SELECT prod_name FROM products LIMIT 5;
    # 限制查询返回的行数(二个参数中第一个为跳过的行数, 第二个参数为要显示的行数)
    SELECT prod_name FROM products LIMIT 5, 5;
    # 从第0行开始取5行返回, 和上面的语句相反
    SELECT prod_name FROM products LIMIT 5 OFFSET 0;
    
    # 全限定表名和列名
    SELECT products.prod_name FROM mysql_need_know.products;
    

    第5章 排序检索数据

    # 排序(默认正序)
    SELECT prod_name FROM products ORDER BY prod_name;
    # 正序
    SELECT prod_name FROM products ORDER BY prod_name ASC;
    # 逆序
    SELECT prod_name FROM products ORDER BY prod_name DESC;
    # 只对其前面的列名排序
    SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name;
    
    
    # 多列排序,会按列的顺序排,先排价格,如果有价格相同的行,这些行再按姓名排
    SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name;
    
    
    # 限制和排序结合,找出指定列的最大值和最小值(LIMIT要在ORDER BY子句之后)
    SELECT prod_price FROM products ORDER BY prod_price LIMIT 1;
    SELECT prod_price FROM products ORDER BY prod_price DESC LIMIT 1;
    

    第6章 过滤数据

    SELECT prod_name, prod_price FROM products WHERE prod_price = 2.50;
    
    # WHERE 子句操作符 =, !=, <>, <, <=, >, >=, BETWEEN a AND b (包含a和b)
    # 大小写不区分(字符串要用小括号括起来)
    SELECT prod_name, prod_price FROM products WHERE prod_name = 'fuses';
    
    # 检测指定列是否包含null值
    SELECT prod_name FROM products WHERE prod_price IS NULL;
    SELECT cust_id FROM customers WHERE cust_email IS NULL;
    

    第7章 数据过滤

    # 多条件WHERE过滤
    # AND
    SELECT prod_id, prod_price, prod_name FROM products WHERE vend_id = 1003 AND prod_price <= 10;
    
    # OR 
    SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003;
    
    # 组合OR和AND(下面是错误的组合方法,AND的优先级比OR要高)
    SELECT prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10;
    
    # 组合OR和AND(使用括号提升包含OR的筛选条件的优先级)
    SELECT prod_name, prod_price FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
    
    # IN 指定条件范围
    SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id IN (1002, 1003) ORDER BY prod_name;
    # 使用OR和上面用IN的效果一样,但是IN更快
    SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003;
    # NOT 否定后面跟的条件
    SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id NOT IN (1002, 1003) ORDER BY prod_name;
    

    第8章 用通配符进行过滤

    # 通配符 % 表示任何字符出现任何次数(当前是不区分大小写的,可以配置区分大小写)
    SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%';
    # 使用多个通配符
    SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '%anvil%';
    
    SELECT prod_name FROM products WHERE prod_name LIKE 's%e';
    
    # 注意,用%不能匹配null
    
    # 下划线(_)匹配一个字符
    SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil';
    

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

    # 在子句中使用正则匹配
    SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORDER BY prod_name;
    
    # 使用.匹配任意一个字符
    SELECT prod_name FROM products WHERE prod_name REGEXP '.000' ORDER BY prod_name;
    # 区分大小写
    SELECT prod_name FROM products WHERE prod_name REGEXP BINARY 'Jet' ORDER BY prod_name;
    # 匹配两个串(类似OR的功能)
    SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000' ORDER BY prod_name;
    # 匹配一组字符
    SELECT prod_name FROM products WHERE prod_name REGEXP '[123] Ton' ORDER BY prod_name;
    
    # 错误的匹配,这等于匹配 1 或者 2 或者 3 Ton
    SELECT prod_name FROM products WHERE prod_name REGEXP '1|2|3 Ton' ORDER BY prod_name;
    # 否匹配
    SELECT prod_name FROM products WHERE prod_name REGEXP '[^123] Ton' ORDER BY prod_name;
    # 匹配范围
    SELECT prod_name FROM products WHERE prod_name REGEXP '[1-5] Ton' ORDER BY prod_name;
    # 匹配特殊字符(在特殊字符前加双斜杠(\))
    SELECT vend_name FROM vendors WHERE vend_name REGEXP '\.' ORDER BY vend_name;
    
    #匹配字符类(预定义的字符集)
    # 任意字母或者数字
    SELECT vend_name FROM vendors WHERE vend_name REGEXP '[[:alnum:]]' ORDER BY vend_name;
    #任意字符
    SELECT vend_name FROM vendors WHERE vend_name REGEXP '[[:alpha:]]' ORDER BY vend_name;
    #任意数字
    SELECT vend_name FROM vendors WHERE vend_name REGEXP '[[:digit:]]' ORDER BY vend_name;
    #任意小写字母
    SELECT vend_name FROM vendors WHERE vend_name REGEXP '[[:lower:]]' ORDER BY vend_name;
    #任意大写字母
    SELECT vend_name FROM vendors WHERE vend_name REGEXP '[[:upper:]]' ORDER BY vend_name;
    
    SELECT prod_name FROM products WHERE prod_name REGEXP '\([0-9] sticks?\)' ORDER BY prod_name;
    
    # 匹配连在一起的4位数字
    SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]{4}' ORDER BY prod_name;
    
    # 使用定位符 匹配以数字或者.开关的所有产品
    SELECT prod_name FROM products WHERE prod_name REGEXP '^[0-9\.]' ORDER BY prod_name;
    
    
    # 不使用数据库检测正则
    SELECT 'hello1' REGEXP '[0-9]';
    

    第10章 创建计算字段

    # 使用concat()函数拼接列
    SELECT CONCAT(vend_name, ' (', vend_country, ')') AS vend_title FROM vendors ORDER BY vend_name;
    
    # 使用RTRIM()函数来删除字段右边的空格
    SELECT CONCAT(RTRIM(vend_name), '(', RTRIM(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
    
    # 查询指定订单号的物品项并计算每项的总价
    SELECT
        prod_id,
        quantity,
        item_price,
        quantity * item_price AS expanded_price
    FROM
        orderitems 
    WHERE
        order_num = 20005;
    
    # 常用检测方法
    SELECT 3 * 2;
    SELECT TRIM('abc');
    SELECT NOW();
    

    第11章 使用数据处理函数

    # 转换大小写函数
    SELECT vend_name, UPPER(vend_name) AS vend_name_upcase FROM vendors ORDER BY vend_name;
    SELECT vend_name, LOWER(vend_name) AS vend_name_lower FROM vendors ORDER BY vend_name;
    
    # 返回串左边和返回串右边指定位数的字符
    SELECT vend_name, LEFT(vend_name, 5) AS vend_name_left FROM vendors ORDER BY vend_name;
    SELECT vend_name, RIGHT(vend_name, 5) AS vend_name_right FROM vendors ORDER BY vend_name;
    
    # 返回串的长度
    SELECT vend_name, LENGTH(vend_name) AS vend_name_length FROM vendors ORDER BY vend_name;
    
    # 返回串的子串第一次出现的位置
    SELECT vend_name, LOCATE('A', vend_name) AS vend_name_locate FROM vendors ORDER BY vend_name;
    
    # 返回子串的字符(截取子串)
    SELECT vend_name, SUBSTRING(vend_name, 1, 5) AS vend_name_locate FROM vendors ORDER BY vend_name;
    
    # 返回串的SOUNDEX值
    SELECT vend_name, SOUNDEX(vend_name) AS vend_name_locate FROM vendors ORDER BY vend_name;
    # 发音相近匹配
    SELECT cust_name, cust_contact FROM customers WHERE SOUNDEX(cust_contact) = SOUNDEX('Y. Lie');
    
    
    SELECT CURDATE(); # 当前日期
    SELECT CURTIME(); # 当前时间
    
    SELECT DATEDIFF('2018-10-10', "2018-10-11"); # 比较日期(计算日期差值)
    SELECT ADDDATE(NOW(), 10); # 给指定的日期增加指定的天数
    SELECT OrderId,DATEADD(day,2,OrderDate) AS OrderPayDate FROM Orders # 向OrderDate增加2天
    SELECT DATE_ADD(NOW(), INTERVAL 60 SECOND) # 高精度增加时间
    SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%S'); # 使用指定格式格式化日期
    SELECT DATE('2018-10-10 12:12'); # 截取日期部分
    SELECT TIME('2018-10-10 12:12:12'); #返回日期的时间部分
    SELECT YEAR('2018-10-10 12:12:12'); #返回日期的年份部分
    SELECT MONTH('2018-10-10 12:12:12'); #返回日期的月份部分
    SELECT DAY('2018-10-10 12:12:12'); #返回日期的天数部分
    SELECT HOUR('2018-10-10 12:12:12'); #返回日期的时针部分
    SELECT MINUTE('2018-10-10 12:12:12'); #返回日期的分针部分
    SELECT SECOND('2018-10-10 12:12:12'); #返回日期的秒部分
    
    # 根据日期筛选
    SELECT cust_id, order_num FROM orders WHERE order_date = '2005-09-01';
    # 更可靠的根据日期筛选
    SELECT cust_id, order_num FROM orders WHERE DATE(order_date) = '2005-09-01';
    # 筛选一个日期范围内的结果
    SELECT cust_id, order_num FROM orders WHERE DATE(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
    # 更可靠的日期范围筛选
    SELECT cust_id, order_num FROM orders WHERE Year(order_date) = 2005 AND Month(order_date) = 9;
    
    # 返回0-1之间不包括1的随机数
    SELECT RAND();
    
    

    第12章 汇总数据

    # 返回指定列的平均值
    SELECT AVG(prod_price) AS avg_price FROM products;
    # 返回指定列符合条件的行的平均值
    SELECT AVG(prod_price) AS avg_price FROM products WHERE vend_id = 1003;
    
    # 计算指定表的行数(包括null值行)
    SELECT COUNT(*) AS num_cust FROM customers;
    
    # 计算指定列的行数(不包括null值行)
    SELECT COUNT(cust_email) AS num_cust FROM customers;
    
    # 返回指定列的最大值(忽略null值)
    SELECT MAX(prod_price) AS max_price FROM products;
    
    # 返回指定列的最小值(忽略null值)
    SELECT MIN(prod_price) AS min_price FROM products;
    
    # 对指定列求合
    SELECT SUM(quantity) AS items_ordered FROM orderitems WHERE order_num = 20005;
    # 在求全函数中计算
    SELECT SUM(quantity*item_price) AS total_price FROM orderitems WHERE order_num = 20005;
    
    # 在函数中使用DISTINCT
    SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id = 1003;
    
    # 使用多个函数
    SELECT
        COUNT( * ) AS num_items,
        MIN( prod_price ) AS price_min,
        MAX( prod_price ) AS price_max,
        AVG( prod_price ) AS price_avg 
    FROM
        products;
    

    第13章 分组数据

    # 使用分组计算所有供应商对应都有几个产品
    SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id;
    
    -- 在具体使用 GROUP BY 子句前,需要知道一些重要的规定。
    --  GROUP BY 子句可以包含任意数目的列。这使得能对分组进行嵌套,
    -- 为数据分组提供更细致的控制。
    --  如果在 GROUP BY 子句中嵌套了分组,数据将在最后规定的分组上
    -- 进行汇总。换句话说,在建立分组时,指定的所有列都一起计算
    -- (所以不能从个别的列取回数据)。
    --  GROUP BY 子句中列出的每个列都必须是检索列或有效的表达式
    -- (但不能是聚集函数)。如果在 SELECT 中使用表达式,则必须在
    -- GROUP BY 子句中指定相同的表达式。不能使用别名。
    --  除聚集计算语句外, SELECT 语句中的每个列都必须在 GROUP BY 子
    -- 句中给出。
    --  如果分组列中具有 NULL 值,则 NULL 将作为一个分组返回。如果列
    -- 中有多行 NULL 值,它们将分为一组。
    --  GROUP BY 子句必须出现在 WHERE 子句之后, ORDER BY 子句之前
    
    # 对分组汇总
    SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id WITH ROLLUP;
    
    # 使用HAVING过滤分组
    SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2;
    
    # 查询出具有2个或以上,价格为10或以上产品的供应商
    SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2;
    
    SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id HAVING COUNT(*) >= 2;
    
    # GROUP BY 和 ORDER BY 结合使用
    SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50 ORDER BY ordertotal;
    
    
    # SELECT子句的顺序
    SELECT > FROM > WHERE > GROUP BY > HAVING > ORDER BY > LIMIT;
    

    第14章 使用子查询

    # 列出订购物品 TNT2 的所有客户
    -- 方式一:分条查询
    SELECT order_num FROM orderitems WHERE prod_id = 'TNT2';
    SELECT cust_id FROM orders WHERE order_num IN (20005, 20007);
    
    -- 方法二:子查询
    SELECT cust_name, cust_contact FROM customers WHERE cust_id IN (
            SELECT cust_id FROM orders WHERE    order_num IN ( 
                        SELECT order_num FROM orderitems WHERE prod_id = 'TNT2'));
    
    
    # 计算字段中使用子查询
    SELECT
        cust_name,
        cust_state,
        ( SELECT COUNT( * ) FROM orders WHERE orders.cust_id = customers.cust_id ) AS orders 
    FROM
        customers 
    ORDER BY
        cust_name;
    

    第15章 联结表

    # 联结查询(等值联结果或者内部连接)
    SELECT
        vend_name,
        prod_name,
        prod_price 
    FROM
        vendors,
        products 
    WHERE
        vendors.vend_id = products.vend_id 
    ORDER BY
        vend_name,
        prod_name;
        
    # 内部连接的另一种更明确的写法
    SELECT vend_name, prod_name, prod_price FROM vendors INNER JOIN products ON vendors.vend_id = products.vend_id;
    
    
    # 同时连接多个表
    SELECT
        prod_name,
        vend_name,
        prod_price,
        quantity 
    FROM
        orderitems,
        products,
        vendors 
    WHERE
        products.vend_id = vendors.vend_id 
        AND orderitems.prod_id = products.prod_id 
        AND order_num = 20005;
    

    第16章 创建高级联结

    # 在连接查询中使用别名
    SELECT
        cust_name,
        cust_contact 
    FROM
        customers AS c,
        orders AS o,
        orderitems AS oi 
    WHERE
        c.cust_id = o.cust_id 
        AND oi.order_num = o.order_num 
        AND prod_id = 'TNT2';
    
    # 自连接
    SELECT p1.prod_id, p1.prod_name
    FROM products AS p1, products AS p2
    WHERE p1.vend_id = p2.vend_id
    AND p2.prod_id = 'DTNTR';
    
    # 自然连接 排除多次出现,使每个列只返回一次 (一般内部连接都是自然连接)
    SELECT
        c.*,
        o.order_num,
        o.order_date,
        oi.prod_id,
        oi.quantity,
        oi.item_price 
    FROM
        customers AS c,
        orders AS o,
        orderitems AS oi 
    WHERE
        c.cust_id = o.cust_id 
        AND oi.order_num = o.order_num 
        AND prod_id = 'FB';
    
    
    # 外部连接(左外和右外)
    SELECT customers.cust_id, orders.order_num FROM customers LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id;
    SELECT customers.cust_id, orders.order_num FROM customers RIGHT OUTER JOIN orders ON orders.cust_id = customers.cust_id;
    
    
    # 带聚集函数的联结
    SELECT
        customers.cust_name,
        customers.cust_id,
        COUNT(orders.order_num) AS num_ord 
    FROM
        customers
        INNER JOIN orders ON customers.cust_id = orders.cust_id 
    GROUP BY
        customers.cust_id;
    
    SELECT
        customers.cust_name,
        customers.cust_id,
        COUNT( orders.order_num ) AS num_ord 
    FROM
        customers
        LEFT OUTER JOIN orders ON customers.cust_id = orders.cust_id 
    GROUP BY
        customers.cust_id;
    
    

    第17章 组合查询

    # 使用UNION组合多条语句查询
    SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5
    UNION
    SElECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002);
    
    # 不自动取消重复行
    SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5
    UNION ALL
    SElECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002);
    
    # 只能在最后一条SQL后写排序
    SELECT vend_id, prod_id, prod_price FROM products WHERE prod_price <= 5
    UNION ALL
    SElECT vend_id, prod_id, prod_price FROM products WHERE vend_id IN (1001, 1002);
    ORDER BY vend_id, prod_price;
    

    第18章 全文本搜索

    # MyISAM支持全文搜索, InnoDB不支持全文搜索
    #为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引
    # 创建表时使用FULLTEXT对指定的列进行索引
    
    # 使用函数进行搜索
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit');
    # 使用LIKE进行搜索
    SELECt note_text FROM productnotes WHERE note_text LIKE '%rabbit%';
    
    # 观察搜索结果排序
    SELECT note_text, Match(note_text) Against('rabbit') AS rank FROM productnotes;
    
    
    # 不使用查询扩展
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('anvils');
    
    # 使用查询扩展(会扫描两遍,第一遍精确查找,第二遍模糊查找)
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION);
    
    # 布尔文本搜索
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('heavy' IN BOOLEAN MODE);
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE);
    
    # 搜索匹配包含词 rabbit 和 bait 的行
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE);
    # 没有指定操作符,这个搜索匹配包含 rabbit 和 bait 中的至少一个词的行
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit bait' IN BOOLEAN MODE);
    # 这个搜索匹配短语 rabbit bait 而不是匹配两个词 rabbit 和bait
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('"rabbit bait"' IN BOOLEAN MODE);
    # 匹配 rabbit 和 carrot ,增加前者的等级,降低后者的等级
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('>rabbit <bait' IN BOOLEAN MODE);
    # 这个搜索匹配词 safe 和 combination ,降低后者的等级
    SELECT note_text FROM productnotes WHERE Match(note_text) Against('"+safe +(<combination)' IN BOOLEAN MODE);
    

    第19章 插入数据

    # 在指定的表中插入一行数据(INSERT语句一般不会产生输出, 但会返回影响的行数)
    # 这种方式不保险, 哪里列的顺序改变了就会出错
    INSERT INTO Customers
    VALUES
        ( NULL, 'Pep E.LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', 'NULL', 'NULL' );
    
    # 指定列名插入, 即使以后列的顺序改变了也不会出错
    INSERT INTO customers ( cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email )
    VALUES
        ( 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA', NULL, NULL);
    
    
    # 插入一行, 只插入指定的列值, 其它为默认值或者NULL
    # 没有默认值或者不能为NULl时会报错,并且插入不成功
    INSERT INTO customers (cust_name) VALUES ('Jack song');
    
    # 降低INSERT语句的优先级
    INSERT LOW_PRIORITY INTO customers ( cust_name )
    VALUES
        ( 'Jone Li. Main' );
    
    # 一次插入多行数据 方式一(用分号分隔)
    INSERT INTO customers ( cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country )
    VALUES
        ( 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA' );
    INSERT INTO customers ( cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country )
    VALUES
        ( 'M. Martian', '42 Galaxy Way', 'New York', 'Ny', '11213', 'USA' );
    
    
    # 一次插入多行数据 方式二(多行数用括号包裹,逗号分隔)
    # 此技术可以提高数据库处理的性能,因为MySQL用单条 INSERT 语句处理多个插入比使用多条 INSERT语句快
    INSERT INTO customers ( cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country )
    VALUES
        ( 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA' ),
        ( 'M. Martian', '42 Galaxy Way', 'New York', 'NY', '11213', 'USA' );
    
    
    # INSERT和SELECT结合插入其它表检索出来的数据
    INSERT INTO customers ( cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country ) SELECT
    cust_id,
    cust_contact,
    cust_email,
    cust_name,
    cust_address,
    cust_city,
    cust_state,
    cust_zip,
    cust_country 
    FROM
        custnew;
    

    第20章 更新和删除数据

    # 不要省略 WHERE 子句 在使用 UPDATE 时一定要注意细心,
    # 因为稍不注意,就会更新表中所有行. 
    
    # 更新符合筛选条件的行中的指定列
    UPDATE customers SET cust_email = 'elemer@fudd.com' WHERE cust_id = 10005;
    
    # 更新多列
    UPDATE customers SET cust_name = 'The Fudds', cust_email = 'elmer@fudd.com' WHERE cust_id = 10005;
    
    # 更新多行时, 使用IGNORE忽略错误, 继续更新下去
    UPDATE IGNORE customers SET cust_email = 'elemer1@fudd.com' WHERE cust_id = '10005';
    
    
    # 可以用来删除指定列(可以为NULL的情况)
    UPDATE customers SET cust_email = NULL WHERE cust_id = 10005;
    
    
    
    # 在使用 DELETE 时一定要注意细心。因为稍不注意,就会错误地删除表中所有行
    # 删除符合筛选条件的行
    DELETE FROM customers WHERE cust_id = 10006;
    
    # DELETE 语句从表中删除行, 甚至是删除表中所有行。但是, DELETE 不删除表本身
    
    -- 更新和删除的指导原则
    -- 前一节中使用的 UPDATE 和 DELETE 语句全都具有 WHERE 子句,这样做的
    -- 理由很充分。如果省略了 WHERE 子句,则 UPDATE 或 DELETE 将被应用到表中
    -- 所有的行。换句话说,如果执行 UPDATE 而不带 WHERE 子句,则表中每个行
    -- 都将用新值更新。类似地,如果执行 DELETE 语句而不带 WHERE 子句,表的
    -- 所有数据都将被删除。
    -- 下面是许多SQL程序员使用 UPDATE 或 DELETE 时所遵循的习惯。
    --  除非确实打算更新和删除每一行,否则绝对不要使用不带 WHERE
    -- 子句的 UPDATE 或 DELETE 语句。
    --  保证每个表都有主键(如果忘记这个内容,请参阅第15章),尽可能
    -- 像 WHERE 子句那样使用它(可以指定各主键、多个值或值的范围)。
    --  在对 UPDATE 或 DELETE 语句使用 WHERE 子句前,应该先用 SELECT 进
    -- 行测试,保证它过滤的是正确的记录,以防编写的 WHERE 子句不
    -- 正确。
    --  使用强制实施引用完整性的数据库(关于这个内容,请参阅第15
    -- 章),这样MySQL将不允许删除具有与其他表相关联的数据的行
    

    第21章 创建和操纵表

    # 使用SQL创建新表
    CREATE TABLE customers1 (
        cust_id INT NOT NULL AUTO_INCREMENT,
        cust_name char(50) NOT NULL,
        cust_address char(50) NULL,
        cust_city char(50) NULL,
        cust_state char(5) NULL,
        cust_zip char(10) NULL,
        cust_country char(50) NULL,
        cust_contact char(50) NULL,
        cust_email char(255) NULL,
        PRIMARY KEY (cust_id)
    ) ENGINE=InnoDB;
    
    
    # 不允许NULL值
    CREATE TABLE orders1 (
        order_num   int NOT NULL AUTO_INCREMENT,
        order_date datetime NOT NULL,
        cust_id int NOT NULL,
        PRIMARY KEY (order_num)
    ) ENGINE=InnoDB;
    
    # 多列主键
    CREATE TABLE orderitems1 (
        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;
    
    
    # 使用函数获得最后自动生成的id
    SELECT LAST_INSERT_ID();
    
    
    # 创建表时给默认值
    CREATE TABLE IF NOT EXISTS orderitems2 (
        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;
    
    
    # 更新表结构(添加列)
    ALTER TABLE vendors ADD vend_phone CHAR(20);
    
    # 更新表结构(删除列)
    ALTER TABLE vendors DROP COLUMN vend_phone;
    
    # 更新表(添加外键)
    ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_orders FOREIGN KEY (order_num) REFERENCES orders (order_num);
    
    ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_products FOREIGN KEY (prod_id) REFERENCES products (prod_id);
    
    ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id) REFERENCES customers (cust_id);
    
    ALTER TABLE products ADD CONSTRAINT fk_products_vendors FOREIGN KEY (vend_id) REFERENCES vendors (vend_id);
    
    
    ##复杂的表结构更改一般需要手动删除过程,它涉及以下步骤:
    --  用新的列布局创建一个新表;
    --  使用 INSERT SELECT 语句(关于这条语句的详细介绍,请参阅第
    --      19章)从旧表复制数据到新表。如果有必要,可使用转换函数和
    --      计算字段;
    --  检验包含所需数据的新表;
    --  重命名旧表(如果确定,可以删除它);
    --  用旧表原来的名字重命名新表;
    --  根据需要,重新创建触发器、存储过程、索引和外键。
    
    
    # 删除表
    DROP TABLE orderitems2
    
    # 重命名表
    RENAME TABLE customers1 TO customer3;
    
    # 同时重命名多个表
    RENAME TABLE customer3 TO customers1, orderitems1 TO orderitems2;
    

    第22章 使用视图

    # 视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询
    
    
    # 普通方法检索需要的数据
    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';
    
    # 使用视图检索(假如可以把整个查询包装成一个名为 productcustomers 的虚拟表)
    SELECT
        cust_name,
        cust_contact 
    FROM
        productcustomers 
    WHERE
        prod_id = 'TNT2';
    
    -- 这就是视图的作用。 productcustomers 是一个视图,作为视图,它
    -- 不包含表中应该有的任何列或数据,它包含的是一个SQL查询(与上面用
    -- 以正确联结表的相同的查询
    
    
    # 创建视图
    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;
    
    # 创建视图
    CREATE VIEW vendorlocations AS SELECT
    Concat ( RTrim( vend_name ), '(', RTrim( vend_country ), ')' ) AS vend_title 
    FROM
        vendors 
    ORDER BY
        vend_name;
    
    # 在视图中查询
    SELECT * FROM vendorlocations;
    
    
    # 创建视图
    CREATE VIEW customeremaillist AS SELECT
    cust_id,
    cust_name,
    cust_email 
    FROM
        customers 
    WHERE
        cust_email IS NOT NULL;
    
    
    # 检索视图
    SELECT * FROM customeremaillist;
    
    # 双WHERE子句(视图中一个, SQL中一个)
    SELECT * FROM customeremaillist WHERE cust_id = 10003;
    
    
    # 创建视图(和计算字段结合)
    CREATE VIEW orderitemsexpanded AS SELECT
    order_num,
    prod_id,
    quantity,
    item_price,
    quantity * item_price AS expanded_price 
    FROM
        orderitems;
    
    # 检索有计算字段的视图
    SELECT * FROM orderitemsexpanded WHERE order_num = 20005;
    
    -- 如果视图定义中有以下操作,则不能进行视图的更新:
    --  分组(使用 GROUP BY 和 HAVING );
    --  联结;
    --  子查询;
    --  并;
    --  聚集函数( Min() 、 Count() 、 Sum() 等)
    --      DISTINCT;
    --  导出(计算)列
    

    第23章 使用存储过程

    # 调用存储过程并返回数据
    CALL productpricing(@pricelow, @pricehigh, @priceaverage);
    
    
    # 创建存储过程
    CREATE PROCEDURE productpricing()
    BEGIN
        SELECT Avg(prod_price) AS priceaverage FROM products;
    END
    
    
    # 调用存储过程
    CALL productpricing();
    
    
    # 为了在命令行中不出错,改变分隔符
    DELIMITER //
    CREATE PROCEDURE productpricing1()
    BEGIN
        SELECT Max(prod_price) AS pricehigh FROM products;
    END //
    DELIMITER ;
    
    CALL productpricing1();
    
    
    # 删除存储过程
    DROP PROCEDURE IF EXISTS productpricing1 ;
    
    
    # 使用OUT参数
    CREATE PROCEDURE productpricingwithavg(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;
    
    # 使用变量接收
    CALL productpricingwithavg(@pricelow, @pricehigh, @priceaverage);
    # 显示出来 
    SELECT @pricelow;
    SELECT @pricelow, @pricehigh, @priceaverage;
    
    
    # 使用IN OUT参数
    CREATE PROCEDURE ordertotal(IN onumber INT, OUT ototal DECIMAL(8,2))
    BEGIN
        SELECT Sum(item_price*quantity) FROM orderitems WHERE order_num = onumber INTO ototal;
    END;
    
    CALL ordertotal(20005, @total);
    SELECT @total;
    
    # 可以用不同的参数反复调用存储过程
    CALL ordertotal(20009, @total);
    SELECT @total;
    
    
    # 一个更智能的存储过程(带税求和和不带税求和)
    -- Name: ordertotal
    -- Parameters: onumber = oreder number
    --                       taxable = 0 if not taxable, 1 if taxable
    --             ototal = order total variable
    
    CREATE PROCEDURE ordertotalsmart ( IN onumber INT, IN taxable BOOLEAN, OUT ototal DECIMAL ( 8, 2 ) ) COMMENT 'Obtain order, optionally adding tax' 
    BEGIN
        
        -- Declare variable for total
        DECLARE total DECIMAL(8,2);
        -- DEclare tax percentage
        DECLARE taxrate INT DEFAULT 6;
        
        -- Get the order total
        SELECT Sum(item_price*quantity)
        FROM orderitems
        WHERE order_num = onumber
        INTO total;
        
        -- Is this taxable?
        IF taxable THEN
            -- Yes, so add taxrate to the total
            SELECT total+(total/100*taxrate) INTO total;
        END IF;
        
        -- And finally, save to out variable
        SELECT total INTO ototal;
        
    END;
    
    # 调用上面的存储过程
    CALL ordertotalsmart(20005, 0, @total);
    SELECT @total;
    CALL ordertotalsmart(20005, 1, @total);
    SELECT @total;
    
    # 显示创建存储过程的语句
    SHOW CREATE PROCEDURE ordertotalsmart;
    
    # 显示所有存储过程的状态
    SHOW PROCEDURE STATUS;
    
    # 显示筛选后的存储过程的状态
    SHOW PROCEDURE STATUS LIKE 'ordertotalsmart';
    

    第24章 使用游标

    -- 使用游标涉及几个明确的步骤
    --  在能够使用游标前,必须声明(定义)它。这个过程实际上没有
    --  检索数据,它只是定义要使用的 SELECT 语句。
    -- 一旦声明后,必须打开游标以供使用。这个过程用前面定义的
    --  SELECT 语句把数据实际检索出来。
    -- 对于填有数据的游标,根据需要取出(检索)各行。
    -- 在结束游标使用时,必须关闭游标
    
    
    # 创建游标(存储过程处理完成后,游标就消失(因为它局限于存储过程))
    CREATE PROCEDURE processorders()
    BEGIN
        DECLARE ordernumbers CURSOR
        FOR
        SELECT order_num FROM ordres;
        
        -- 打开游标
        OPEN ordernumbers;
        
        
        -- 关闭游标 
        CLOSE ordernumbers;
        
    END;
    
    # 使用游标(FETCH)
    CREATE PROCEDURE processorders1()
    BEGIN
        
        -- Declare local variables
        DEClARE o INT;
    
        -- Declare the cursor
        DECLARE ordernumbers CURSOR
        FOR
        SELECT order_num FROM orders;
        
        -- open cursor
        OPEN ordernumbers;
        
        
        -- Get order number
        FETCH ordernumbers INTO o;
        
        
        -- close cursor
        CLOSE ordernumbers;
        
        
    END;
    
    
    # 用游标循环获取行
    CREATE PROCEDURE processorders2 ()
    BEGIN
        -- Declare local variables
        -- 变量要申明在游标或者句柄之前
        DECLARE done BOOLEAN DEFAULT 0;
        DECLARE o INT;
        
        -- Declare the cursor
        DECLARE ordernumbers CURSOR
        FOR 
        SELECT order_num FROM orders;
        
        -- Declare continue handler
        DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
        
        -- open cursor
        OPEN ordernumbers;
        
        -- loop through all rows
        REPEAT
            
            -- Get order number
            FETCH ordernumbers INTO o;
        
        -- End of loop
        UNTIL done END REPEAT;
        
        -- close cursor
        CLOSE ordernumbers;
        
    END;
    
    
    # 实例
    CREATE PROCEDURE porcessoredres4()
    BEGIN
    
        -- Declare loca variables
        DECLARE done BOOLEAN DEFAULT 0;
        DECLARE o INT;
        DECLARE t DECIMAL(8,2);
        
        -- Declare the cursor
        DECLARE ordernumbers CURSOR
        FOR
        SELECT order_num FROM orders;
        
        -- Declare continue handler
        DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
        
        -- Create a table to store the results
        CREATE TABLE IF NOT EXISTS ordertotals (order_num INT, total DECIMAL(8,2));
        
        -- Open cursor
        OPEN ordernumbers;
        
        -- Loop through all rows
        REPEAT
            
            -- Get order number
            FETCH ordernumbers INTO o;
            
            -- Get the total for this order
            CALL ordertotalsmart(o, 1, t);
            
            -- Insert order and total into ordertotals
            INSERT INTO ordertotals(order_num, total) VALUES (o, t);
        
            -- End of loop
            UNTIL done END REPEAT;
        
            -- Close cursor
            ClOSE ordernumbers;
    
    END;
    
    
    # 调用实例
    CALL porcessoredres4();
    

    第25章 使用触发器

    -- 触发器按每个表每个事件每次地定义,每个表每个事件每次只允许一个触发器。
    -- 因此,每个表最多支持6个触发器(每条 INSERT 、 UPDATE和 DELETE 的之前和之后)
    -- 只有表才支持触发器,视图不支持(临时表也不支持
    
    
    # 创建一个触发器
    CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW
    BEGIN
    
    END;
    
    
    # 删除一个触发器
    DROP TRIGGER newproduct;
    
    
    # 创建一个触发器
    CREATE TRIGGER neworder AFTER INSERT ON orders
    FOR EACH ROW 
    BEGIN
        
    END;
    
    
    # DELETE触发器
    CREATE TRIGGER deleteorder BEFORE DELETE ON orders
    FOR EACH ROW
    BEGIN
        INSERT INTO archive_orders(order_num, ordre_date, cust_id)
        VALUES(OLD.order_num, OLD.order_date, OLD.cust_id);
    END;
    
    
    # UPDATE触发器
    CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors
    FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_state);
    

    第26章 管理事务处理

    # 事务 使用ROLLBACK
    SELECT * FROM ordertotals;
    START TRANSACTION;              
    DELETE FROM ordertotals;
    SELECT * FROM ordertotals;
    ROLLBACK;
    SELECT * FROM ordertotals;
    
    
    # 使用COMMIT提交事务
    START TRANSACTION;
    DELETE FROM orderitems WHERE order_num = 20009;
    DELETE FROM orders WHERE order_num = 20010;
    COMMIT;
    
    
    # 设置保留点并回滚到保留点
    START TRANSACTION;
    SELECT * FROM ordertotals;
    SAVEPOINT delete1;
    DELETE FROM ordertotals;
    SELECT * FROM ordertotals;
    ROLLBACK TO delete1;
    SELECT * FROM ordertotals;
    
    
    # 取消MYSQL的自动提交(MYSQL默认每条语句是自动提交的)
    # autocommit 标志是针对每个连接而不是服务器的
    SET autocommit=0;
    

    第27章 全球化和本地化

    # 查看支持的字符集
    SHOW CHARACTER SET;
    
    
    # 查看校对表
    SHOW COLLATION;
    
    # 查看所使用的字符集和校对
    SHOW VARIABLES LIKE 'character%';
    SHOW VARIABLES LIKE 'collation%';
    
    
    # 创建表时指定字符集
    CREATE TABLE mytable (
        columnn1 INT,
        columnn2 VARCHAR(10)
    ) DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
    
    
    # 对指定的列设置字符集
    CREATE TABLE mytable1(
        columnn1 INT,
        columnn2 VARCHAR(10),
        columnn3 VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci
    ) DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
    
    
    # 在检索的时候指定校对
    SELECT * FROM customers
    ORDER BY lastname, firstname COLLATE latin1_general_cs;
    

    第28章 安全管理

    # 查看此MYSQL服务器上的所有用户
    USE mysql;
    USE mysql_need_know;
    SELECT `user` FROM user;
    SELECT * FROM user;
    
    # 创建一个新的用户账号并指定密码(没有任何权限,要在之后分配权限)
    CREATE USER bean IDENTIFIED BY '123456';
    
    # 重命令用户
    RENAME USER bean TO bforta;
    
    # 删除一个用户(Mysql5.0之前只会删除账号,不会删除此账号的权限需要先用 REVOKE删除与账号相关的权限)
    DROP USER bean;
    
    # 查看用户权限
    SHOW GRANTS FOR bforta;
    SHOW GRANTS FOR root@localhost;
    
    -- 用户定义为 user@host MySQL的权限用用户名和主机名结
    -- 合定义。如果不指定主机名,则使用默认的主机名 % (授予用
    -- 户访问权限而不管主机名
    
    # 设置权限(bforta可以检索数据库crashcourse中的所有表)
    GRANT SELECT ON crashcourse.* TO bforta;
    
    # 移除权限
    REVOKE SELECT ON crashcourse.* FROM bforta;
    
    -- GRANT 和 REVOKE 可在几个层次上控制访问权限:
    --  整个服务器,使用 GRANT ALL 和 REVOKE ALL;
    --  整个数据库,使用 ON database.*;
    --  特定的表,使用 ON database.table;
    --  特定的列;
    --  特定的存储过程
    
    
    -- 未来的授权 在使用 GRANT 和 REVOKE 时,用户账号必须存在,
    -- 但对所涉及的对象没有这个要求。这允许管理员在创建数据库
    -- 和表之前设计和实现安全措施。
    -- 这样做的副作用是,当某个数据库或表被删除时(用 DROP 语
    -- 句),相关的访问权限仍然存在。而且,如果将来重新创建该
    -- 数据库或表,这些权限仍然起作用
    
    
    # 一次授予多个权限
    GRANT SELECT, INSERT ON crashcourse.* TO bforta;
    
    
    # 更改指定用户的密码(使用Password函数)
    SET PASSWORD FOR bforta = Password('12345');
    
    # 更改当前登陆用户的密码
    SET PASSWORD = Password('123456');
    

    第29章 数据库维护

    # 使用在命令行工具中使用mysqldump备份所有数据库到外部文件中
    
    -- 备份:mysqldump -u root -p --databases 数据库1 数据库2 > xxx.sql
    -- 还原:MySQL -uroot -p123456 <f:all.sql
    -- 常见选项:
    -- --all-databases, -A: 备份所有数据库
    -- --databases, -B: 用于备份多个数据库,如果没有该选项,mysqldump把第一个名字参数作为数据库名,后面的作为表名。使用该选项,mysqldum把每个名字都当作为数据库名。
    -- 
    -- --force, -f:即使发现sql错误,仍然继续备份
    -- --host=host_name, -h host_name:备份主机名,默认为localhost
    -- --no-data, -d:只导出表结构
    -- --password[=password], -p[password]:密码
    -- --port=port_num, -P port_num:制定TCP/IP连接时的端口号
    -- --quick, -q:快速导出
    -- --tables:覆盖 --databases or -B选项,后面所跟参数被视作表名
    -- --user=user_name, -u user_name:用户名
    -- --xml, -X:导出为xml文件
    -- 1.备份全部数据库的数据和结构
    -- 
    -- mysqldump -uroot -p123456 -A >F:all.sql
    -- 
    -- 2.备份全部数据库的结构(加 -d 参数)
    -- 
    -- mysqldump -uroot -p123456 -A-d>F:all_struct.sql
    -- 1.还原全部数据库:
    -- 
    -- (1) mysql命令行:mysql>source f:all.sql
    -- 
    -- (2) 系统命令行: mysql -uroot -p123456 <f:all.sql
    
    
    # 检查表键
    ANALYZE TABLE orders;
    
    # 检查多表键
    CHECK TABLE orders, orderitems;
    

    第30章 改善性能

    -- 首先,MySQL(与所有DBMS一样)具有特定的硬件建议。在学
    -- 习和研究MySQL时,使用任何旧的计算机作为服务器都可以。但
    -- 对用于生产的服务器来说,应该坚持遵循这些硬件建议。
    --  一般来说,关键的生产DBMS应该运行在自己的专用服务器上。
    --  MySQL是用一系列的默认设置预先配置的,从这些设置开始通常
    -- 是很好的。但过一段时间后你可能需要调整内存分配、缓冲区大
    -- 小等。(为查看当前设置,可使用 SHOW VARIABLES; 和 SHOW
    -- STATUS; 。)
    --  MySQL一个多用户多线程的DBMS,换言之,它经常同时执行多
    -- 个任务。如果这些任务中的某一个执行缓慢,则所有请求都会执
    -- 行缓慢。如果你遇到显著的性能不良,可使用 SHOW PROCESSLIST
    -- 显示所有活动进程(以及它们的线程ID和执行时间)。你还可以用
    -- KILL 命令终结某个特定的进程(使用这个命令需要作为管理员登
    -- 录)。
    --  总是有不止一种方法编写同一条 SELECT 语句。应该试验联结、并、
    -- 子查询等,找出最佳的方法。
    --  使用 EXPLAIN 语句让MySQL解释它将如何执行一条 SELECT 语句。
    --  一般来说,存储过程执行得比一条一条地执行其中的各条MySQL
    -- 语句快。
    --  应该总是使用正确的数据类型。
    --  决不要检索比需求还要多的数据。换言之,不要用 SELECT * (除
    -- 非你真正需要每个列)。
    --  有的操作(包括 INSERT )支持一个可选的 DELAYED 关键字,如果
    -- 使用它,将把控制立即返回给调用程序,并且一旦有可能就实际
    -- 执行该操作。
    --  在导入数据时,应该关闭自动提交。你可能还想删除索引(包括
    -- FULLTEXT 索引),然后在导入完成后再重建它们。
    --  必须索引数据库表以改善数据检索的性能。确定索引什么不是一
    -- 件微不足道的任务,需要分析使用的 SELECT 语句以找出重复的
    -- WHERE 和 ORDER BY 子句。如果一个简单的 WHERE 子句返回结果所花
    -- 的时间太长,则可以断定其中使用的列(或几个列)就是需要索
    -- 引的对象。
    --  你的 SELECT 语句中有一系列复杂的 OR 条件吗?通过使用多条
    -- SELECT 语句和连接它们的 UNION 语句,你能看到极大的性能改
    -- 进。
    --  索引改善数据检索的性能,但损害数据插入、删除和更新的性能。
    -- 如果你有一些表,它们收集数据且不经常被搜索,则在有必要之
    -- 前不要索引它们。(索引可根据需要添加和删除。)
    --  LIKE 很慢。一般来说,最好是使用 FULLTEXT 而不是 LIKE 。
    --  数据库是不断变化的实体。一组优化良好的表一会儿后可能就面
    -- 目全非了。由于表的使用和内容的更改,理想的优化和配置也会
    -- 改变。
    --  最重要的规则就是,每条规则在某些条件下都会被打破
    

    附录A MySQL入门 附录B 样例表 附录C MySQL语句的语法 附录D MySQL数据类型 附录E MySQL保留字 索引

    《MySQL必知必会》SQL文件:

    表的创建和外键绑定:

    # 在Mysql中取消外键约束 
    SET FOREIGN_KEY_CHECKS=0;  
    DROP TABLE customers;
    DROP TABLE orderitems;
    DROP TABLE orders;
    DROP TABLE products;
    DROP TABLE vendors;
    DROP TABLE productnotes;
    # 然后再设置外键约束
    SET FOREIGN_KEY_CHECKS=1;  
    
    CREATE TABLE customers
    (
      cust_id      int       NOT NULL AUTO_INCREMENT COMMENT '唯一的顾客ID',
      cust_name    char(50)  NOT NULL COMMENT '顾客名',
      cust_address char(50)  NULL COMMENT '顾客的地址',
      cust_city    char(50)  NULL COMMENT '顾客的城市',
      cust_state   char(5)   NULL COMMENT '顾客的州',
      cust_zip     char(10)  NULL COMMENT '顾客的邮政编码',
      cust_country char(50)  NULL COMMENT '顾客的国家',
      cust_contact char(50)  NULL COMMENT '顾客的联系名',
      cust_email   char(255) NULL COMMENT '顾客的联系email地址',
      PRIMARY KEY (cust_id)
    ) ENGINE=InnoDB;
    CREATE TABLE orderitems
    (
      order_num  int          NOT NULL COMMENT '订单号',
      order_item int          NOT NULL COMMENT '订单物品号',
      prod_id    char(10)     NOT NULL COMMENT '产品ID',
      quantity   int          NOT NULL COMMENT '物品数量',
      item_price decimal(8,2) NOT NULL COMMENT '物品价格',
      PRIMARY KEY (order_num, order_item)
    ) ENGINE=InnoDB;
    CREATE TABLE orders
    (
      order_num  int      NOT NULL AUTO_INCREMENT COMMENT '唯一订单号',
      order_date datetime NOT NULL COMMENT '订单日期',
      cust_id    int      NOT NULL COMMENT '订单顾客ID',
      PRIMARY KEY (order_num)
    ) ENGINE=InnoDB;
    CREATE TABLE products
    (
      prod_id    char(10)      NOT NULL COMMENT '唯一的产品ID',
      vend_id    int           NOT NULL COMMENT '产品供应商ID',
      prod_name  char(255)     NOT NULL COMMENT '产品名',
      prod_price decimal(8,2)  NOT NULL COMMENT '产品价格',
      prod_desc  text          NULL COMMENT '产品描述',
      PRIMARY KEY(prod_id)
    ) ENGINE=InnoDB;
    CREATE TABLE vendors
    (
      vend_id      int      NOT NULL AUTO_INCREMENT COMMENT '唯一的供应商ID',
      vend_name    char(50) NOT NULL COMMENT '供应商名',
      vend_address char(50) NULL COMMENT '供应商的地址',
      vend_city    char(50) NULL COMMENT '供应商的城市',
      vend_state   char(5)  NULL COMMENT '供应商的州',
      vend_zip     char(10) NULL COMMENT '供应商的邮政编码',
      vend_country char(50) NULL COMMENT '供应商的国家',
      PRIMARY KEY (vend_id)
    ) ENGINE=InnoDB;
    CREATE TABLE productnotes
    (
      note_id    int           NOT NULL AUTO_INCREMENT COMMENT '唯一注释ID',
      prod_id    char(10)      NOT NULL COMMENT '产品ID',
      note_date datetime       NOT NULL COMMENT '增加注释的日期',
      note_text  text          NULL COMMENT '注释文本',
      PRIMARY KEY(note_id),
      FULLTEXT(note_text)
    ) ENGINE=MyISAM;
    ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_orders FOREIGN KEY (order_num) REFERENCES orders (order_num);
    ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_products FOREIGN KEY (prod_id) REFERENCES products (prod_id);
    ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id) REFERENCES customers (cust_id);
    ALTER TABLE products ADD CONSTRAINT fk_products_vendors FOREIGN KEY (vend_id) REFERENCES vendors (vend_id);
    
    ##########################
    # Populate customers table
    ##########################
    INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
    VALUES(10001, 'Coyote Inc.', '200 Maple Lane', 'Detroit', 'MI', '44444', 'USA', 'Y Lee', 'ylee@coyote.com');
    INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
    VALUES(10002, 'Mouse House', '333 Fromage Lane', 'Columbus', 'OH', '43333', 'USA', 'Jerry Mouse');
    INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
    VALUES(10003, 'Wascals', '1 Sunny Place', 'Muncie', 'IN', '42222', 'USA', 'Jim Jones', 'rabbit@wascally.com');
    INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
    VALUES(10004, 'Yosemite Place', '829 Riverside Drive', 'Phoenix', 'AZ', '88888', 'USA', 'Y Sam', 'sam@yosemite.com');
    INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
    VALUES(10005, 'E Fudd', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'E Fudd');
    
    
    ########################
    # Populate vendors table
    ########################
    INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
    VALUES(1001,'Anvils R Us','123 Main Street','Southfield','MI','48075', 'USA');
    INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
    VALUES(1002,'LT Supplies','500 Park Street','Anytown','OH','44333', 'USA');
    INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
    VALUES(1003,'ACME','555 High Street','Los Angeles','CA','90046', 'USA');
    INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
    VALUES(1004,'Furball Inc.','1000 5th Avenue','New York','NY','11111', 'USA');
    INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
    VALUES(1005,'Jet Set','42 Galaxy Road','London', NULL,'N16 6PS', 'England');
    INSERT INTO vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
    VALUES(1006,'Jouets Et Ours','1 Rue Amusement','Paris', NULL,'45678', 'France');
    
    
    #########################
    # Populate products table
    #########################
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('ANV01', 1001, '.5 ton anvil', 5.99, '.5 ton anvil, black, complete with handy hook');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('ANV02', 1001, '1 ton anvil', 9.99, '1 ton anvil, black, complete with handy hook and carrying case');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('ANV03', 1001, '2 ton anvil', 14.99, '2 ton anvil, black, complete with handy hook and carrying case');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('OL1', 1002, 'Oil can', 8.99, 'Oil can, red');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('FU1', 1002, 'Fuses', 3.42, '1 dozen, extra long');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('SLING', 1003, 'Sling', 4.49, 'Sling, one size fits all');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('TNT1', 1003, 'TNT (1 stick)', 2.50, 'TNT, red, single stick');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('TNT2', 1003, 'TNT (5 sticks)', 10, 'TNT, red, pack of 10 sticks');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('FB', 1003, 'Bird seed', 10, 'Large bag (suitable for road runners)');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('FC', 1003, 'Carrots', 2.50, 'Carrots (rabbit hunting season only)');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('SAFE', 1003, 'Safe', 50, 'Safe with combination lock');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('DTNTR', 1003, 'Detonator', 13, 'Detonator (plunger powered), fuses not included');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('JP1000', 1005, 'JetPack 1000', 35, 'JetPack 1000, intended for single use');
    INSERT INTO products(prod_id, vend_id, prod_name, prod_price, prod_desc)
    VALUES('JP2000', 1005, 'JetPack 2000', 55, 'JetPack 2000, multi-use');
    
    
    
    #######################
    # Populate orders table
    #######################
    INSERT INTO orders(order_num, order_date, cust_id)
    VALUES(20005, '2005-09-01', 10001);
    INSERT INTO orders(order_num, order_date, cust_id)
    VALUES(20006, '2005-09-12', 10003);
    INSERT INTO orders(order_num, order_date, cust_id)
    VALUES(20007, '2005-09-30', 10004);
    INSERT INTO orders(order_num, order_date, cust_id)
    VALUES(20008, '2005-10-03', 10005);
    INSERT INTO orders(order_num, order_date, cust_id)
    VALUES(20009, '2005-10-08', 10001);
    
    
    ###########################
    # Populate orderitems table
    ###########################
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20005, 1, 'ANV01', 10, 5.99);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20005, 2, 'ANV02', 3, 9.99);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20005, 3, 'TNT2', 5, 10);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20005, 4, 'FB', 1, 10);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20006, 1, 'JP2000', 1, 55);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20007, 1, 'TNT2', 100, 10);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20008, 1, 'FC', 50, 2.50);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20009, 1, 'FB', 1, 10);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20009, 2, 'OL1', 1, 8.99);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20009, 3, 'SLING', 1, 4.49);
    INSERT INTO orderitems(order_num, order_item, prod_id, quantity, item_price)
    VALUES(20009, 4, 'ANV03', 1, 14.99);
    
    #############################
    # Populate productnotes table
    #############################
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(101, 'TNT2', '2005-08-17',
    'Customer complaint:
    Sticks not individually wrapped, too easy to mistakenly detonate all at once.
    Recommend individual wrapping.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(102, 'OL1', '2005-08-18',
    'Can shipped full, refills not available.
    Need to order new can if refill needed.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(103, 'SAFE', '2005-08-18',
    'Safe is combination locked, combination not provided with safe.
    This is rarely a problem as safes are typically blown up or dropped by customers.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(104, 'FC', '2005-08-19',
    'Quantity varies, sold by the sack load.
    All guaranteed to be bright and orange, and suitable for use as rabbit bait.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(105, 'TNT2', '2005-08-20',
    '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.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(106, 'TNT2', '2005-08-22',
    'Matches not included, recommend purchase of matches or detonator (item DTNTR).'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(107, 'SAFE', '2005-08-23',
    'Please note that no returns will be accepted if safe opened using explosives.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(108, 'ANV01', '2005-08-25',
    'Multiple customer returns, anvils failing to drop fast enough or falling backwards on purchaser. Recommend that customer considers using heavier anvils.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(109, 'ANV03', '2005-09-01',
    'Item is extremely heavy. Designed for dropping, not recommended for use with slings, ropes, pulleys, or tightropes.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(110, 'FC', '2005-09-01',
    'Customer complaint: rabbit has been able to detect trap, food apparently less effective now.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(111, 'SLING', '2005-09-02',
    'Shipped unassembled, requires common tools (including oversized hammer).'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(112, 'SAFE', '2005-09-02',
    'Customer complaint:
    Circular hole in safe floor can apparently be easily cut with handsaw.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(113, 'ANV01', '2005-09-05',
    'Customer complaint:
    Not heavy enough to generate flying stars around head of victim. If being purchased for dropping, recommend ANV02 or ANV03 instead.'
    );
    INSERT INTO productnotes(note_id, prod_id, note_date, note_text)
    VALUES(114, 'SAFE', '2005-09-07',
    'Call from individual trapped in safe plummeting to the ground, suggests an escape hatch be added.
    Comment forwarded to vendor.'
    );
    


    3.类似Oracle中的经典SQL练习案例
    
    /*
    Navicat MySQL Data Transfer
    
    Source Server         : MySQL_Localhost
    Source Server Version : 50540
    Source Host           : localhost:3306
    Source Database       : like_oracle
    
    Target Server Type    : MYSQL
    Target Server Version : 50540
    File Encoding         : 65001
    
    Date: 2020-05-05 14:06:37
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for bonus
    -- ----------------------------
    DROP TABLE IF EXISTS `bonus`;
    CREATE TABLE `bonus` (
      `ename` varchar(10) DEFAULT NULL,
      `job` varchar(9) DEFAULT NULL,
      `sal` int(11) DEFAULT NULL,
      `comm` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of bonus
    -- ----------------------------
    
    -- ----------------------------
    -- Table structure for dept
    -- ----------------------------
    DROP TABLE IF EXISTS `dept`;
    CREATE TABLE `dept` (
      `deptno` int(2) NOT NULL,
      `dname` varchar(14) DEFAULT NULL,
      `loc` varchar(13) DEFAULT NULL,
      PRIMARY KEY (`deptno`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of dept
    -- ----------------------------
    INSERT INTO `dept` VALUES ('10', 'ACCOUNTING', 'NEW YORK');
    INSERT INTO `dept` VALUES ('20', 'RESEARCH', 'DALLAS');
    INSERT INTO `dept` VALUES ('30', 'SALES', 'CHICAGO');
    INSERT INTO `dept` VALUES ('40', 'OPERATIONS', 'BOSTON');
    
    -- ----------------------------
    -- Table structure for emp
    -- ----------------------------
    DROP TABLE IF EXISTS `emp`;
    CREATE TABLE `emp` (
      `empno` int(4) NOT NULL,
      `ename` varchar(10) DEFAULT NULL,
      `job` varchar(9) DEFAULT NULL,
      `mgr` int(4) DEFAULT NULL,
      `hiredate` date DEFAULT NULL,
      `sal` float(7,2) DEFAULT NULL,
      `comm` float(7,2) DEFAULT NULL,
      `deptno` int(2) DEFAULT NULL,
      PRIMARY KEY (`empno`),
      KEY `fk_deptno` (`deptno`),
      CONSTRAINT `fk_deptno` FOREIGN KEY (`deptno`) REFERENCES `dept` (`deptno`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of emp
    -- ----------------------------
    INSERT INTO `emp` VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980-12-17', '800.00', null, '20');
    INSERT INTO `emp` VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600.00', '300.00', '30');
    INSERT INTO `emp` VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250.00', '500.00', '30');
    INSERT INTO `emp` VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975.00', null, '20');
    INSERT INTO `emp` VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250.00', '1400.00', '30');
    INSERT INTO `emp` VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850.00', null, '30');
    INSERT INTO `emp` VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450.00', null, '10');
    INSERT INTO `emp` VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-07-13', '3000.00', null, '20');
    INSERT INTO `emp` VALUES ('7839', 'KING', 'PRESIDENT', null, '1981-11-07', '5000.00', null, '10');
    INSERT INTO `emp` VALUES ('7844', 'TURNER', 'SALESMAN', '7698', '1981-09-08', '1500.00', '0.00', '30');
    INSERT INTO `emp` VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-07-13', '1100.00', null, '20');
    INSERT INTO `emp` VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950.00', null, '30');
    INSERT INTO `emp` VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000.00', null, '20');
    INSERT INTO `emp` VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300.00', null, '10');
    
    -- ----------------------------
    -- Table structure for salgrade
    -- ----------------------------
    DROP TABLE IF EXISTS `salgrade`;
    CREATE TABLE `salgrade` (
      `grade` int(11) DEFAULT NULL,
      `losal` int(11) DEFAULT NULL,
      `hisal` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of salgrade
    -- ----------------------------
    INSERT INTO `salgrade` VALUES ('1', '700', '1200');
    INSERT INTO `salgrade` VALUES ('2', '1201', '1400');
    INSERT INTO `salgrade` VALUES ('3', '1401', '2000');
    INSERT INTO `salgrade` VALUES ('4', '2001', '3000');
    INSERT INTO `salgrade` VALUES ('5', '3001', '9999');
    
    
  • 相关阅读:
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 Cowboys
    Java实现 蓝桥杯 算法训练 Cowboys
    55. Jump Game
    54. Spiral Matrix
    50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/wqkeep/p/12548618.html
Copyright © 2011-2022 走看看