SQL点滴24监测表的变化
SQL 变化 监测 24 点滴
2023-06-13 09:14:30 时间
有时候,我们在某一重要的时间段需要监控某张表的变化情况,包含插入、更新、删除。举例来说,当我们把数据导出到外部的系统时,我们希望导出的是全部的数据,而且最好是导出上次导出之后变动的数据。
作为DBA,我们可采传统的触发器操作,来构建一个元数据表或一个时间戳列来监控数据的变化。
代码如下:CodeListing1
该代码在SQL2005(SP3),SQL2008R2(RTMwithcu5)测试通过
复制代码代码如下:
作为DBA,我们可采传统的触发器操作,来构建一个元数据表或一个时间戳列来监控数据的变化。
代码如下:CodeListing1
该代码在SQL2005(SP3),SQL2008R2(RTMwithcu5)测试通过
-------------------
--Method1:TRIGGER
-------------------
--BaseTableDefinition
IFOBJECT_ID("CheckSumTest","U")ISNOTNULLDROPTABLECheckSumTest
GO
CREATETABLECheckSumTest
(
idintIDENTITY(1,1)NOTNULLPRIMARYKEY,
vc1varchar(1)NOTNULL,
vc2varchar(1)NOTNULL
)
GO
INSERTdbo.CheckSumTest(vc1,vc2)SELECT"a","b"
INSERTdbo.CheckSumTest(vc1,vc2)SELECT"b","a"
GO
--CreateAuditSummaryTabletoholdMeta-Data
IFOBJECT_ID("dbo.TableAuditSummary","U")ISNOTNULLDROPTABLEdbo.TableAuditSummary
CREATETABLEdbo.TableAuditSummary
(idINTIDENTITY(1,1)NOTNULLPRIMARYKEY,
TableNamesysnameNOTNULL,
LastUpdateDATETIMENOTNULL,
LastExportDATETIMENOTNULL
)
GO
INSERTdbo.TableAuditSummary(TableName,LastUpdate,LastExport)VALUES("dbo.CheckSumTest",GETDATE(),GETDATE())
GO
--Tablesthatneedexporting
SELECT*FROMdbo.TableAuditSummaryWHERELastUpdate>LastExport
--CreateTriggeronallBaseTables
--Thisfiresonanyinsert/update/deleteandwritesnewLastUpdatecolumnforthetablesettoCurrentDateandTime
IFOBJECT_ID("dbo.trg_CheckSumTest_MaintainAuditSummary","TR")ISNOTNULLDROPTRIGGERdbo.trg_CheckSumTest_MaintainAuditSummary
GO
CREATETRIGGERdbo.trg_CheckSumTest_MaintainAuditSummary
ONdbo.CheckSumTest
AFTERINSERT,UPDATE,DELETE
AS
BEGIN
IF(object_id("dbo.CheckSumTest")ISNOTNULL)
UPDATEdbo.TableAuditSummarySETLastUpdate=GETDATE()WHERETableName="dbo.CheckSumTest"
END
GO
--MakeanUpdate
UPDATEdbo.CheckSumTestSETvc1="b",vc2="a"WHEREid=1
UPDATEdbo.CheckSumTestSETvc1="a",vc2="b"WHEREid=2
--CheckMeta-Data
SELECT*FROMdbo.TableAuditSummaryWHERELastUpdate>LastExport
--WhenwehaveExportedthedata,werunthefollowingtoresetMetaData
UPDATEdbo.TableAuditSummarySETLastExport=GETDATE()WHERELastUpdate>LastExport
最近我正在读关天SQLSERVER在线帮助(BOL)相关的知识,我接触到了SQLServerCHECKSUM(),BINARY_CHECKSUM(),andCHECKSUM_AGG()这几个函数,由此突然想到这些函数是不是也可以监控表的数据变化,而事实证明CHECKSUM_AGG()函数尽管被描述为检测表的变化,但这里不适用.
使用CheckSum()andCheckSum_Agg()函数
CHECKSUM_AGG()函数,在BooksOnLine和许多相关的站点上是这样描述的,通常用于检测一个表的数据是否更改.这是一个代替触发器的更好的方法,只是该操作会引起表扫描的操作。于是我这次我仍然使用元数据来跟踪数据的变化,只是新建了列LastChkSum代替了LastUpdate,该列用于保存CHECKSUM_AGG(BINARY_CHECKSUM(*)),它将会在全表中产生一个唯一值,以区别数据的变化情况。
代码如下:Listing2.
---------------------------------------------
--Method2:usingCheckSum(notreliable)
---------------------------------------------
--BaseTableDefinition
IFOBJECT_ID("CheckSumTest","U")ISNOTNULLDROPTABLECheckSumTest
GO
CREATETABLECheckSumTest
(
idintIDENTITY(1,1)NOTNULLPRIMARYKEY,
vc1varchar(1)NOTNULL,
vc2varchar(1)NOTNULL
)
GO
INSERTdbo.CheckSumTest(vc1,vc2)SELECT"a","b"
INSERTdbo.CheckSumTest(vc1,vc2)SELECT"b","a"
GO
--CreateAuditSummaryTabletoholdMeta-Data
IFOBJECT_ID("dbo.TableAuditSummary","U")ISNOTNULLDROPTABLEdbo.TableAuditSummary
CREATETABLEdbo.TableAuditSummary
(idINTIDENTITY(1,1)NOTNULLPRIMARYKEY,
TableNamesysnameNOTNULL,
LastChkSumINTNOTNULL
)
GO
INSERTdbo.TableAuditSummary(TableName,LastChkSum)
SELECT"dbo.CheckSumTest",CHECKSUM_AGG(BINARY_CHECKSUM(*))FROMdbo.CheckSumTest
GO
--Tablesthatneedexporting
SELECT*FROMdbo.TableAuditSummaryWHERETableName="dbo.CheckSumTest"
ANDLastChkSum<>(SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMdbo.CheckSumTest)
UNIONALL
...
--MakeaSimple(Singlerow)Update
UPDATEdbo.CheckSumTestSETvc1="c",vc2="a"WHEREid=1
--Tablesthatneedexporting
SELECT*FROMdbo.TableAuditSummaryWHERETableName="dbo.CheckSumTest"
ANDLastChkSum<>(SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMdbo.CheckSumTest)
UNIONALL
...
--ResetMetaData
UPDATEdbo.TableAuditSummarySETLastChkSum=(SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMdbo.CheckSumTest)
WHERETableName="dbo.CheckSumTest"
--MakeaSymmetricchange
UPDATEdbo.CheckSumTestSETvc1="b",vc2="a"WHEREid=1
UPDATEdbo.CheckSumTestSETvc1="c",vc2="a"WHEREid=2
--Tablesthatneedexporting(norowsreturnedasCHECKSUM_AGG()hasnotchanged!!)
SELECT*FROMdbo.TableAuditSummaryWHERETableName="dbo.CheckSumTest"
ANDLastChkSum<>(SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMdbo.CheckSumTest)
UNIONALLCodeListing2
正如你所看到的那样,对于单个的变化的情况,CHECKSUM是使用比较好的,但是CHECKSUM_AGG()却不能反应数据的变化
代码如下:CodeListing3
--BaseTableDefinition
IFOBJECT_ID("CheckSumTest","U")ISNOTNULLDROPTABLECheckSumTest
GO
CREATETABLECheckSumTest
(
idintIDENTITY(1,1)NOTNULLPRIMARYKEY,
vc1varchar(1)NOTNULL,
vc2varchar(1)NOTNULL,
chksum1AS(CHECKSUM(id,vc1,vc2)),
chksum2AS(BINARY_CHECKSUM(id,vc1,vc2))
)
GO
INSERTdbo.CheckSumTest(vc1,vc2)SELECT"a","b"
INSERTdbo.CheckSumTest(vc1,vc2)SELECT"b","a"
GO
--ShowComputedColumnsandCheckSum_Agg()value=199555
SELECT*FROMCheckSumTest
SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMCheckSumTest
--MakeaSimple(Singlerow)Update
UPDATEdbo.CheckSumTestSETvc1="c",vc2="a"WHEREid=1
--ShowComputedColumnsandCheckSum_Agg()value=204816(Ok)
SELECT*FROMCheckSumTest
SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMCheckSumTest
--MakeaSymmetricchange
UPDATEdbo.CheckSumTestSETvc1="b",vc2="a"WHEREid=1
UPDATEdbo.CheckSumTestSETvc1="c",vc2="a"WHEREid=2
--ShowComputedColumnsandCheckSum_Agg()value=204816(NotOk!)
SELECT*FROMCheckSumTest
SELECTCHECKSUM_AGG(BINARY_CHECKSUM(*))FROMCheckSumTest
我们会发现调整前后CHECKSUM_AGG(BINARY_CHECKSUM(*))的值是一样的,不能区分
结论:
CHECKSUM_AGG()函数尽管被描述为能监测表数据的变化,在实际测试中是不行的。尤其是对表进行对称数据修改时,无法监测
作者:TylerNing
相关文章
- 2023-01-03:超过5名学生的课。编写一个SQL查询来报告 至少有5个学生 的所有班级,返回结果不限顺序。请问sql语句如
- ORA-06516: PL/SQL: the Probe packages do not exist or are invalid ORACLE 报错 故障修复 远程处理
- Mybatis多表查询与动态SQL特性详解
- 实现SQL Server 原生数据从XML生成JSON数据的实例代码
- SQL与MySQL的异同比较(sql与mysql的区别)
- MSSQL导出数据到SQL:实现快速简单的数据迁移(mssql导出sql)
- SQL到Oracle的数据迁移之路(sql转换oracle)
- sql develperMac上使用Oracle SQL Developer的指南(mac版oracle)
- Spark SQL 究竟是何方神圣?
- SQL Server计算:记录每位新员工的到职时间(sqlserver计算入职多久)
- 农做一名精通SQL Server的码农(sqlserver码)
- SQL Server 开启数据库之旅(sqlserver 开窗)
- 用SQL Server和JS实现数据库管理技术(sqlserver.js)
- Oracle SQL跟踪:如何优化数据库性能?(oracle跟踪sql)
- Oracle查询:锁定表的SQL语句(oracle查询锁表sql)
- Oracle 高效拼接SQL,节省时间提高效率(Oracle写拼接sql)
- MySQL 上下级 SQL 查询技巧(mysql 上下级sql)
- 优化深入探究Oracle下的SQL优化之道(oracle下sql)
- Oracle SQL实现求余运算(oracle sql求余)