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技术》第一次作业
    链队列基本操作
    行编辑器,数制转换,杨辉三角
    顺序队列基本操作
    链栈基本操作
    顺序栈基本操作
    PTA链表
    PTA顺序表
    《Java技术》第三次作业
    《Java技术》第二次作业
  • 原文地址:https://www.cnblogs.com/wqkeep/p/12548618.html
Copyright © 2011-2022 走看看