第六章静态查询分析:使用自定义的变量

使用自定义的变量:
缺点:

  1. 使用自定义变量的查询,不能使用查询缓存。
  2. 生命周期在一个连接中有效,不能用他们来做连接间的通信
  3. 如果使用连接池会有变量污染的情况
  4. 自定义变量在 mysql 5.0之前是 大小写敏感,版本问题,以及代码问题
  5. 不能显式的声明自定义变量,定义的时候 如果 整数类型就赋值为 0,浮点型 0.0 ,字符型 ‘’
  6. := 优先级很低,在与其他sql 同个连接中执行时最好加 ()

使用场景:

  1. 查询运算时,计算总数和平均值
  2. 模拟GROUP语句中的函数 FIRST() LAST()
  3. 计算一个大表的MD5散列值
  4. 编写一个样本处理函数,当样本中的数值超过某个边界值时候,将其变为0
  5. 模拟读写 游标
  6. 在SHOW 语句的WHERE 字句中加入变量值

查排名这种先group by,然后再查临时表里面的数据

SET @curr_cnt:=0,@prev_cnt:=0,@rank:=0;
SELECT actor_id,
  @curr_cnt:= cnt AS cnt,
  @rank :=IF(@prev_cnt <> @curr_cnt,@rank+1,@rank) AS rank,
  @prev_cnt :=@curr_cnt AS dummy
FROM (
    SELECT actor_id,COUNT(*) AS cnt
    FROM film_actor
    GROUP BY actor_id
    ORDER BY cnt DESC
    LIMIT 10
)as der;

eg2:
查询刚刚插入的数据

UPDATE t1 SET lastUpdate = NOW() WHERE id=1 AND @now := NOW();
SELECT @now;

统计更新和插入的数量
INSERT INTO ON DUPLICATE KEY UPDATE 与 REPLACE 区别。 转自 :http://blog.itpub.net/29733787/viewspace-1399583/
INSERT INTO ON DUPLICATE KEY UPDATE 缺点:
1. 当主键或唯一键冲突时,执行更新操作,否则执行插入操作,auto_increment始终累加。
2. 更新操作受多个唯一键影响,在MySQL5.6.6之后的SBR中被标记为不安全的
3. DELAYED选项将被忽略
4. MySQL5.6.6之前,对于表级锁存储引擎(MyISAM),该语句会锁定分区表中所有分区。MySQL5.6.6之后,只会锁定所更新的分区(InnoDB无影响)
5. INSERT … SELECT ON DUPLICATE KEY UPDATE可能导致主从数据不一致,因此该语句在MySQL5.6.4之后的SBR中被标记为不安全的。

REPLACE 特点:
1. 当主键或唯一键冲突时,执行删除操作,然后执行插入操作,否则直接执行插入操作。
2. 使用REPLACE时,必须同时拥有INSERT及DELETE权限
3. 删除操作受多个唯一键影响,受影响的行数是删除和插入的行的总和
4. REPLACE … SELECT可能导致主从数据不一致,因此该语句在MySQL5.6.4之后的SBR中被标记为不安全的。
5. REPLACE表不支持子查询中查询同一个表
REPLACE INTO test SET a = 14 ,b= (select b from test where b = 12) ,c=’12’,d=12;
6. MySQL5.6.6之前,对于表级锁存储引擎(MyISAM),该语句会锁定分区表中所有分区,即使使用REPLACE … PARTITION语句。MySQL5.6.6之后,如不更新分区列,只锁定与WHERE子句匹配的分区,如更新分区列,整个表将被锁定

REPLACE算法(LOAD DATA… REPLACE):

  • 尝试向表中插入新记录
  • 因为主键或唯一索引中的重复键错误导致插入失败
  • 从表中删除与重复键值冲突的记录
  • 再次向表中插入新记录

总结:
INSERT INTO ON DUPLICATE KEY UPDATE
可以自定义的更新一些字段,并且可以在update字段中做一些运算。
replate
只能运算好。然后更新替换或者插入

避免遇到重复值时插入失败。

INSERT INTO t1 (c1, c2) VALUES (4,4),(2,1)
ON DUPLICATE KEY UPDATE
     c1 = VALUES(c1) + (0 * (@x :=@x+1))

引入自定义变量,使条件和赋值发生在同一时间。

SET @rownum :=0; SELECT actor_id, @rownum AS rownum FROM actor WHERE
(@rownum := @rownum +1) <=1;

**MYSQL 无需在返回值中新增额外的列,这样的函数有
LEAST GREATEST LENGTH ISNULL NULLIFL IF COALESCE

GREATEST 在一组数据中,取出最大值
LEAST 在一组数据中,取出最小值
COALESCE 在一组参数中,选择第一个已经被定义的变量**

偷懒写 Uninon all

SELECT id FROM users WHERE ID =123
UNION ALL
SELECT id FROM users_archived WHERE id =123;

即使users表中已经找到了记录,上面的查询还是回到users_archived 中再查一遍。

可以写成

SELECT GREATEST(@found :=-1, id) AS id,'users' AS which_tbl
FROM users WHERE id =1 
UNION ALL
    SELECTG id,'users_archived' FROM users_archived WHERE id =1 AND @found IS NULL
UNION ALL
    SELECT 1,'reset' FROM DUAL WHERE (@found := NULL) IS NOT NULL

首先赋值,
最后一句用于重置@found 的值,来防止影响下一次循环。

使用MYSQL 来执行队列 ——-不研究这个了………………现在基本都用redis或memcache实现。

SELECT FOR UPDATE  为了防止同时有两个线程执行代码导致数据覆盖的问题。

BEGIN;
SELECT id FROM unsend_emails
    WHERE owner =0 AND status ='unsend'
    LIMIT 10 FOR UPDATE;
UPDATE unsend_emails
    SET status ='claimed', owner = CONNECTION_ID()
WHERE id IN(123,456,789);
COMMIT;

#不同条件更新不同的值demo
UPDATE vip_member 
SET 
   start_at = CASE
              WHEN end_at < NOW() 
                 THEN NOW()
              ELSE start_at
              END,
   end_at = CASE
            WHEN end_at < NOW()
               THEN DATE_ADD(NOW(), INTERVAL #duration:INTEGER# MONTH)
            ELSE DATE_ADD(end_at, INTERVAL #duration:INTEGER# MONTH)
            END,
   active_status=1,
   updated_at=NOW()
WHERE uid=#uid:BIGINT#
LIMIT 1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值