数据查询与存储过程

1》查询语句的基本语法

   语法:
      SELECT 属性列表
      FROM 表名
      [WHERE 条件表达式 1]
      [GROUP BY 属性名1 [HAVING 条件表达式2]]
      [ORDER BY 属性名2 [ASC | DESC]]
      属性列表表示需要查询的字段名
      表名表示指的表名
      WHERE 表示指定查询的条件
      GROUP BY 指定的字段进行分组
      如果GROUP BY 子句后面带着HAVING关键字,那么只有满足条件2才能输出。

2》在单表上查询数据:
  v 列出表的所有字段
    root@zytest 16:19>select order_num,order_date,cust_id from orders;

  v 使用*查出单表所有字段
    root@zytest 16:22>select * from orders;

  v 查询指定的字段
    在orders表中有3个字段,order_num、order_date、cust_id,我们查询其中2个。
    root@zytest 16:22>select order_num,order_date from orders;

  v where查询指定记录
    root@zytest 16:53>select * from orders where cust_id=10003;

         *****比较
    root@zytest 16:53>select * from orders where cust_id<=10003;小于或者等于
    root@zytest 16:56>select * from orders where cust_id>=10003;大于或者等于
    root@zytest 16:56>select * from orders where cust_id>10003;大于
    root@zytest 16:56>select * from orders where cust_id<10003;小于
    root@zytest 16:57>select * from orders where cust_id != 10003; 不等于
    root@zytest 16:57>select * from orders where cust_id <> 10003;排除掉10003

             

            指定范围
      root@zytest 16:57>select * from orders where cust_id between 10003 and 10004;
      root@zytest 16:57>select * from orders where cust_id not between 10003 and 10004;

    指定集合
      root@zytest 16:57>select * from orders where cust_id in(10001,10004);
      root@zytest 16:57>select * from orders where cust_id not in(10003,10004);

   匹配字符
      root@zytest 16:57>select * from orders where cust_id like ‘10001’;
      root@zytest 16:57>select * from orders where cust_id not like ‘10001’;

     是否为空值
      root@zytest 16:57>select * from vendors where vend_state is null;
      root@zytest 16:57>select * from vendors where vend_state is not null;

   多条件查询
      root@zytest 16:57>select * from orders where cust_id=10003 and order_num=20005;
      root@zytest 16:57>select * from orders where cust_id=10003 or cust_id=10005;

          查询结果不重复(distinct)字段名
     语法:select distinct 字段名
        select distinct cust_id from orders;

   查询结果进行排序
     语法:order by 属性名 [ASC|DESC]
        select distinct cust_id from orders where cust_id>10003 order by cust_id desc;

      查询数据进行分组group by
        语法:group by 属性名 [having 条件表达式][with rollup]
        having用来限制分组后的显示,满足条件表达式的结果将被显示
        with rollup 关键字将会在所有记录的最后加上一条记录,该记录是上面所有记录的总和.
        group关键字通常和group_concat()函数一起使用.group_concat把每个分组指定的字段值显示出来.

                   

             group by 使用having条件约束过滤having 跟where作用一样。但是having只能用于group by 。
      select sex,count(sex),group_concat(name) from student group by sex having sex='女';

    group by 多个字段进行分组
    select sex,count(sex),group_concat(name) from student group by sex,user_id having sex='女';

    group by 与with rollup一起使用

    root@zytest 10:02>select sex,count(sex) from student group by sex;
      得出了分组出来的数量。如果想得到分组出来的总和怎么办?
      我们后面再加上with rollup就可以得出。
    root@zytest 10:02>select sex,count(sex) from student group by sex with rollup;

    对单个字段进行普通分组
    root@zytest 06:56>select * from student group by address;
    结合group_concat()进行指定每个分组的值
    root@zytest 08:48>select sex,group_concat(name) from student group by sex;

                  

           使用limint限制查询结果的数量
    root@zytest 10:07>select * from student where user_id >2 limit 2;

3》使用集合函数查询数据

  集合函数包括:
    count() 用来统计记录的条数
    sum() 用来计算字段的值和总数
    avg() 用来计算字段的值的平均值
    max() 用来查询字段的最大值
    min() 用来查询字段的最小值

    count()总计所有记录的条目总数
    root@zytest 10:24>select count(*) from student;
    sum字段值得总和
    root@zytest 10:25>select
sum(user_id) from student;
    avg 取平均值
    root@zytest 10:25>select avg(user_id) from student;
    max()取字段值得最大值
    root@zytest 10:27>select
max(user_id) from student;
    min()取字段值得最小值
    root@zytest 10:28>select min(user_id) from student;

4》多表连接查询

  1>内连接
    具有相同意义的字段,才可以进行内连接:
    root@zytest 15:56>select cust_name,cust_address,order_date from customers,orders
    where customers.cust_id=orders.cust_id;

         2>外连接
    外连接包括左查询和右查询
    select属性名列表
    from 表名1 left | right join 表名2 on 表名1.属性名=表名2.属性名;

    左连接查询:
    可以查询出表名1里面所有的数据,而表名2只能查出匹配的记录。
    以下例子:表名1=vendors(主表)表名2=products(匹配表)
    root@zytest 17:42>select vendors.vend_id,prod_name,prod_price from vendors left join products on
    vendors.vend_id=products.vend_id;

    右连接查询
    可以查询出表名2所有的记录。而表名1只能查出匹配记录。
    以下例子:表名2=products(主表) 表名1=vendors(匹配表)
    root@zytest 17:52>select products.vend_id,prod_name from vendors right join products on
    vendors.vend_id=products.vend_id;

                 

                 看不到1006?因为products里面没有1006,所以在vendors表中不匹配。这里用用vendors ID去匹配products。有则匹配。

     复合查询:
    在左连接或者右连接查询出来之后如何进一步过滤?
    root@zytest 18:18>select products.vend_id,prod_name,vend_name,vendors.vend_id from vendors right
    join products on vendors.vend_id=products.vend_id where products.prod_name='Safe';
    在后面直接加where就行了。

5》子查询

  子查询时将一个查询语句内嵌到另个查询语句当中。内层查询的查询结果,可以为外层查询语句提供查询条件;
      1>带IN关键字的子查询
      insert into student values('10005','aaaaa','','aaaaaa');
      insert into student values('10006','aaaaa','','aaaaaa');
      insert into student values('10003','aaaaa','','aaaaaa');
    root@zytest 18:40>select * from orders where cust_id in (select user_id from student);
    root@zytest 18:55>select * from orders where cust_id in (select user_id from student) and cust_id>'10003';进一步过滤

6》合并查询

     有时候需要多个表进行合并数据。我们使用union和union all,使用union时系统会将合并的结果去掉重复。并且显示。但是union all恰恰相反,不会去掉   重复,会把所有的内容全部显示出来;

    root@zytest 19:06>select vend_id from vendors union select vend_id from products;
    root@zytest 19:07>select vend_id from vendors union all select vend_id from products;

7》为表和字段取别名:
  为表取别名:
    select * from student aa where aa.user_id='1';
  为字段取别名:
    select user_id as alvinzeng from student;

  mysql> select * from yy1 aa where aa.user_id=1;

                       +---------+-----------+
      | user_id | user_name |
      +---------+-----------+
      | 1 | zhangsan |
      +---------+-----------+
      1 row in set (0.00 sec)

8》使用正则查看

  在我们的mysql当中,照样可以使用正则表达式来查询结果;

         

           正则我们使用关键字“regexp”来连接正则
    select * from vendors where vend_name regexp '^An';以An开头的
    select * from vendors where vend_city regexp 's$';以s结尾的
    select * from vendors where vend_city regexp '.d';如果字符后面包含d
    select * from vendors where vend_city regexp 'd.'; d后面包含的任意字符
    select * from vendors where vend_city regexp '[London]';只要包含中括号里面任意一个字符的都会被显示出来
    select * from vendors where vend_city regexp '[^Paris]';匹配除了Paris以外的所有字符,也就是说Paris将被过滤掉了。
    select * from vendors where vend_state regexp 'MI|OH';匹配MI或者OH任意一个满足都会被显示出来。
    select * from vendors where vend_state regexp 'M*';匹配以包含M后面的任何字符。
    select * from vendors where vend_name regexp 'll+';代表多个字符前面或者后面的任何字符
    select * from vendors where vend_city regexp 'd{1}';查询d出现过1次或者N次
    select * from vendors where vend_city regexp 'd{1,3}';查询d出现过1次,最多出现3次,

  =====================Mysql存储过程与存储函数=================


1》
创建存储过程

  语法:
  MySQL中,创建存储过程的基本形式如下:

         1>CREATE PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body
    create 是创建的的意思
    procedure 是指的创建的类型是存储过程。
    sp_name参数是存储过程的名称;
    proc_parameter表示存储过程的参数列表;
    characteristic参数指定存储过程的特性;
    routine_body参数是SQL代码的内容,可以用BEGIN…END来标志SQL代码的开始和结束。
    proc_parameter中的每个参数由3部分组成。这3部分分别是输入输出类型、参数名称和参数类型。其形式如下:
    [ IN | OUT | INOUT ] param_name type
      其中,IN表示输入参数;OUT表示输出参数; INOUT表示既可以是输入,也可以是输出; param_name参数是存储过程的参数名称;type参数指               定存储过程的参数类型,该类型可以是MySQL数据库的任意数据类型。
    说明:MySQL中默认的语句结束符为分号(;)。存储过程中的SQL语句需要分号来 结束。为了避免冲突,首先用"DELIMITER &&"将MySQL的结束符         设置为&&。最后再用"DELIMITER ;"来将结束符恢复成分号。这与创建触发器时是一样的。 

              2>存储过程和存储函数的区别:
      存储过程和函数目的是为了可重复地执行操作数据库的SQL语句的集合,区别是写法和调用上:
    写法上:存储过程的参数列表可以有输入参数,输出参数,可以输入输出参数。函数的参数列表只有输入参数,并且有return<返回值类型,无长度说                                明>
    在返回值上的区别:存储过程的返回值,可以有多个值,函数返回值,只有一个值;

         

            举例1:
    需求一、存储过程一(功能返回Mysql的版本号、用户、所在数据库、用户连接数、)
      Delimiter &&
      create procedure alvin1(
      out getversion varchar(30),
      out userversion varchar(30),
      out userdatabase varchar(30),
      out userconnection int)
      reads sql data
      begin
      select version() into getversion;
      select user() into userversion;
      select database() into userdatabase;
      select connection_id() into userconnection;
      end &&
      delimiter ;
      call alvin1(@a,@b,@c,@d);
      select @a,@b,@c,@d;

                    

             需求二、统计student id的数据量总共是多少?
    create procedure alvin2(
    out zycount int)
    reads sql data
    begin
    select count(*) into zycount from student;
    end&&
    delimiter ;
    call alvin2(@a);
    select @a;

2》变量的使用

    在整个存储和函数中,可以定义和使用变量,用户可以使用declare关键字来定义变量,然后可以为变量赋值,这些变量的作用范围是begin…end程序           中。
  1>定义变量
    declare aa_id int default 10;

   2>为变量赋值
    set aa_id=1001;

          IN参数例子:
    root@zytest 23:15>delimiter &&
    root@zytest 23:16>create procedure alvin1( #创建一个名字为alvin1存储过程
      -> in p_in int) #设置传入的参数类型和变量
      -> begin
      -> select p_in; #查询第一次传进来的参数
      -> set p_in=2; #:重新给p_in 赋值后。覆盖掉传进来的参数值
      -> select p_in; #:在查询一次赋值
      ->end&&
    root@zytest 23:19>delimiter ;
    root@zytest 23:19>set @p_in=1;#开始传入参数赋值
    root@zytest 23:19>call alvin1(@p_in);#调用存储过程

                 +------+
       | p_in |
     +------+
     | 1| #传入的值为1,
     +------+
     1 row in set (0.03 sec)

                  +------+
        | p_in |
     +------+
     | 2 | #过程当中的二次赋值
     +------+
     1 row in set (0.03 sec)

      Query OK  0 rows affected (0.03 sec)

     root@zytest 23:20>select @p_in; #查询外边传参赋值的结果
      +-------+
      | @p_in |
      +-------+
      | 1 |
      +-------+

                 OUT参数例子:
      root@zytest 23:41>delimiter &&
      root@zytest 23:41>create procedure name_info(创建一个名称为name_info的存储过程
        -> out p_out int) #定义输出的变量和数据类型
        -> begin
        -> select p_out; #查看输出参数
        -> set p_out=2; #给参数赋值
        -> select p_out; #查询赋值结果
        ->end&&
      Query OK, 0 rows affected (0.00 sec)
    root@zytest 23:42>delimiter ;
    root@zytest 23:42>set @p_out=1; #传入一个参数。看看是否会在call调用的时候显示出来?
      Query OK, 0 rows affected (0.00 sec)
    root@zytest 23:42>call name_info(@p_out);

              +-------+
    | p_out |
    +-------+
    | NULL | #传入的参数为空
      +-------+
    1 row in set (0.01 sec)
    +-------+
    | p_out |
    +-------+
    | 2 | #存储函数里面赋值的参数调用成功
    +-------+
    1 row in set (0.01 sec)
    root@zytest 23:42>select @p_out;
    +--------+
    | @p_out |
    +--------+
    | 2 | #:只看到存储函里面赋值的。传入的参数无效。
    +--------+
    1 row in set (0.00 sec)

             INOUT参数列子:
    root@zytest 00:03>delimiter &&
    root@zytest 00:03>create procedure alvin_name( #创建一个名为alvin_name的函数
      -> inout p_inout int) #创建一个可以传入和传出的p_inout的变量和数据类型
      -> begin
      -> select p_inout; #:查询传入的数据
      -> set p_inout=2; #:给p_inout的赋值
      -> select p_inout; #:在此查询p_inout的值
      ->end&&
   root@zytest 00:04>delimiter ;
   root@zytest 00:04>set @p_inout=1; #:开始传入参数
    Query OK, 0 rows affected (0.00 sec)
   root@zytest 00:04>call alvin_name(@p_inout); #:开始调用

             +---------+
    | p_inout |
    +---------+    
    | 1 | #使用inout既可以传入可以传出
    +---------+
    1 row in set (0.00 sec)
    +---------+
    | p_inout |
    +---------+
    | 2 | #使用inout既可以传入可以传出
    +---------+
    1 row in set (0.00 sec)
    root@zytest 00:04>select @p_inout; #查询最后结果
    +----------+
    | @p_inout |
    +----------+
    | 2 | #:可以传出也可以传入,最终返回结果为2,
    +----------+
    1 row in set (0.00 sec) 

3》创建存储函数

  语法:create function sp_name([func_parameter[,…….]])
    Returns type
    [characteristic…]routine_body。
    其中,sp_name参数是存储函数的名称。
    Func_parameter 表示存储函数的参数列表。
    Returns type 指定返回的参数类型。
    characteristic参数指定存储函数的特性。
    routine_body参数是SQL代码的内容。
    可以用BEGIN…END来标志 SQL代码开始和结束。
    create function 函数名(参数1 数据类型[,参数2 数据类型,参数3 数据类型])returns 返回值类型
    begin
    任意系列的sql语句;
    return 返回值;
    end;

       注:与储存过程不同
    1、参数只有输入型
    2、向调用方返回结果值

  常见的错误:
    This function has none of DETERMINISTIC, NO SQL解决办法
创建存储过程时
  出错信息:
  ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。如果我们开启了 bin-log, 我们就必须为我们的function指定一个参数。
解决方法:
SQL code
mysql> show variables like 'log_bin_trust_function_creators';

        +---------------------------------+-------+
  | Variable_name | Value |
  +---------------------------------+-------+  
  | log_bin_trust_function_creators | OFF |
  +---------------------------------+-------+
mysql> set global log_bin_trust_function_creators=1;
mysql> show variables like 'log_bin_trust_function_creators';
  +---------------------------------+-------+w
  | Variable_name | Value |
  +---------------------------------+-------+
  | log_bin_trust_function_creators | ON |
  +---------------------------------+-------+
这样添加了参数以后,如果mysqld重启,那个参数又会消失,因此记得在my.cnf配置文件中添加:
  log_bin_trust_function_creators=1

    举列:根据输入的vend_id查询到每个用户的vend_name。
    delimiter&&
    create function alvin11( #创建一个函数名称为alvin11
    bb_id int)#定义一个参数类型和它的数据类型
    returns varchar(20)#定义下面vend_name的返回数据类型
    begin # 开始
    return (select vend_name from vendors#返回 SQL语句查询的结果,
    where vend_id=bb_id);
    end && #结束
    delimiter ;#跳出总体段落。
    select alvin11(1001);#调用存储函数-查询结果

4》流程控制

  1>存储过程if语句使用方法:
    delimiter&&
    create procedure zy_if(in aa int,out bb int)
    begin
    if aa>20 then
    set bb=30;
    elseif aa=20
    then
    set bb=20;
    else
    set bb=15;
    end if;
    end&&
    delimiter ;

    开始调用1 aa=20
    call zy_if(20,@bb);
    select @bb;

    开始调用2 aa=25
    call zy_if(25,@bb);
    select @bb;

    开始调用3 aa=15
    call zy_if(15,@bb);
    select @bb;

       2>存储过程case用法
    delimiter&&
    create procedure zy_case(in aa int,inout bb int)
    begin
    case
    when aa=20 then set bb=20;
    when aa>20 and aa<=50 then set bb=30;
    when aa>51 then set bb=60;
    else set bb=15;
    end case;
    end&&
    delimiter ;
    开始调用验证1
    call zy_case(20,@bb);
    select @bb;

    开始调用验证2
    call zy_case(21,@bb);
    select @bb;

    开始调用验证3
    call zy_case(52,@bb);
    select @bb;

      开始调用验证4
    call zy_case(10,@bb);
    select @bb;

         3>存储过程 while 循环使用,插入1万条数据
    delimiter&&
    create procedure zy_while()
    begin
    declare count int default 0;
    while count < 10000 do
    insert into zybb (user_id,name)values(count,'aa1');
    set count = count + 1;
    end while;
    end&&
    delimiter ;
    call zy_while();调用存储过程

5》调用存储过程和函数

    1>调用方式call +存储过程名称+参数

      如:call alvin_name(@p_inout);
    2>查询结果
      select @p_inout
6》
查看存储过程和函数

    1>查询存储过程
      show procedure status;
     查询某具体存储过程详细
      show create procedure alvin1G;

    2>查询存储函数
      show function status;
      查询某个具体存储函数详细
      show create function alvin10G;

7》
删除存储过程和函数

    1>删除存储过程
      drop procedure alvin1;
    2>删除存储函数
      drop function alvin1;

原文地址:https://www.cnblogs.com/xiaocheche/p/7611332.html