上周同事又问一个问题:表 C_Application 中数据量较大,需要批量更新 load_start_time 的时间为 '1900-01-01 18:43:49' 为初始值,以一定时间间隔且每次更新数据量为2000笔的时间设定。
如何进行快速的数据更新操作(其初始手动单批次更新,更新效率比较低;后找开发也未提供给其比较好的方案)?
其实,此种问题的解决并不难,因为目标明确。可以通过最笨的分布式更新(多人单批次同步更新)、Excel拼sql更新等等,相信大家也可以想出很多的方法。如下提供两种基础解决参考(均为未完成的,或者说是有问题的),感兴趣的可以自行完善一下。
第一种:通过脚本语言,拼接sql语句,采用人工或自动更新数据库。python不完善脚本如下所示:
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 import time 5 import DbsUtil 6 7 if __name__ == '__main__': 8 9 TIME_FORMAT_STYLE='%Y-%m-%d %X' 10 11 time_start = '1900-01-01 18:43:49' 12 time_end = '2016-12-21 00:00:00' 13 14 conn_dict = {"server": "127.0.0.1,1433", "db_name": "pythonMssql", "user_name": "ffp", "pwd": "ffp123"} 15 16 time_stamp_start = time.mktime(time.strptime(time_start, TIME_FORMAT_STYLE)) 17 time_stamp_end = time.mktime(time.strptime(time_end, TIME_FORMAT_STYLE)) 18 19 timestamp_step = 60 20 21 update_time = time.strftime(TIME_FORMAT_STYLE, time.localtime(time_stamp_start)) 22 23 row_num_start = 1 24 row_num_step = 2000 25 row_num_end = 2000 26 27 ms = DbsUtil.MSSQL(host="127.0.0.1",user="ffp",pwd="ffp123",db="pythonMssql") 28 resList = ms.ExecQuery("SELECT count(*) as counts_up from C_Application") 29 print resList 30 CYCLE_MAXa = int(resList[0][0]) / row_num_step + 1 31 print CYCLE_MAXa 32 CYCLE_MAX = int(1874826 / row_num_step + 1) 33 34 print CYCLE_MAX 35 CYCLE_MIN = 0 36 37 while CYCLE_MIN < CYCLE_MAX: 38 row_num_start = 1 + CYCLE_MIN * row_num_step 39 row_num_end = (CYCLE_MIN + 1) * row_num_step 40 update_time = time.strftime(TIME_FORMAT_STYLE, time.localtime(time_stamp_start + CYCLE_MIN * timestamp_step)) 41 42 update_sql = "update C_Application set load_start_time = '" + update_time + "' where AppKey in ((select AppKey from (select row_number() over (order by AppKey) as rowId, AppKey from C_Application where Load_Date = '2016-12-21 00:00:00' and load_start_time = '1900-01-01 18:43:49') as t where rowId between " + str(row_num_start) + " and " + str(row_num_end) + "))" 43 44 print update_sql 45 CYCLE_MIN = CYCLE_MIN + 1
第二种:通过mssql中的存储过程也可以实现需求。不完善代码如下所示,可自行完善!
1 create proc page_update( 2 @TableName varchar(50), -- 表名 3 @ReFieldsStr varchar(200), -- 字段名(全部字段为*) 4 @OrderString varchar(200), -- 排序字段(必须!支持多字段不用加order by) 5 @WhereString varchar(500) = N'', -- 条件语句(不用加where) 6 @PageSize int, -- 每页多少条记录 7 @PageIndex int = 1 , -- 指定当前为第几页 8 @TotalRecord int output -- 返回执行结果总记录数 9 ) 10 as 11 begin 12 -- 处理开始点和结束点 13 Declare @StartRecord int; 14 Declare @EndRecord int; 15 Declare @TotalCountSql nvarchar(500); 16 Declare @SqlString nvarchar(2000); 17 18 SET @StartRecord = (@PageIndex-1)*@PageSize + 1 19 SET @EndRecord = @StartRecord + @PageSize - 1 20 -- 总记录数语句 21 SET @TotalCountSql = N'select @TotalRecord = count(*) from ' + @TableName; 22 -- 查询语句 23 SET @SqlString = N'(select row_number() over (order by '+ @OrderString +') as rowId,'+@ReFieldsStr+' from '+ @TableName; 24 25 IF (@WhereString != '' or @WhereString != null) 26 BEGIN 27 SET @TotalCountSql=@TotalCountSql + ' where '+ @WhereString; 28 SET @SqlString =@SqlString+ ' where '+ @WhereString; 29 END 30 31 -- 返回总记录数 32 EXEC sp_executesql @totalCountSql,N'@TotalRecord int out',@TotalRecord output; 33 34 -- 执行主语句 35 SET @SqlString ='select ' + @ReFieldsStr + ' from ' + @SqlString + ') as t where rowId between ' + ltrim(str(@StartRecord)) + ' and ' + ltrim(str(@EndRecord)); 36 print @SqlString 37 END 38 39 40 41 --调用分页存储过程 page_update 42 --exec page_update 'C_Application','AppKey','AppKey',"Load_Date = '2016-12-21 00:00:00' and load_start_time = '1900-01-01 18:43:49'",2000,1,0; 43 --exec page_update 'C_Application','*','AppKey',"Load_Date = '2016-12-21 00:00:00' and load_start_time = '1900-01-01 18:43:49'",2000,2,0; 44 45 -- 46 --declare @totalCount int 47 --exec page_update 'C_Application','*','AppKey',"Load_Date = '2016-12-21 00:00:00' and load_start_time = '1900-01-01 18:43:49'",1000,2,@totalCount 48 --select @totalCount as totalCount 49 50 51 GO
PS:如上两种仅仅提供了两种实现的思想基础和方法,感兴趣的童鞋,可自行将其完善,需要自行创建测试验证数据。完善后可恢复哦 ^_^
其实,在日常的工作生活中,我们经常会遇到各种各样的问题,需要我们去解决,只是每个人面对问题时的处理方式不同。但是,从根本上来讲,解决问题的方法途径有很多种,关键是你能否快速的利用你已经掌握的知识,结合现有的可用资源,进行灵活的知识变现和资源整合,以更快更好的解决问题。技术仅仅是手段,思想方法才是核心!