Chinaunix首页 | 论坛 | 博客
  • 博客访问: 931015
  • 博文数量: 177
  • 博客积分: 8613
  • 博客等级: 中将
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-12 04:16
文章分类
文章存档

2012年(12)

2011年(24)

2010年(24)

2009年(75)

2008年(42)

我的朋友

分类: Mysql/postgreSQL

2012-03-30 17:04:18

    5点了,今天弄了一天,弄出来另一个更新ip的存储过程,100多行的程序,在editplus里写完后运行,竟然没有bug,擦啊。
 
 
说明:客户端传来的串和数据表里的字段 request_ip 的格式必须遵循一样的规律,都是类似 192.168.3.44,389-10.110.10.12,590-$ 这样,以-分隔的ip,ip出现的次数,以$结尾
具体应该代表:
客户端ip,此ip出现的次数-客户端ip,此ip出现的次数-$
举例:
192.168.3.44,389-10.110.10.12,590-$
算法为:
初始化set NewValue='';
第一个循环,以数据库中的老ip为基础
从表里select出来request_ip,存入字符串@OldValue中,循环处理,取出每一个 “ip,次数” 的子串,在传入的字符串中寻找是否有此ip
若有:增加此ip出现的次数
否则:不增加次数
拼凑ip,times串,然后concat到NewValue中
第二个循环,以客户端传过来的AddValue为基础,循环比对数据库中的值,
若有:不进行任何处理,因为在前一个循环里已经累加过了
否则:将此对ip,times 增加到NewValue中
最后,添加上 $ ,update NewValue

知识准备:
INSTR(str,substr)
    返回子串substr在字符串str中的第一个出现的位置。这与有2个参数形式的LOCATE()相同,除了参数被颠倒。
    mysql> select INSTR('foobarbar', 'bar');
                -> 4
    mysql> select INSTR('xbar', 'foobar');
                -> 0
    这函数是多字节可靠的。
   
SUBSTRING(str,pos)
     
SUBSTRING(str FROM pos)
    从字符串str的起始位置pos返回一个子串。
    mysql> select SUBSTRING('Quadratically',5);
                -> 'ratically'
    mysql> select SUBSTRING('foobarbar' FROM 4);
                -> 'barbar'

 
调用方法为:
call UpdateRequestIp('access_log_reg_201203','/jsp10','2012-03-22 12:30:00','10.110.10.159,23-$',@a);
---------------------------------------------------------------
drop procedure if exists UpdateRequestIp;
 
DELIMITER $$
-- Purl 是存储过程接收的access_url, Pdatetime是存储过程接收的access_datetime
create procedure UpdateRequestIp(IN tablename varchar(80), IN Purl varchar(100), IN Pdatetime datetime ,IN AddValue varchar(256), OUT ReturnValue varchar(80) )
top:BEGIN

--OldValue循环加上此存储过程接收的参数AddValue后,形成NewValue
declare NewValue varchar(1024);
--保存OldValue中,以-分隔的各个ip,times串
declare TmpStrOld_ip_times varchar(80);
declare TmpStrOld_ip varchar(80);
declare TmpStrOld_times varchar(80);
--保存AddValue中,以-分隔的各个ip,times串
--从AddValue中取出寻找到的ip到结尾的串,备用下面分隔ip和次数
declare TmpStrAdd varchar(80);
declare TmpStrAdd_ip_times varchar(80);
declare TmpStrAdd_ip varchar(80);
declare TmpStrAdd_times varchar(80);
-- 保存AddValue中,寻找到的ip的起始位置
declare instr_i int ;
declare Length int ;
declare i int ;
--初始化新字符串
set NewValue='';
set autocommit=0;
--这句话弄了半下午,主要是表名用变量和select into到变量这两个问题。
SET @SqlCmd = concat('select request_ip into @OldValue from ', tablename ,' where access_url=\'', Purl, '\' and access_datetime=\'', Pdatetime, '\' for update');
PREPARE stmt FROM @SqlCmd;
EXECUTE stmt;
--第一个循环,以数据库中的串为基础
set Length = length(@OldValue);
set i = 1;
-- 以OldValue的长度为遍历次数,按-分隔,取出"ip,times"这样的串,一个个地累加OldValue和AddValue,遇到'$'时退出循环,最后形成NewValue,注意,数据库中的OldValue很有可能会比客户端调用的AddValue要多,因为AddValue只传过来top10,而数据库中是累加的。
first_while_label: while i < Length
 do
 -- 获取数据库中串里的ip和次数
 set TmpStrOld_ip_times = substring_index( substring_index(@OldValue, '-', i), '-', -1 );
 -- 判断结束,结束条件是数据库中的串的最后一位是$,否则要返回错误,通知调用者
 if(TmpStrOld_ip_times = '$')
 then
  --返回值应该是SUCCESS,这里返回一半,最后update完毕后返回全部
  set ReturnValue = 'SUCCESSfirstloop';
  --select ReturnValue;
  leave first_while_label;
 end if;
 set TmpStrOld_ip = substring_index(TmpStrOld_ip_times, ',', 1);
 set TmpStrOld_times = substring_index(TmpStrOld_ip_times, ',', -1);
 -- 在AddValue 中寻找此ip
 set instr_i = instr(AddValue, TmpStrOld_ip);
 if(instr_i > 0)
  then
   set TmpStrAdd = substring(AddValue, instr_i);
   set TmpStrAdd_ip_times = substring_index(TmpStrAdd, '-', 1);
   set TmpStrAdd_ip = substring_index(TmpStrAdd_ip_times, ',', 1);
   set TmpStrAdd_times = substring_index(TmpStrAdd_ip_times, ',', -1);
   -- 前面的一系列都是为了这句:
   set TmpStrOld_times = TmpStrOld_times + TmpStrAdd_times ;
 end if;
 -- 构造新值
 set NewValue =  concat(NewValue, TmpStrOld_ip, ',', TmpStrOld_times, '-');
 set i=i+1;
end while;
--如果第一个循环结束时,最后一个字符不是$,就说明格式不对,需要退出此存储过程。
if(TmpStrOld_ip_times != '$')
 then
 set ReturnValue = 'format error, exit with no update';
 leave top;
 select 'can you see this?';
end if;

--第二个循环,以客户端传过来的 AddValue 串为基础
set Length = length(AddValue);
set i = 1;
-- 以AddValue的长度为遍历次数,按-分隔,取出"ip,times"这样的串,如果这个串在数据库中,前面的循环已经处理了,累加不在的串即可。
second_while_label: while i < Length
 do
 -- 获取串里的ip和次数
 set TmpStrAdd_ip_times = substring_index( substring_index(AddValue, '-', i), '-', -1 );
 -- 判断结束,结束条件是串的最后一位是$,否则要返回错误,通知调用者
 if(TmpStrAdd_ip_times = '$')
 then
  --返回值应该是SUCCESS,这里返回一个错误的,有利于判断程序在哪里出错,最后update完毕后返回全部
  set ReturnValue = 'SUCCESSsecondloop';
  --select ReturnValue;
  leave second_while_label;
 end if;
 set TmpStrAdd_ip = substring_index(TmpStrAdd_ip_times, ',', 1);
 --set TmpStrAdd_times = substring_index(TmpStrAdd_ip_times, ',', -1);
 -- 在 @OldValue 中寻找此ip
 set instr_i = instr(@OldValue, TmpStrAdd_ip);
 if(instr_i = 0)
  then
   set NewValue =  concat(NewValue, TmpStrAdd_ip_times, '-');
 end if;
 set i=i+1;
end while;
--如果循环结束时,最后一个字符不是$,就说明格式不对,需要退出此存储过程。
if(TmpStrAdd_ip_times != '$')
 then
 set ReturnValue = 'format error, exit with no update';
 leave top;
 select 'can you see this in second loop?';
end if;
set NewValue =  concat(NewValue, '$');
-- 前面有错误的话,会直接退出了,所以update的时候放心update即可。
--update tablename set request_ip=NewValue where access_url=Purl and access_datetime=Pdatetime;
SET @SqlCmd = concat('update ', tablename ,' set request_ip=\'', NewValue,'\' where access_url=\'', Purl, '\' and access_datetime=\'', Pdatetime, '\'');
PREPARE stmt FROM @SqlCmd;
EXECUTE stmt;
-- 拼凑最后的返回值,应该是SUCCESS
set ReturnValue = 'SUCCESS';
commit;
set autocommit=1;
END $$
DELIMITER ;
---------------------------------------------------------------
阅读(1158) | 评论(0) | 转发(0) |
0

上一篇:第一个mysql存储过程

下一篇:python base64

给主人留下些什么吧!~~