如何能更简洁的记录表历史

很多时候,都需要对数据表进行历史记录。比如每修改一次表单,之前的表单数据都需要计入历史。当表单比较多的时候,记录历史是一件比较麻烦的事情。又要建日志表,又要写存储过程,又要写页面逻辑等等。有没有通用点的办法呢?最近做项目时碰到了,要求每次审核、退回等操作时就要记录表历史。于是,作者就想到了以下方案。在此与大家分享了,如果有更合适的或合理的建议,请回复本帖。

1)创建日志表

一个一个建表是一件烦躁的事,而且还容易出错。那么,以下存储过程就能批量建表了,还添加了LogCreateDate、LogDefaultFlag、LogPTID这3个字段。值得注意的是,创建表结构可以用以下语句“SELECT * Into tableName_Log FROM tableName”。如果只需要复制表结构,那就插入一行,再删除就是。

SQL里面实现遍历数据集不方便,不想用游标,于是采用了以下方式。具体存储过程如下:

  1. USE [NbShop]    
  2. GO    
  3. /****** Object:  StoredProcedure [dbo].[CreateLogTable]    Script Date: 07/02/2011 12:54:32 ******/    
  4. SET ANSI_NULLS ON   
  5. GO    
  6. SET QUOTED_IDENTIFIER ON   
  7. GO    
  8. -- =============================================    
  9. -- Author:      LWQ    
  10. -- Create date: 2011-6-29    
  11. -- Description: 创建日志表(命名规则:表名+_Log)    
  12. -- =============================================    
  13. ALTER PROCEDURE [dbo].[CreateLogTable]    
  14. AS   
  15. BEGIN   
  16.     -- SET NOCOUNT ON added to prevent extra result sets from    
  17.    -- interfering with SELECT statements.    
  18.     SET NOCOUNT ON;    
  19.      
  20.     -- Insert statements for procedure here    
  21.     -------------------创建日志表------------------------------    
  22. declare @rows     int   
  23. declare @n        int   
  24. declare @tableName        varchar(100)    
  25. select @n=1    
  26.     SELECT     name   
  27.     INTO            [#tempTables]    
  28.     FROM         sys.sysobjects    
  29.     WHERE     (xtype = 'U 'AND (name NOT IN ('sysdiagrams''T_BasicTime''T_Attribute''T_AttributeType''T_BasicTime''T_City','T_CompeteForMeasu',     
  30.                           'T_DocumentTypeRestrictions''T_FormRelevance''T_HistroyShopAction''T_Notice''T_NoticeReceive''T_Organize''T_OrgType',     
  31.                           'T_Province''T_Role''T_RptShopStatus''T_UploadFile''T_UrlPrint'))    
  32.                           AND (name NOT LIKE '%flow%'AND (name NOT LIKE '%Control%'AND    
  33.                           (name NOT LIKE '%Menu%'AND (name NOT LIKE '%Node%'AND (name NOT LIKE '%Log%'AND (name NOT LIKE '%Event%'AND (name NOT LIKE '%Object%'AND    
  34.                           (name NOT LIKE '%Process%'AND (name NOT LIKE '%ShopStatus%'AND (name NOT LIKE '%Task%')     
  35.                           AND (name NOT LIKE '%ThirdParty%'AND (name NOT LIKE '%User%')    
  36.                           AND (name NOT LIKE '%order%')    
  37.     Select * from   #tempTables    
  38.     Select name into #tempCurrent  from #tempTables    
  39.     Delete from  #tempCurrent    
  40.      
  41.     select @rows = @@rowcount    
  42.     while @n <= @rows   
  43.     begin   
  44.       set @tableName=(Select  top 1  name from #tempTables     
  45.       Where name not in    
  46.       (select name from #tempCurrent))    
  47.       if(@tableName is not null)    
  48.       begin   
  49.         insert into #tempCurrent values(@tableName)    
  50.         if object_id(@tableName+'_Log'is not null    
  51.         begin   
  52.             print   '表'+  @tableName +'已存在,仅做数据更新处理'   
  53.             exec ('INSERT INTO'+ @tableName +'_Log SELECT * FROM '+@tableName)                  
  54.         end   
  55.         else   
  56.         begin   
  57.             exec ('SELECT * Into '+@tableName+'_Log FROM '+@tableName)    
  58.             print   '表'+  @tableName +'创建成功'   
  59.             exec ('alter   table   '+@tableName+'_Log   add   LogCreateDate   datetime')    
  60.             exec ('alter   table   '+@tableName+'_Log   add   LogDefaultFlag   int')    
  61.             exec ('alter   table   '+@tableName+'_Log   add   LogPTID   varchar(32)')    
  62. ----            if   col_length( @tableName+' ',   'LogCreateDate ')   is not   null     
  63. ----            begin    
  64. ----                exec ('ALTER   TABLE   '+@tableName+'   DROP   COLUMN   LogCreateDate')     
  65. ----                print '删除'+@tableName+'的列LogCreateDate成功'    
  66. ----            end    
  67. ----            if(@tableName not in ('T_Shop','T_MeasurementAddress','T_TurnAround','T_IrisInstrumentHistory','T_ChainTurnApplication','T_TrainingNotice'))    
  68. ----            begin    
  69. ----                if   col_length( @tableName+' ',   'CreateDate ')   is not   null     
  70. ----                begin    
  71. ----                    exec ('ALTER   TABLE   '+@tableName+'   DROP   COLUMN   CreateDate ')    
  72. ----                    print '删除'+@tableName+'的列CreateDate成功'    
  73. ----                end     
  74. ----            end    
  75.         end   
  76.     end   
  77.         select @n = @n + 1    
  78.     end   
  79.     drop table  #tempCurrent    
  80.     drop table  #tempTables    
  81. -------------------创建日志表------------------------------    
  82. END  

#p#

2)删除日志表

在开发过程中,难免会对字段进行更改。于是删除的存储过程也得有。具体代码如下:

  1. USE [NbShop]  
  2. GO  
  3. /****** Object:  StoredProcedure [dbo].[DropLogTable]    Script Date: 07/02/2011 12:54:29 ******/  
  4. SET ANSI_NULLS ON 
  5. GO  
  6. SET QUOTED_IDENTIFIER ON 
  7. GO  
  8. -- =============================================  
  9. -- Author:      LWQ  
  10. -- Create date: 2011-6-29  
  11. -- Description: 删除日志表(_log)  
  12. -- =============================================  
  13. ALTER PROCEDURE [dbo].[DropLogTable]  
  14. AS 
  15. BEGIN 
  16.     -- SET NOCOUNT ON added to prevent extra result sets from  
  17.     -- interfering with SELECT statements.  
  18.     SET NOCOUNT ON;  
  19.  
  20.     -------------------删除日志表------------------------------  
  21. declare @rowsIndex     int 
  22. declare @nIndex        int 
  23. declare @LogTableName        varchar(100)  
  24. select @nIndex=1  
  25.     SELECT     name 
  26.     INTO            #LogtempTables  
  27.     FROM         sys.sysobjects  
  28.     WHERE     (xtype = 'U 'AND (name like '%\_log' escape '\')    
  29.     Select * from #LogtempTables  
  30.     Select name into #LogtempCurrent  from #LogtempTables  
  31.     Delete from  #LogtempCurrent  
  32.     select @rowsIndex = (Select count(*) from   #LogtempTables)  
  33.     print   @rowsIndex  
  34.       
  35. while @nIndex <= @rowsIndex  
  36. begin 
  37.   set @LogTableName=(Select  top 1  name from #LogtempTables   
  38.   Where name not in   
  39.   (select name from #LogtempCurrent))  
  40.   if(@LogTableName IS NOT NULL)  
  41.   begin 
  42.     insert into #LogtempCurrent values(@LogTableName)  
  43.     print     'Drop table '+@LogTableName  
  44.     exec ('Drop table '+@LogTableName)  
  45.     print    '删除'+@LogTableName+'成功' 
  46.   end 
  47.    
  48.   select @nIndex = @nIndex + 1  
  49. end 
  50. Drop table   #LogtempTables  
  51. Drop table   #LogtempCurrent  
  52. SELECT     name FROM         sys.sysobjects     WHERE     (xtype = 'U 'AND (name like '%\_log' escape '\')   
  53. -------------------删除日志表------------------------------  
  54. END 

以上语句值得注意的是在查找以“_Log”结尾的表名的搜索条件,需要加上“escape ‘\’”。

3)记录日志

日志表有了,还得记录日志呢。为每个表写个存储过程会过于繁琐,而且改动了就得跟着改动。就是码农也吃不消。于是有了以下存储过程,该存储过程定义了7个参数,允许传入存储过程、表名、Where条件等。具体如下:

  1. USE [NbShop]  
  2. GO  
  3. /****** Object:  StoredProcedure [dbo].[RecordLog]    Script Date: 07/02/2011 12:54:07 ******/  
  4. SET ANSI_NULLS ON 
  5. GO  
  6. SET QUOTED_IDENTIFIER ON 
  7. GO  
  8.  
  9.  
  10. -- =============================================  
  11. -- Author:      LWQ  
  12. -- Create date: 2011-6-29  
  13. -- Description: 记录日志  
  14. -- =============================================  
  15. ALTER PROCEDURE   [dbo].[RecordLog]  
  16.     @ObjectID varchar(32),                      ---门店ID  
  17.     @TableName varchar(100),                    ---表名  
  18.     @PTID varchar(32),                          ---PTID(阶段ID),可选  
  19.     @PhasesID varchar(32),                      ---阶段ID,可选  
  20.     @ProcedureName varchar(200),                ---存储过程名称,可选  
  21.     @InsertSQLWhere nvarchar(1000),                 ---主表的筛选条件  
  22.     @UpdateSQLWhere nvarchar(1000)                  ---主表的筛选条件  
  23. AS 
  24. BEGIN 
  25.     -- SET NOCOUNT ON added to prevent extra result sets from  
  26.     -- interfering with SELECT statements.  
  27.     SET NOCOUNT ON;  
  28.       
  29.     IF (@ProcedureName is not NULL)  
  30.     BEGIN 
  31.         exec ('exec('+@ProcedureName+''''+@ObjectID+''','''+@PTID+''','''+@PhasesID+''')')  
  32.     END 
  33.     ELSE IF(@InsertSQLWhere IS NOT NULL)  
  34.     BEGIN 
  35.         IF(@UpdateSQLWhere IS NOT NULL)  
  36.         Begin 
  37.             exec('Update '+ @tableName +'_Log Set LogDefaultFlag=0 ' +@UpdateSQLWhere)  
  38.         End 
  39.         Else 
  40.         Begin 
  41.             declare @UpdateExecSQL nvarchar(2000)  
  42.             Select @UpdateExecSQL='Update '+    @tableName +'_Log Set LogDefaultFlag=0 Where ' 
  43.             --------------判断是否存在ObjectID列(门店ID)-----------------------------  
  44.             if @ObjectID IS NOT NULL AND col_length( @tableName+' ',   'ObjectID ')   is not   null   
  45.             BEGIN 
  46.                 Select @UpdateExecSQL=@UpdateExecSQL+' ObjectID='''+@ObjectID+''' ' 
  47.             END       
  48.             Else 
  49.             Begin 
  50.                 Select @UpdateExecSQL=@UpdateExecSQL+' ShopID='''+@ObjectID+''' ' 
  51.             END 
  52.             exec(@UpdateExecSQL)  
  53.         END 
  54.         exec('INSERT INTO '+    @tableName +'_Log SELECT *,getdate(),1,'''+@PTID+''' FROM '  + @tableName+' '+@InsertSQLWhere)  
  55.     END 
  56.     ELSE 
  57.     BEGIN 
  58.         declare @InsertSQL nvarchar(2000)  
  59.         declare @UpdateSQL nvarchar(2000)  
  60.         Declare @WhereCount int 
  61.         Select @WhereCount=0   
  62.           
  63.         Select @UpdateSQL='Update '+@tableName+'_Log Set LogDefaultFlag=0 ' 
  64.         select @InsertSQL='INSERT INTO '+   @tableName +'_Log SELECT *,getdate(),1,'''+@PTID+''' FROM '  + @tableName;  
  65.         --------------判断是否存在DefaultFlag列-------------------------  
  66.         if   col_length( @tableName+' ',   'DefaultFlag ')   is not   null   
  67.         BEGIN 
  68.             select @InsertSQL=@InsertSQL+' Where DefaultFlag=1 ' 
  69.             Select @WhereCount=@WhereCount+1          
  70.         END 
  71.         --------------判断是否存在ObjectID列(门店ID)-----------------------------  
  72.         if @ObjectID IS NOT NULL AND col_length( @tableName+' ',   'ObjectID ')   is not   null   
  73.         BEGIN 
  74.             IF(@WhereCount>0)  
  75.             BEGIN 
  76.                 select @InsertSQL=@InsertSQL+' AND ObjectID='''+@ObjectID+''' ' 
  77.                 Select @UpdateSQL=@UpdateSQL+' AND ObjectID='''+@ObjectID+''' ' 
  78.             END 
  79.             ELSE 
  80.             BEGIN 
  81.                 select @InsertSQL=@InsertSQL+' WHERE ObjectID='''+@ObjectID+''' ' 
  82.                 Select @UpdateSQL=@UpdateSQL+' WHERE ObjectID='''+@ObjectID+''' ' 
  83.             END 
  84.             Select @WhereCount=@WhereCount+1          
  85.         END 
  86.         --------------判断是否存在ShopID列(门店ID)-----------------------------  
  87.         if @ObjectID IS NOT NULL AND col_length( @tableName+' ',   'ShopID ')   is not   null   
  88.         BEGIN 
  89.             IF(@WhereCount>0)  
  90.             BEGIN 
  91.                 select @InsertSQL=@InsertSQL+' AND ShopID='''+@ObjectID+''' ' 
  92.                 Select @UpdateSQL=@UpdateSQL+' AND ShopID='''+@ObjectID+''' ' 
  93.             END 
  94.             ELSE 
  95.             BEGIN 
  96.                 select @InsertSQL=@InsertSQL+' WHERE ShopID='''+@ObjectID+''' ' 
  97.                 Select @UpdateSQL=@UpdateSQL+' WHERE ShopID='''+@ObjectID+''' ' 
  98.             END 
  99.             Select @WhereCount=@WhereCount+1          
  100.         END 
  101.         --------------判断是否存在PTID列(模版ID)-----------------------------  
  102.         if @PTID IS NOT NULL AND col_length( @tableName+' ',   'PTID ')   is not   null   
  103.         BEGIN 
  104.             IF(@WhereCount>0)  
  105.             BEGIN 
  106.                 select @InsertSQL=@InsertSQL+' AND PTID='''+@PTID+''' ' 
  107.             END 
  108.             ELSE 
  109.             BEGIN 
  110.                 select @InsertSQL=@InsertSQL+' WHERE PTID='''+@PTID+''' ' 
  111.             END 
  112.             Select @WhereCount=@WhereCount+1          
  113.         END 
  114.         --------------判断是否存在PhasesID列(阶段ID)-----------------------------  
  115.         if @PhasesID IS NOT NULL AND  col_length( @tableName+' ',   'PhasesID ')   is not   null   
  116.         BEGIN 
  117.             IF(@WhereCount>0)  
  118.             BEGIN 
  119.                 select @InsertSQL=@InsertSQL+' AND PhasesID='''+@PhasesID+''' ' 
  120.             END 
  121.             ELSE 
  122.             BEGIN 
  123.                 select @InsertSQL=@InsertSQL+' WHERE PhasesID='''+@PhasesID+''' ' 
  124.             END 
  125.             Select @WhereCount=@WhereCount+1          
  126.         END 
  127.         print @UpdateSQL  
  128.         exec (@UpdateSQL)  
  129.         print @InsertSQL  
  130.         Exec  (@InsertSQL)  
  131.     END 
  132.      
  133. END 

#p#

存储过程有了,再配个XML,根据参数把TableName配进去,再加点可配的自定义属性什么的,例如:

  1. <Control Display="解约申请"> 
  2.   <QueryStrings> 
  3.     <QueryString QueryName="PEId">D80E55971198454F97F7EBFE89D239DC</QueryString> 
  4.   </QueryStrings> 
  5.   <Url><![CDATA[/FormServerTemplates/ChainsReleaseForm.aspx]]></Url> 
  6.   <SQlTableName>T_ChainsReleaseForm</SQlTableName> 
  7.   <SQlTableName SQlWhere=" Where CRFID=(Select top 1 CRFID from T_ChainsReleaseForm Where ShopID={@ShopID@})">T_GeneralFromTable</SQlTableName> 
  8. </Control> 
  9. <Control Display="客户信息表"> 
  10.   <QueryStrings> 
  11.     <QueryString QueryName="PEId">E515165457C5493DA605D4E66416A685</QueryString> 
  12.     <QueryString QueryName="PEId">F9D6E25D978D4E5DB061AE33D68EE279</QueryString> 
  13.     <QueryString QueryName="PEId">D9B9D05380EF4F11B2D2A74D0684DF4B</QueryString> 
  14.     <QueryString QueryName="PEId">45C2B486EB7A463E94B3D55D48DB4A74</QueryString> 
  15.     <QueryString QueryName="PEId">509B5BB3A3B14912ACD633F28A6C91A1</QueryString> 
  16.     <QueryString QueryName="PEId">0CFE53A2A3BB4D6A891B34AA43B0FAC7</QueryString> 
  17.     <QueryString QueryName="PEId">70247883D6414746848E0CE22F06A3F3</QueryString> 
  18.     <QueryString QueryName="PEId">C1E2AD7DFC674DC2AA8434763D4DA0A3</QueryString> 
  19.     <QueryString QueryName="PEId">EE895BBB5B2D43179B196F753ACADCC9</QueryString> 
  20.   </QueryStrings> 
  21.   <Url><![CDATA[/FormServerTemplates/AddShopInfo.aspx]]></Url> 
  22.   <SQlTableName>T_Shop</SQlTableName> 
  23.   <SQlTableName>T_Shopkeeper</SQlTableName> 
  24.   <SQlTableName>T_Acreage</SQlTableName> 
  25.   <SQlTableName>T_BusinessDistrict</SQlTableName> 
  26.   <SQlTableName>T_Compete</SQlTableName> 
  27.   <SQlTableName>T_SupportingFacility</SQlTableName> 
  28. </Control> 

这样,就一劳永逸了。

原文链接:http://www.cnblogs.com/codelove/archive/2011/07/02/2096296.html

【编辑推荐】

  1. SQL Server复灾 你懂了吗?
  2. SQL Server管理 这些你懂吗?
  3. 客户的一次疏忽,DBA的一次噩梦
  4. 单数据库vs多数据库,单实例vs多实例 效率测试
  5. 关于Update在不同数据库的使用

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/231913.html<

(0)
运维的头像运维
上一篇2025-04-19 22:23
下一篇 2025-04-19 22:25

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注