zoukankan      html  css  js  c++  java
  • sql

    "Effective MySQL之SQL语句最优化"
    
    DBA5分钟速成(
        --测试表
        CREATE TABLE IF NOT EXISTS inventory
        (
            id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
            supp_id int(11) UNSIGNED NOT NULL DEFAULT '0',
            item_id int(11) UNSIGNED NOT NULL DEFAULT '0',
            qty int(11) NOT NULL,
            created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY(id),
            UNIQUE KEY supp_id (supp_id, item_id),
            KEY created (created)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表';
    
    
        --1.查看慢查询,找Time超过合理值的语句。
        SHOW FULL PROCESSLIST
    
        --2.重复执行被找到的语句,观察时间,如果是UPDATE或DELETE语句,要改成SELECT。
        "ALTER语句是阻塞操作,执行期间不允许其他数据库操作,且在线更新可能需要很多时间。"
        "是否一定要添加item_id为索引?一个表多个索引性能开销需考虑!"
        SELECT * FROM inventory WHERE item_id = 11;
    
        --3.生成查询执行计划(Query Execution Plan,QEP),在结果中查看key和rows的值(估计值)是否很大。
        EXPLAIN SELECT * FROM inventory WHERE item_id = 11;
    
        --4.添加索引,如果之前没有。
        ALTER TABLE inventory ADD INDEX(item_id);
    
        --5.再次执行EXPLAIN语句,确认优化。如观察到rows的值有明显变小,视为成功。
        EXPLAIN SELECT * FROM inventory WHERE item_id = 11;
    
        "
        总结:
            优化SQL语句的正确方法:理解和验证此SQL语句,以及与表相关的SQL语句目的。
            如果被优化的表中已有可用的索引,就不必再创建了。
    
        注意:
            在添加索引前,需要确认:
                1、表的结构;
                    SHOW CREATE TABLE inventory;
                2、表的大小,查看Rows和Data_length的值(近似值)。
                    SHOW CREATE STATUS LIKE 'inventory';
        "
    )
    
    基本分析命令(
    
    "
    QEP由SQL语句每次执行时的实际情况而定,即使使用存储过程也是如此。
    下面三种情况能帮助快速定位问题:
        1、没有使用索引(key的值为NULL);
        2、很多处理过的行(rows列);
        3、很多被评估过的索引(possible_keys列)。
    "
    EXPLAIN PA
    
    
    -- 测试表
    CREATE TABLE IF NOT EXISTS wp_options
    (
        option_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
        blog_id int(11) UNSIGNED NOT NULL DEFAULT '0',
        option_name VARCHAR(64) NOT NULL DEFAULT '',
        option_value LONGTEXT NOT NULL,
        autoload VARCHAR(20) NOT NULL DEFAULT 'yes',
        PRIMARY KEY(option_id),
        UNIQUE KEY option_name (option_name)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表';
    
    )
    场景(
        user1表(测试基线项目的测试人员):id,user_name,work_level;
        user2表(测试定制项目的测试人员):id,user_name,work_level;
        user_bugs表(发现bug的数目):id,user_id,timestr,bug_nums;
    )
    
    联接(
        内联结(
            'A与B的交集'
            SELECT <select_list> FROM user1 a INNER JOIN user2 b ON a.user_name = b.user_name;
        )
        
        左联结(
            'A的全部'
            SELECT <select_list> FROM user1 a LEFT  JOIN user2 b ON a.user_name = b.user_name;
            
            'A - A与B的交集'
            SELECT <select_list> FROM user1 a LEFT  JOIN user2 b ON a.user_name = b.user_name 
            WHERE b.user_name IS NULL;
        )
        
        右联结(
            'B的全部'
            SELECT <select_list> FROM user1 a RIGHT JOIN user2 b ON a.user_name = b.user_name;
    
            'B - A与B的交集'
            SELECT <select_list> FROM user1 a RIGHT JOIN user2 b ON a.user_name = b.user_name 
            WHERE a.user_name IS NULL;
        )
        
        全联结(
            'A + B'
            SELECT <select_list> FROM user1 a FULL  JOIN user2 b ON a.user_name = b.user_name;
            
            'A + B - A与B的交集'
            SELECT <select_list> FROM user1 a FULL  JOIN user2 b ON a.user_name = b.user_name 
            WHERE a.user_name IS NULL OR b.user_name IS NULL;
            
            '注意:MySQL不支持全连接,会产生1064的错误。需要使用UNION ALL'
            SELECT a.user_name, a.over, b.over
            FROM user1 a
            LEFT JOIN  user2 b ON a.user_name = b.user_name
            UNION ALL
            SELECT b.user_name, b.over, a,over
            FROM user1 a
            RIGHT JOIN user2 b ON a.user_name = b.user_name; 
        )
        
        交叉联结(
            'A * B 笛卡尔积'
            SELECT <select_list> FROM user1 a CROSS JOIN user2 b ON a.user_name = b.user_name;
        )
        
        联接更新(
            'MySQL与SQL Server和Oracle不同,不支持UPDATE语句中出现FROM。MySQL错误码:1093'
            -- 提升最辛苦的同事为测试经理
            UPDATE user1 SET work_level = '测试经理' WHERE user1.user_name IN (
                -- 找到同时既测试定制又测试基线的同事
                SELECT b.user_name FROM user1 a JOIN user2 b 
                ON a.user_name = b.user_name
            );
    
            'MySQL实现更新通过联接查询出的语句'
            UPDATE user1 a JOIN (SELECT b.user_name FROM user1 a JOIN user2 b 
                ON a.user_name = b.user_name) b ON a.user_name = b.user_name
            SET a.work_level = '测试经理';
        )
        
        查询优化(
            对子查询的优化(
                -- 优化前:找到啥活都接的同事
                SELECT a.user_name
                    , a.work_level
                    , (SELECT work_level FROM user2 b WHERE a.user_name = b.user_name) AS work_level2
                FROM user1 a;
                
                -- 优化后:找到啥活都接的同事
                SELECT a.user_name, a.work_level, b.work_level AS work_level2
                FROM user1 a
                LEFT JOIN user2 b ON a.user_name = b.user_name;
            )
        
            对聚合查询的优化(
                '未优化前的SQL语句'
                -- 在测试基线项目组员中,单轮找到bug最多的同事
                SELECT a.user_name, b.timestr, b.bug_nums
                FROM user1 a JOIN user_bugs b 
                ON a.id = b.user_id
                WHERE b.bug_nums = (
                    -- 找到测试定制项目成员中,找到bug最多的同事
                    SELECT MAX(c.bug_nums) FROM user_bugs c 
                    WHERE c.user_id = b.user_id
                );
                
                '使用JOIN优化聚合子查询'
                SELECT a.user_name, b.timestr, b.bug_nums
                    FROM user1 a
                    JOIN user_bugs b ON a.id = b.user_id
                    JOIN user_bugs c ON c.user_id = b.user_id
                    GROUP BY a.user_name, b.timestr, b.bug_nums
                HAVING b.bug_nums = MAX(c.bug_nums);
            )
        )
    )
    "
    MySQL必知必会
    Effective Mysql之备份与恢复(涵盖MySQL5.5 GA、MySQL5.6 DMR 和云计算中的MySQL)
    Effective Mysql之SQL语句最优化
    Effective Mysql之深入解析复制技术
    部分SQL Server的相关内容
    "
        命令行(
            mysql --help                                           -- 帮助
            mysql -u 用户名                                        -- 指定用户登录名
            mysql -u 用户名 -p -h myserver -P 9999                 --
    
            SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');
            
            show warnings;      -- 显示告警
        )
        
        配置(
        
            -- 获取MySQL数据库当前支持的系统版本
            SELECT LOWER(LEFT(VARIABLE_VALUE, 30)) AS os 
            FROM information_schema.global_variables 
            WHERE VARIABLE_NAME='version_compile_os';
        
        )
        
        元数据(
            DESC table_name;                                      -- 显示表结构
            DESCRIBE customers;                                   -- 显示表中的一列
            SHOW COLUMNS FROM customers;                          -- 显示表中的一列
            SHOW STAUS;
            SHOW CREATE DATA BASE;
            
            获取服务器元数据(
                SELECT VERSION()        -- 服务器版本字符串
                SELECT DATABASE()       -- 默认的数据库名称,如果没有则为空
                SELECT USER()           -- 客户端连接时给出的当前用户
                SELECT CURRENT_USER()   -- 用户用来检查客户端权限的
                SHOW GLOBAL STATUS      -- 服务器全局状态指示器
                SHOW VARIABLES          -- 服务器配置变量
                
                JDBC_code(
                    DatabaseMetaData md = conn.getMetaData();
                    //也可以使用 SELECT VERSION() 得到这个信息
                    System.out.println("Product version: " + md.getDatabaseProductVersion());
                    //这与 SELECT USER() 类似,但不包括主机名称
                    System.out.println("Username: " + md.getUserName());
                )
            )
        )
    
        限制(
            SELECT * FROME 表名 LIMIT 5;                          -- 查询表中前5行的结果
            SELECT * FROME 表名 LIMIT 3,4;                        -- 查询表中,从行3开始的4行数据
            SELECT * FROME 表名 LIMIT 3 OFFSET 4;                 -- 查询表中,从行3开始的4行数据
        )
        
        排序(
            SELECT * FROM 表名 ORDER BY 字段;                     -- 默认排序(A~Z)
            SELECT * FROM 表名 ORDER BY 字段 ASC;                 -- 升序排序(A~Z),ASC=ASCENDING
            SELECT * FROM 表名 ORDER BY 字段1, 字段2;             -- 两个条件默认排序
            SELECT * FROM 表名 ORDER BY 字段 DESC;                -- 降序
            SELECT * FROM 表名 ORDER BY 字段1 DESC, 字段2;        -- 字段1降序,字段2默认排序
            SELECT * FROM 表名 ORDER BY 字段1 DESC LIMIT 1;       -- 得到按字段1降序后的第一行
        )
        
        查询( 
            SELECT DISTINCT 字段 FROM 表名;                       -- 只返回不同的值
    
            SELECT * FROM 表名 WHERE 字段 <> 5;                   -- 字段不等于5
            SELECT * FROM 表名 WHERE 字段 BETWEEN 5 AND 10;       -- 字段区间[5,10]
            
            "
            原文:你可能希望返回具有NULL值得行,但不行。
                因为未知具有特殊含义,数据库不知道它们是否匹配,所以在匹配过滤或不匹配过滤时不返回它们。
                因此,在过滤数据时,一定要验证返回数据中确实给出了被过滤列具有NULL的行。
            "
            SELECT * FROM 表名 WHERE 字段 IS NULL;                -- 字段为空
            
            SELECT * FROM 表名 WHERE 条件1 OR 条件2;              -- 字段为空
            SELECT * FROM 表名 WHERE 条件1 AND 条件2;             -- 字段为空
            SELECT * FROM 表名 WHERE (条件1) AND (条件2);         -- 字段为空,推荐使用()明确地分组操作符
            
            --IN与OR的功能是相同的        
            SELECT * FROM 表名 WHERE 字段1 = 100 OR 字段1 = 200 ORDER BY 字段2;            -- 按字段2排序,返回字段1为100或200的结果
            
            SELECT * FROM 表名 WHERE 字段1 IN (100,200) ORDER BY 字段2;                     -- 按字段2排序,返回字段1为100或200的结果
            '
            IN的优点:
                    1、更清楚、直观;
                    2、计算的次序更易管理(因使用操作符更少);
                    3、执行更快;
                    4、可包含其他SELECT语句,更动态地建立WHERE语句。
            '
        
            SELECT * FROM 表名 WHERE 字段1 NOT IN (100,200) ORDER BY 字段2;                 -- 按字段2排序,返回字段1不是100和200的结果
            
            SELECT * FROM 表名 WHERE 字段 LIKE 'test%';                                     -- 结果以"test"开头
            SELECT * FROM 表名 WHERE 字段 LIKE '%test%';                                    -- 结果中包含"test"
            SELECT * FROM 表名 WHERE 字段 LIKE 'a%b';                                       -- 结果以a开头,以b结尾
            SELECT * FROM 表名 WHERE 字段 LIKE '_bc';                                       -- 结果以单个字符开头,其后内容为bc
            '
            _只能匹配单个字符,而%可以匹配多个字符
                使用通配符搜索处理时间较其他搜索所花费时间更长
                使用技巧:
                    1、尽量用其他操作符代替,非必要不用;
                    2、尽量不要放在搜索模式的开始处,否则搜索会更慢;
            '
            
            正则表达式(
                "正则表达式用来匹配文本的特殊字符串(字符集合)。"
                
                SELECT * FROM 表名 WHERE 字段 REGEXP '1000' ORDER BY 字段;                 -- 结果包含'1000'。并不比LIKE好,可能更差。
                SELECT * FROM 表名 WHERE 字段 REGEXP '.000' ORDER BY 字段;                 -- 结果包含'1000','2000'等
                SELECT * FROM 表名 WHERE 字段 REGEXP '1000|2000' ORDER BY 字段;            -- 结果包含'1000'或'2000'
                SELECT * FROM 表名 WHERE 字段 REGEXP BINARY 'AbC' ORDER BY 字段;           -- 结果区分大小写
                SELECT * FROM 表名 WHERE 字段 REGEXP '[123]xx' ORDER BY 字段;              -- 结果包含1xx或2xx或3xx
                SELECT * FROM 表名 WHERE 字段 REGEXP '^[123]xx' ORDER BY 字段;             -- 结果不包含1xx或2xx或3xx
                '
                [123]xx 与 [1|2|3]xx 等价
                    ^[123]xx表示不包含1xx或2xx或3xx;
                    [0123456789] 与 [0-9] 等价,表示匹配0~9的数字。[a-z]也同理。
                '
                
                SELECT 'hello' REGEXP '[0-9]'                                              -- 结果返回0(如有数字则返回1)
                
                SELECT * FROM 表名 WHERE 字段 REGEXP '\.' ORDER BY 字段;                  -- 结果包含特殊字符'.',\用来引导转义特殊字符。
                /* 需要转移的字符列表:
                    \f     换页
                    \n     换行
                    \r     回车
                    \t     制表
                    \v     纵向制表
                    \     反斜杠
                    为什么使用两个反斜杠(),MySQL自己用一个,正则用一个。
                */
                
                /* 常用正则:
                    [:alnum:]       任意字母和数字(同[a-zA-Z0-9])
                    [:digit:]       任意数字(同[0-9])
                    [:alpha:]       任意字符(同[a-zA-Z])
                    [:lower:]       任意小写字符(同[a-z])
                    [:upper:]       任意大写字符(同[A-Z])
    
                    [:xdigit:]       任意十六进制数字(同[a-fA-F0-9])
    
                    [:cntrl:]       ASCII控制字符(ASCII 0到31和127)
                    [:punct:]       既不在[:alnum:],又不在[:cntrl:]中的任意字符
                    
                    [:print:]       任意可打印字符
                    [:graph:]       与[:print:]相同,但不包含空格
    
                    [:blank:]       空格和制表(同[\t])
                    [:space:]       包括空格在内的任意空白字符(同[\f\n\r\t\v])
                */
                
                匹配多个实例(
                    
                    重复元字符(
                        /* 重复元字符列表:
                            *           0个或多个匹配
                            +           1个或多个匹配(同{1,})
                            ?           0个或1个匹配(同{0,1})
                            {n}         指定数目的匹配
                            {n,}        不少于指定数目的匹配
                            {n,m}       匹配数目的范围(m不超过255)
                        */
                        
                        SELECT * FROM 表名 WHERE 字段 REGEXP '\([0-9] sticks?\)' ORDER BY 字段;
                        /*
                            '\(' 和 '\)' 用来匹配括号;
                            'sticks?' 用来匹配 stick 和 sticks
                            搜索结果类似于:'1 stick' 和 '2 sticks' 等
                        */
                        
                        SELECT * FROM 表名 WHERE 字段 REGEXP '[[:digit:]]{4}' ORDER BY 字段;  -- 结果中包含任意四位数字
                        
                        SELECT * FROM 表名 WHERE 字段 REGEXP '[0-9][0-9][0-9][0-9]' 
                        ORDER BY 字段;                                                        -- 作用同上
                    )
    
                    定位符(
                        /* 定位符列表:
                            ^           文本的开始
                            $           文本的结尾
                            [[:         词的开始
                            [[:>:]]     词的结尾
                            
                        注意:
                            1、'^'还有另外一个用途————在集合中(用[和]定义),表示取反;
                            2、LIKE与REGEXP的区别在于——前者匹配整个字符串,后者匹配子串。LIKE等于REGEXP以^开始,以$结束。
                        */
    
                        SELECT * FROM 表名 WHERE 字段 REGEXP '^[0-9\.]' ORDER BY 字段;       -- 结果以一个数(包括小数点开的数)开始
                        -- 使用 [0-9\.] 和 [[:digit:]\.] 不行,因为它们会在文本任意位置查找匹配。
                    )
                )
            )
            
            计算字段(
                "
                存储在表中的数据都不是应用程序所需要的,我们需要直接从数据库中检索出转换、计算或格式化过的数据;
                    而不是检索出数据,然后再在客户机应用程序或报告程序中重新格式化。
                    字段(field)与列(column)基本相同,前者通常用在计算字段的连接上。
                "
                拼接(concatenate)(
                    "MySQL使用Concat()拼接多列数据,其他DBMS事情'+''||'来实现拼接。"
                    
                    输入:
                    SELECT CONCAT(rr.strName, '(', rr.strInterAreaCode, ')')
                    FROM regionres rr
                    ORDER BY rr.ID;    
                    
                    输出:
                    Embedded Net DVR_模拟通道_01(10000000001310607103)
                    Embedded Net DVR_模拟通道_02(10000000001310941706)
                    Embedded Net DVR_模拟通道_03(10000000001310607103)
                    ......
                )
    
                去掉空格(Trim)(
                    SELECT RTRIM(rr.strName) FROM regionres rr;                     -- RTRIM()去掉右侧多余的空格。 
                    SELECT LTRIM(rr.strName) FROM regionres rr;                     -- RTRIM()去掉左侧多余的空格。 
                    SELECT TRIM(rr.strName) FROM regionres rr;                      -- RTRIM()去掉左右两侧多余的空格。 
                )
                
                别名(alias)(
                    SELECT rr.strName AS str_name FROM regionres rr;
                    '
                    导出列别名有时也称为导出列(derivedcolumn)
                        其他用途:
                            1、在实际的表列名包含不符合规定的字符(如空格)时重新命名它;
                            2、在原来的名字含混或容易误解时扩充它等。
                    '
                )
    
                算术计算(
                    /* 算术计算操作符:
                        +   加
                        -   减
                        *   乘
                        /   除
                        此外,圆括号可以用来区分优顺序。
                    */
                    SELECT rr.ID * rr.nMultID AS mult_id FROM regionres rr;
                )
            )
            
            数据处理函数(
                "
                函数的可移植性(portable)没有SQL语言强,使用时须做好注释。
                大多数SQL实现支持以下函数:
                    1、文本串(如删除或填充值,转换值为大写或小写)的文本函数;
                    2、算术计算函数;
                    3、日期和时间值并从中提取特定成分(如,返回两个日期的差,检查日期有效性等);
                    4、返回DBMS正使用的特殊信息(如用户登录信息,检查版本细节)的系统函数。
                "
               
                SELECT UPPER(rr.strName) AS str_name FROM regionres rr;             -- 文本大小写转换
               
                文本处理函数(
                    /* 文本处理函数:
                        LEFT()          串的左侧字符
                        RIGHT()         串的右侧字符
                        LENGTH()        串的长度
                        LOCATE()        找出一个子串
                        LOWER()         转换为小写
                        UPPER()         转换为大写
                        TRIM()          去掉左右侧空格
                        LTRIM()         去掉左侧空格
                        RTRIM()         去掉右侧空格
                        SOUNDEX()       串的SOUNDEX值
                        SUBSTRING()     子串的字符
                        
                        此外,SOUNDEX的意思:
                            1、是将任何文本串转换为描述其语音表示的字母数字模式的算法。
                            2、其考虑了发音字符合音节,使得能对串进行发音比较而不是字母比较。
                            3、虽然其不是SQL概念,但多数DBMS都对其支持。
                   */
                   
                    输入:
                    SELECT rr.strName AS str_name 
                    FROM regionres rr
                    WHERE SOUNDEX(rr.strName) = SOUNDEX('ENat DVR_模拟_01');      -- 可解决英文的拼写错误
                    
                    输出:
                    ENet DVR_模拟_01
                )
    
                日期和时间处理函数(
                    /* 常用日期和时间处理函数:
                        AddDate()       增加一个日期(天、周等)
                        AddTime()       增加一个时间(时、分等)
                        CurDate()       返回当前日期
                        CurTime()       返回当前时间
                        Date()          返回日期时间的日期部分
                        DateDiff()      计算两个日期之差
                        Date_Add()      高度灵活的日期运算函数
                        Date_Format()   返回一个格式化的日期或字符串
                        Day()           返回一个日期的天数部分
                        DayOfWeek()     返回一个日期对应的星期几
                        Hour()          返回时间的-时
                        Minute()        返回时间的-分
                        Second()        返回时间的-秒
                        Year()          返回日期的-年
                        Month()         返回日期的-月
                        Time()          返回日期的-时间
                        Now()           返回当前日期和时间
                    */
    
                    SELECT * FROM biao WHERE DATE(dt_order) = '2015-09-01';
                
                    SELECT * FROM biao WHERE DATE(dt_order) BETWEEN '2015-09-01' AND '2015-09-30';
                
                    SELECT * FROM biao WHERE YEAR(dt_order) = 2015 AND MONTH(dt_order) = 9;
                )
                
                数值处理函数(
                    /* 常用数值处理函数:
                        Abs()       绝对值
                        Cos()       余弦
                        Exp()       指数
                        Mod()       余数
                        Pi()        圆周率
                        Rand()      随机数
                        Sin()       正弦
                        Sqrt()      平方根
                        Tan()       正切
                    */
                )
            )
            
            汇总数据(
                /*
                常见的聚集函数:
                    AVG     平均值
                    COUNT   行数
                    MAX     最大值
                    MIN     最小值
                    SUM     和
                */
            )
            
            联结表(
                "
                关系表设计:
                    保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系relational)互相关联。
                    相同数据出现多次决不是件好事,此为关系数据库设计之基础。
                    
                可伸缩性(sacle):
                    能够适应不断增加的工作量而不失败。设计良好的数据库称为可伸缩性好(scale well)。
                    
                维护应用完整性:
                    指示MySQL只允许表中的外键是合法值,即外键值是存在另一个表中的。可通过指定主键和外键来实现。
                    
                完全限定列名:
                    为防止出现二义性,必须使用完整的限定列名(用一个点分割表名和列名)。
                "
                
                "
                例子:
                    超市存储产品信息
                    -->有很多供应商(供应商信息),有很多产品(产品信息)
                    -->同一个供应商的产品的供应商信息相同,可以统一保存,更新时只在一处变动即可。
                    -->如果产品信息和供应商信息保存在一处,很难保证每次输入数据方式都相同。
                    
                    因此,可建2个表: vendors(供应商信息),products(产品信息)。
                    每个供应商都有唯一标识符,即主键(primarykey)。
                    products表只存储vendors表的主键,vendors表的主键又称为products表的外键。
                    
                "
                
                SELECT b1.name, b2.name     -- 查询结果
                FROM biao_1 b1, biao_2 b2   -- 相关的表
                WHERE b1.id = b2.id         -- 过滤条件
                ORDER BY b1.name, b2.name;  -- 排序方式
                '
                如果去掉WHERE子语句(联结条件),将出现笛卡尔积。检索出的行数目 = 表1行数 * 表2行数。
                '
            )
            
            高级联结(
                MySQL_JOIN.sql
            )
            
            组合查询(
                "
                执行多个查询,并将结果作为单个查询结果集返回。称为:并(union)或复合查询(compoundquery)。
                需要使用组合查询的条件:
                    1、在单个查询中,从不同表返回类似结构的数据;【单查询,多表】
                    2、对单个表执行多个查询,按单个查询返回数据。【单表,多查询】
                注意:
                    1、组合查询和对个WHERE条件,作用相同,可相互替换;
                    2、UNION必须包含相同的列、表达式或聚集函数(列顺序可不同);
                    3、列数据类型必须兼容,不必完全相同,但必须是DBMS可隐含地转换的类型;
                    4、可使用UNION ALL取消自动去重,UNION ALL与WHERE不能相互替换。
                    5ORDER BY只在最后一条语句中有效,并排序所有的结果。
                "
                
                单表多查询(
                    '查询1'
                    SELECT Z_1, Z_2, Z_3 FROM B WHERE Z_1 <= 5;
                    
                    '查询2'
                    SELECT Z_1, Z_2, Z_3 FROM B WHERE Z_3 IN (10, 50);
                    
                    '组合查询'
                    SELECT Z_1, Z_2, Z_3 FROM B WHERE Z_1 <= 5
                    UNION
                    SELECT Z_1, Z_2, Z_3 FROM B WHERE Z_3 IN (10, 50);
                    
                    '多个WHERE'
                    SELECT Z_1, Z_2, Z_3 FROM B WHERE Z_1 <= 5 OR Z_3 IN (10, 50);
                )
            )
            
            全文本搜索(
            )
        )
        
        插入数据(
            "
            注意:
                总是使用列的列表一般不要使用没有明确给出列的列表的INSERT语句。
                使用列的列表能使SQL语句继续发挥作用,即使表结构发生了变化。
                
                省略部分列:
                    如果表的定义允许,可以再INSERT时省略部分列。满足条件:
                        1、该列允许NULL值(无值或空值);
                        2、表定义中给出默认值;
    
                    如果表中不允许NULL值且没有默认值得列不给值,将产生一个错误消息,操作失败。
                
                提高性能:
                    数据库常被多个用户访问,对处理什么请求以及用什么次序处理进行管理是MySQL的任务。
                    INSERT操作可能很耗时(特别是有很多索引需要更新时),而且它可能降低等待处理的SELECT语句的性能。
                    
                    如果数据检索是最重要的(通常是这样),可使用LOW_PRIORITY指示MySQL降低INSERT语句的优先级:
                        INSERT LOW_PRIORITY INTO ......
                    上述,同样适用于UPDATE和DELETE。
            "
            
            INSERT INTO biao(f1, f2, f3...) VALUES(v1, v2, v3...);                  -- 插入单条
            
            INSERT INTO biao(f1, f2, f3...) VALUES(v1, v2, v3...),(v1, v2, v3...);  -- 插入多条
            
            INSERT LOW_PRIORITY INTO biao(f1, f2, f3...) VALUES(v1, v2, v3...);     -- 降低INSERT的优先级,同样适用于UPDATE和DELETE。
            
            INSERT INTO biao_1(f1, f2, f3...) SELECT f1, f2, f3... FROM biao_2;     -- INSERT与SELECT组合,将biao_2数据合并到biao_1中。
        )
            
        更新和删除数据(
            更新(
                "为安全起见,需要限制UPDATE语句的使用。在安全管理章节有详细介绍。"
                
                UPDATE biao SET f1 = v1 WHERE id = 1000;                                -- 更新单个列,WHERE控制更新几行
                
                UPDATE biao SET f1 = v1, f1 = 'v2' WHERE id = 1000;                     -- 更新多个列,WHERE控制更新几行
                
                UPDATE IGNORE biao ...                                                  -- 更新多行,忽略所有错误。
                '注意:
                    UPDATE更新多行,如果出现一次错误,整个操作将被取消(错误前的所有数据将被恢复原来的值)。
                    使用IGNORE后,即使发生错误,也继续更新。
                '
                
                UPDATE biao SET f1 = NULL WHERE id = 1000;                              -- 清空某些值
            )
    
            删除(
                "为安全起见,需要限制UPDATE语句的使用。在安全管理章节有详细介绍。"
    
                DELETE FROM biao WHERE id = 1000;   -- 逐行删除
    
                TRUNCATE TABLE biao;                -- 更快地删除表的方法,删除原表,再重新创建一个。         
            )
            
            " 
            UPDATE和DELETE的注意事项:
                1、除非确定,否则必须带WHERE;
                2、保证每个表都有主键(见 联结表),尽可能像WHERE子句那样使用它(可指定各主键、多个值或值的范围);
                3、使用WHERE前,要用SELECT测试下。保证WHERE语句正确;
                4、使用强制实施引用完整性的数据库(见 联结表),这样MySQL将不允许删除具有与其他表相关联的数据的行;
                5、小心使用,成功后不可撤销。
            "
        )
        
        创建和操纵表(
            创建表(
            )
            
            更新表(
            )
            
            删除表(
                DROP TABLE table_name;
            )
            
            重命名(
                RENAME TABLE table_name1 TO table_name2;
            )
        )
        
        视图(
            "视图是虚拟的表。只包含使用时动态检索数据的查询。
            为何要用:
                1、重用SQL语句;
                2、简化复杂SQL语句,封装基本查询细节;
                3、使用表的组成部分,而非整个表;
                4、保护数据。可给用户授权表的部分字段的访问,而非整个表;
                5、更改数据格式和表示。视图返回与底层表的格式不同的数据。
            性能问题:
                因其不包含数据,每次查询都要执行所需的所有检索。
                以下情况性能下降很严重:
                    1、视图以多个联结和过滤创建;
                    2、嵌套视图。
            注意事项:
                1ORDER BY可被视图使用,但如果从视图检索数据SELECT中也含有ORDER BY,那么视图中的ORDER BY将被覆盖;
                2、视图不能索引,也不能有关联的触发器或默认值。
            "
    
            创建、查看、删除和使用(
                -- 创建视图(如果存在则更新,否则创建)
                CREATE OR REPLACE VIEW test1 AS
                SELECT rr.strName AS r_name, d.strName AS d_name
                FROM regionres rr, device d
                
                -- 查看创建视图的语句
                SHOW CREATE VIEW test1;
                
                -- 删除视图
                DROP VIEW test1;
                
                -- 使用视图
                SELECT * FROM test1;
            )
                
            格式化输出(
                -- 原始常用语句
                SELECT CONCAT(RTRIM(rr.strName), '(', RTRIM(rr.strInterAreaCode), ')') AS name_index
                FROM regionres rr
                ORDER BY rr.ID ASC;
                
                -- 使用视图简化细节
                CREATE OR REPLACE VIEW rr_name_index AS
                SELECT CONCAT(RTRIM(rr.strName), '(', RTRIM(rr.strInterAreaCode), ')') AS name_index
                FROM regionres rr
                ORDER BY rr.ID ASC;
                
                -- 调用视图完成格式化数据
                SELECT * FROM rr_name_index;
            )
            
            更新视图(
                "更新一个视图将更新其基表,但以下情况将无法更新:
                    1、分组(使用GROUP BYHAVING);
                    2、联结;
                    3、子查询;
                    4、并;
                    5、聚集函数(MIN()、COUNT()、SUM()等);
                    6DISTINCT7、导出(计算)列。
                注意:视图用来检索(SELECT),而非更新(INSERTUPDATE、DELECT)。
                "
            )
        )
        
        函数(
            "
            用户自定义函数(user-defined function,UDF)是一种MySQL的扩展途径,其用法与内置函数相同。
            参数和返回值.
            复合结构必须用BENGIN和END包含。
            "
    
            CREATE FUNCTION  function_name
            RETURNS
            {STRING|INTEGER|REAL|DECIMAL}
            routine_body
    
            -- 无参数的函数
            CREATE FUNCTION get_data() RETURNS VARCHAR(30)
            RETURN DATA_FORMAT(NOW(), "%Y-%m-%d %H:%i:%s");
    
            -- 有参数的函数
            CREATE FUNCTION get_avg(num1 SMALLINT UNSIGNED, num2 SMALLINT UNSIGNED) 
            RETURNS FLOAT(10, 2) UNSIGNED
            RETURN (num1 + num2) / 2;
    
            -- 复合结构函数
            DELIMITER //
            CREATE FUNCTION get_last_id() RETURNS INT UNSIGNED
            RETURN SELECT MAX(id) FROM users;
            //
            CREATE FUNCTION add_user(user_name VARCHAR(20)) RETURNS INT UNSIGNED
            BEGIN 
                INSERT users (user_name) VALUES (user_name);
                RETURN get_last_id();
            END
            //
            DELIMITER ;
        )
    
        存储过程(
            "
            SQL语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理。节省了语法分析和编译时间,提高了效率。
            优点:
                1、增强功能和灵活性;
                2、实现较快的执行速度;
                3、减少了网络流量。
    
            注意:
                只能用于增删改查,不能创建数据表和数据库。
                参数名不能与数据库表中的名称相同。
            "
    
            表达式(
                CREATE
                [DEfINER = {user | CURRENT_USER}]
                PROCEDURE sp_name ([proc_parameter[,...]])
                [characteristic ...] routine_body
    
                proc_parameter:
                [IN | OUT | INOUT] param_name type
            )
    
            -- 无参数的存储过程
            CREATE PROCEDURE get_user_name() SELECT user_name FROM users;
    
            -- 带IN和OUT参数的存储过程
            DELIMITER //
            CREATE PROCEDURE del_user_by_id
            (
                IN user_id INT UNSIGNED
                , OUT del_count INT UNSIGNED
                , OUT user_nums INT UNSIGNED
            )
            BEGIN
                DELETE FROM users WHERE id = user_id;
                SELECT ROW_COUNT() INTO del_count;
                SELECT COUNT(1) FROM users INTO user_nums;
                
                -- 后者会覆盖前者
                SET @sql_exec = CONCAT('SELECT strName INTO @a FROM Device');
                PREPARE stm1 FROM @sql_exec;
                EXECUTE stm1;
                SELECT @a;
                DEALLOCATE PREPARE stm1;
            END
            //
            DELIMITER ;
    
            -- 调用存储过程
            CALL del_user_by_id(3, @a, @b);
    
            -- 获取结果
            SELECT @a, @b;
    
            -- 删除存储过程
            DROP PROCEDURE IF EXISTS del_user_by_id;
    
            存储过程与函数的区别(
                "
                1、存储过程较复杂,函数针对性更强;
                2、存储过程返回值多,函数只能有一个返回值;
                3、存过一般独立执行,函数作为其他SQL语句的组成部分。
                "
            )
    
            IVMS8100v3-mysql数据库示例(
                
                错误方式(
                    -- 删除旧用户
                    DROP USER 'root'@'%';
                    DROP USER 'root'@'localhost';
                    DROP USER 'root'@'127.0.0.1';
    
                    -- 创建新用户
                    DROP USER 'root'@'%';
                    CREATE USER 'root'@'%' IDENTIFIED BY '888';
                    GRANT GRANT OPTION ON *.* TO 'root'@'%';
                    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'root'@'%' WITH GRANT OPTION;
                )
                
                -- 开启创建存储过程的权限,然后重启mysql数据库
                UPDATE mysql.`user` AS sys_u SET 
                    sys_u.Create_routine_priv = 'Y', 
                    sys_u.Alter_routine_priv = 'Y',
                    sys_u.Execute_priv = 'Y'
                WHERE sys_u.`Host` = '%'; -- 用户为:'root'@'%'
    
                
                -- 创建存储过程
                USE ivms8100v3;
                DELIMITER //
                DROP PROCEDURE IF EXISTS get_reg_size;
                CREATE PROCEDURE get_reg_size()
                BEGIN
                    SELECT COUNT(1) AS 'reg_size' FROM Region;
                END //
                DELIMITER ;
    
                -- 调用存储过程 
                CALL get_reg_size()
            )
        )
        
        游标(
            "
            游标(cursor)提供在检索出的结果集中前进或后退的功能。
            不像其他DBMS,MySQL只能用于存储过程或函数。
            主要用于交互式应用,用户根据需要滚动屏幕上的数据,并对其浏览或更改。
            "
    
            CREATE PROCEDURE get_all_users()
            BEGIN
                --声明本地变量
                DECLARE done BOOLEAN DEFAULT 0;
                DECLARE n INT;
    
                -- 创建游标
                DESCRIBE user_id CURSOR
                FOR
                SELECT id FROM users;
    
                -- 声明continue句柄
                DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
    
                -- 打开
                OPEN user_id;
    
                -- 执行循环
                REPEAT
                    -- 相关操作
                    FETCH user_id INTO n;
                -- 循环结尾
                UNTIL done END REPEAT;
    
                -- 关闭
                CLOSE user_id;
            END;
        )
        
        触发器(
            "
            在某个表发生更改(DELETEINSERTUPDATE)时自动处理某些事情。
            
            创建触发器:
                1、唯一的名;
                2、关联的表;
                3、响应活动(DELETEINSERTUPDATE);
                4、何时执行(处理前/后)。
    
            注意:
                触发器只支持表,不支持触发器和临时表。
            "
    
            INSERT触发器(
                "
                INSERT触发器,注意:
                    1、可使用NEW访问被插入的数据;
                    2、BEFORE INSERT 触发器允许更改被插入的值;
                    3、AUTO_INCREAMENT列,NEW在INSERT执行前包含0,在INSERT执行后包含心的自增长值。
                "
                -- 创建一个INSERT触发器,插入完成后返回插入的ID。
                CREATE TRIGGER new_user
                AFTER INSERT ON users 
                FOR EACH ROW SELECT NEW.id;
    
                -- 执行插入语句
                INSERT INTO users(str_name, str_tel)('xuejianhui', '15657119571');
            )
    
            DELETE触发器(
                "
                DELETE触发器,注意:
                    1、可使用OLD访问只读的被删除的行;
                "
                -- 创建一个DELETE触发器,将实时日志中被删除的数据插入到历史日志表。
                CREATE TRIGGER delete_real_logs
                BEFORE DELETE ON real_logs
                FOR EACH ROW
                BEGIN
                    INSERT INTO history_logs(...) VALUES(...);
                END;
            )
    
            UPDATE触发器(
                "
                UPDATE触发器,注意:
                    1、NEW和OLD都可用;
                    2、BEFORE UPDATE中,允许更改NEW中的值;
                    3、OLD中的值为只读。
                "
                -- 创建一个UPDATE触发器,更新用户表时转换名称的大小写。
                CREATE TRIGGER update_user_name
                BEFORE UPDATE ON users
                FOR EACH ROW
                SET NEW.str_name = UPPER(NEW.str_name);
            )
    
            -- 删除触发器
            DROP TRIGGER new_user;
    
            总结(
                "
                注意:
                    1、创建触发器可能需要特殊的安全访问权限;
                    2、触发器可用来检查数据的一致性;
                    3、可用来记录操作流水;
                    4、MySQL触发器不支持调用存储过程。
                "
            )
        )
        
        事务_MySQL(
            "
            可用来维护数据库的完整性,保证完全执行,要么完全不执行。
            MyISAM不支持,InnoDB支持;
    
            注意:
                只支持DELETE、INSERTUPDATE,不支持CREATE和DROP。
    
            事务(Transaction):
                原子性(Atomicity)  : 一个事务不可分割,要么做要么不做。
                一致性(Consistency): 使DB从一个一致性状态到另一个一致性状态。
                隔离性(Isolation)  : 并发执行的各事务互不干扰。
                永久性(Durability) : 一旦执行完,数据永久不改变。
              
            术语:
                事务(TRANSACTION) :把一组SQL语句组装为逻辑快;
                回退(ROLLBACK)    :反悔;
                提交(COMMIT)      :成交;
                保留点(SAVEPOINT) :在事务中设置临时占位符(place-holder),部分回退。
            "
    
            场景(
                order 表保存订单;
                orderitems 表存储订单的各项物品。
                ID为主键,并互相关联。
            ) 
    
            -- 开始事务,删除订单货物的同时,删除订单。
            START TRANSACTION;
            DELETE FROM orderitems WHERE order_num = 1111;
            DELETE FROM order WHERE order_num = 1111;
            COMMIT;
    
            保留点(
                -- 设置保留点,名称要唯一。
                SAVEPOINT oper_1;
    
                -- 回滚保留点,ROLLBACK或COMMIT后保留点将被释放。
                ROLLBACK TO oper_1;
    
                -- 自MySQL 5.0以来,可明确地释放保留点。
                RELEASE SAVEPOINT;
            )
    
            更改默认提交行为(
                -- 取消默认的自动提交更改,针对的是连接级别,而不是服务器。
                SET autocommit = 0;
            )
        )
    
        事务_MSSQL(
            "
            事务(Transaction)
                原子性(Atomicity)  : 一个事务不可分割,要么做要么不做。
                一致性(Consistency): 使DB从一个一致性状态到另一个一致性状态。
                隔离性(Isolation)  : 并发执行的各事务互不干扰。
                永久性(Durability) : 一旦执行完,数据永久不改变。
            "
            原子性例子(
                -- 创建个按钮表,约束列ID只为5
                CREATE TABLE Test
                (
                    ID INT,
                    CONSTRANINT CheckID
                    CHECK(ID=5)
                );
    
                -- 插入两条数据,一个数据是5,另一个数据是6
                INSERT INTO Test(ID) VALUES (5), (6);
    
                -- 因6不符合规范,因此没有数据被插入
                SELECT * FROM Test;
    
                --新建一个事务
                BEGIN TRANSACTION;
    
                INSERT INTO Test(ID) VALUES (5);
    
                --提交一个事务
                COMMIT TRANSACTION;
    
                --回滚一个事务
                ROLLBACK TRANSACTION;
            )
    
            一致性例子(
                --创建一张主表
                CREATE TABLE TableA
                (
                    ID INT PRIMARY KEY
                );
    
                INSERT INTO TableA VALUES(1);
    
                --创建一张从表
                CREATE TABLE TableAChild
                (
                    ID INT PRIMARY KEY,
                    Col INT,
                    CONSTRANINT FK_S FOREIGN KEY (Col) REFERENCES TableA(ID) --外键
                );
    
                INSERT INTO TableAChild VALUES(1,1);
    
                --删除主表的列,由于此列在从表中有引用,
                --为了保证DB事务一致性,此操作会被禁止
                DELETE TableA;
    
                DROP TABLE TableAChild
                GO;
    
            )
        )
        
        全球化和本地化(
        )
    
        安全管理(
            备份(
                -- 备份前需要确定这个备份文件的大小,本地磁盘是否有足够的空间存储。
                SELECT 
                    ROUND(SUM(data_length+index_length)/1024/1024) AS total_mb,
                    ROUND(SUM(data_length)/1024/1024) AS data_mb,
                    ROUND(SUM(index_length)/1024/1024) AS index_mb
                FROM information_schema.`TABLES`;
            )
        )
        
        维护(
        )
        
        改善性能(
        )
        
        集群(
            同步集群(
                "
                mysql cluster(data + sql + mgm节点)
                特点:
                    1)  内存级别的,对硬件要求较低,但是对内存要求较大。换算比例为:11.12)  数据同时放在几台服务器上,冗余较好;
                    3)  速度一般;
                    4)  建表需要声明为engine=ndbcluster
                    5)  扩展性强;
                    6)  可以实现高可用性和负载均衡,实现对大型应用的支持;
                    7)  必须是特定的mysql版本,如:已经编译好的max版本;
                "
            )
            
            异步集群(
                "
                mysql replication(master + slave)
                特点:
                    1)  主从数据库异步数据;
                    2)  数据放在几台服务器上,冗余一般;
                    3)  速度较快;
                    4)  扩展性差;
                    5)  无法实现高可用性和负载均衡(只能在程序级别实现读写分离,减轻对主数据库的压力);
                    6)  配置和管理较差,可能会丢失数据;
                "
            )
    
            负载均衡(
                "
                通过director,将用户的请求分发到real?server服务器上,然后返回给用户。
                负载均衡部署灵活、能够满足各种需求。
                实现方式:
                    硬件:BIG/IP、Cisco、IBM(昂贵)
                    软件:LVS(免费)
                        LVS系统将用户的请求的数据包在数据层和网络层进行了封装和转发,由三种方式满足各种需求。
                        1)  DR:直接路由
                        2)  Tuning:tcp/ip隧道
                        3)  NAT:网络地址转换
                "
            )
        )
        
        优化(
            书籍(
                《数据库系统概论》
                《数据库查询优化器的艺术——原理解析与SQL性能优化》
                《The Art of Database Query Optimizer》
                《Principle SQL Performance Optinization》
                《Postgre SQL数据库内核分析》
            )
            
            "
            解决实际问题:查优原理+工程实施角度=DBMS查优
            "
            
            逻辑优化(
                关系代数的等价变换
                重写(关系代数)
            )
            
            物理优化(
                数据读取,表连接方式、顺序、排序
                算法优化(最小花费技术)
            )
        )
    MySql技巧个人笔记 
    1.数据null时sum的用法
    mysql数据库SUM(A+B)不一定等于SUM(A)+SUM(B),当A或B为NULL时,SUM(A+B)=NULL2.or改为in
             同一字段,将or改写为in()。OR效率:O(n);IN效率:O(Log n);当n很大时,OR会慢很多。注意控制in的个数,建议n小于200。
    
    3. or和union的效率
    (1)不同字段,将or改为union。
    
    (2)相同字段(针对单表操作)
           对于索引列来最好使用union all,因复杂的查询【包含运算等】将使or、in放弃索引而全表扫描,除非你能确定or、in会使用索引。对于只有非索引字段来说你就老老实实的用or 或者in,因为 非索引字段本来要全表扫描而union all 只成倍增加表扫描的次数。对于及有索引字段【索引字段有效】又包含非索引字段来时,按理你也使用or 、in或者union all 都可以,但是我推荐使用or、in4.union all与union
           若无需对结果进行去重,则用union all 而非union;union会自动对结果去重,有去重开销。
    5.Group by去除排序
          Gourp by 实现分组、自动排序。则无需排序:order by null6.将字符转换为数字
          数字型VS字符串型索引:数字型更高效、查询更快、占用空间更小。
    7.拒绝大SQL
            拒绝大sql,拆解成多条简单sql:
    (1)可能一条大sql就把整个数据库堵死;
    (2)简单sql缓存命中率更高;
    (3)减少锁表时间,特别是MyISAM;
    (4)用上多cpu,一条sql只能在一个cpu中运行。
    8Load data导数据
               批量数据块导入:
    (1)成批装载比单行装载更快,不需要每次都刷新缓存;
    (2)无索引装载比索引装载更快;
    (3Insert values,values,values减少索引刷新;
    (4Load data 比Insert快约20倍
             尽量不要用insert….select….
    (1) 延迟
    (2)同步出错
    9.打散大批量更新
    (1)大批量更新凌晨操作,避开高峰
    (2)凌晨不限制
    (3)白天上限默认为100条/秒(特殊再议)
    
    10. mysql int(3)与int(11)的区别
           总结,int(M) zerofill,加上zerofill后M才表现出有点点效果,比如 int(3) zerofill,你插入到数据库里的是10,则实际插入为010,也就是在前面补充加了一个0.如果int(3)和int(10)不加 zerofill,则它们没有什么区别.M不是用来限制int个数的.
           注意:这里的M代表的并不是存储在数据库中的具体的长度,以前总是会误以为int(3)只能存储3个长度的数字,int(11)就会存储11个长度的数字,这是大错特错的。
          其实当我们在选择使用int的类型的时候,不论是int(3)还是int(11),它在数据库里面存储的都是4个字节的长度,在使用int(3)的时候如 果你输入的是10,会默认给你存储位010,也就是说这个3代表的是默认的一个长度,当你不足3位时,会帮你不全,当你超过3位时,就没有任何的影响。
    11.count(distinct field)是魔鬼
          Count(distinct field)查询效率极低,数据量大时甚至会爆出内存不足。优化技巧:使用临时表概念,先把distinct的field 经过group by过滤后,再对其进行count计算。
    优化前:
    
    优化后:
    
     
    12.mysql函数
    (1)replace函数
       Update tr_app_data  set content = replace(content,'SGSN206','SGSN1') where app_data_cat='AlarmMonitor_Widget_195'2)concat函数
    select concat(LAC,'_',CI) from `sheet1`
    (3)IFNULL函数
           IFNULL(expr1,expr2) ,如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2。IFNULL()返回一个数字或字符串值。
    (4)IF函数
          如果expr1是TRUE(expr1<>0且expr1<>NULL),那么IF()返回expr2,否则它返回expr3。IF()返回一个数字或字符串值,取决于它被使用的上下文。
    (5CASE WHEN函数
          Case具有两种格式。简单Case函数和Case搜索函数
         --简单Case函数 如果case有条件,when 只能是对条件值的罗列,不能再加条件,否则出错  
     
    
    CASE sex   
    
    WHEN '1' THEN ''   
    
    WHEN '2' THEN ''   
    
    ELSE '其他' END  
    
    如果case 没有条件,when 里面可以加个条件判断
     
     
    --Case搜索函数  
     
     
    CASE WHEN sex = '1' THEN ''   
    
    WHEN sex = '2' THEN ''   
    
    ELSE '其他' END  
    13.单表去重并保留id最小的一条
          数据库现在不支持这样的操作(对一个表进行select等子操作后,然后对该表做delete或者updata这类的操作。so,可以用临时表解决。如下:
    DELETE FROM table_test WHERE id NOT IN (SELECT id FROM (SELECT MIN(id) AS id FROM table_test AS t GROUP BY uid) t1);
  • 相关阅读:
    php数组函数-array_push()
    php数组函数-array_pop()
    php数组函数-array_pad()
    php数组函数-array_merge()
    php数组函数-array_map()
    php数组函数-array_keys()
    php数组函数-array_key_exists()
    php数组函数-array_intersect()
    php数组函数-array_flip()
    php数组函数-array_filter()
  • 原文地址:https://www.cnblogs.com/youdream/p/9001658.html
Copyright © 2011-2022 走看看