在手头的一个项目中需要对某些历史库中的过期(超过一定时长)记录进行备份,但备份库可能是分布在其它服务器上的。因此不能简单地通过SELECT INTO 语句来进行处理,Google了一下也没找到什么好的办法,只好自己写代码进行处理。(另:由于此项目是用VC++开发,如果是用C#开发就好处理多了)
下面简要介绍一下实现过程,请高手指点。
1. 用到的一些配置变量:
COleDateTime m_dtLastClearTime; // 最后一次备份时间
int m_iHistoryOverdueDays; // 历史记录过期的天数
2. 实现流程
a. 判断是否需要进行备份(判断最后一次备份时间与当前时间差是否大于历史记录过期的天数,如果是则进行备份,否则退出不作备份)
b. 使用数据表创建脚本在备份数据库中创建备份数据表(备份表的命名约定:原表名+年月日)
c. 转移满足条件的数据
d. 删除原表中过期数据
3. 转移满足条件的数据的代码
1
HRESULT TransferHistoryRecords(const CString csTime, const CString csTableName, const CString csTimeFieldName)
2
{
3
try
4
{
5
CString csQuerySql = _T(""), csOverdueDays, csNewTableName;
6
csOverdueDays.Format(_T("%d"), m_iHistoryOverdueDays);
7
csNewTableName.Format(_T("%s_%s"), csTableName, csTime);
8
csQuerySql.Format(_T("SELECT * FROM %s "), csTableName);
9
csQuerySql += _T(" WHERE (") + csTimeFieldName + _T("<DATEADD(dd,-") + csOverdueDays + _T(",GETDATE()))");
10
}
11
12
AdoNS::_RecordsetPtr rsTt;
13
HRESULT hr = rsTt.CreateInstance(__uuidof(AdoNS::Recordset));
14
rsTt->CursorLocation=AdoNS::adUseClient;
15
hr = rsTt->Open(_bstr_t(csQuerySql),_variant_t((IDispatch *)m_objDbConn.m_pDbConnAlarm,true),AdoNS::adOpenDynamic,AdoNS::adLockUnspecified,AdoNS::adCmdText);
16
if (FAILED(hr))
17
{
18
CSasLog::WriteLog(_T("Ex050001: 历史数据库查询出错: ") + csTableName);
19
return E_FAIL;
20
}
21
22
AdoNS::FieldsPtr pFields;
23
rsTt->get_Fields(&pFields);
24
long iFieldCount = 0;
25
hr = pFields->get_Count(&iFieldCount);
26
if (FAILED(hr))
27
{
28
CSasLog::WriteLog(_T("Ex050002: 历史数据库查询出错: ") + csTableName);
29
rsTt->Close();
30
return E_FAIL;
31
}
32
33
AdoNS::_RecordsetPtr rsAn;
34
hr = rsAn.CreateInstance(__uuidof(AdoNS::Recordset));
35
rsAn->CursorLocation = AdoNS::adUseClient;
36
if ((m_objHistoryBackDbConnPrm.m_pDbConn != NULL) && (m_objHistoryBackDbConnPrm.m_pDbConn->State == 1))
37
{
38
hr = rsAn->Open(_bstr_t(csNewTableName), m_objHistoryBackDbConnPrm.m_pDbConn.GetInterfacePtr(), AdoNS::adOpenKeyset, AdoNS::adLockOptimistic, AdoNS::adCmdTable);
39
if (FAILED(hr))
40
{
41
CSasLog::WriteLog(_T("Ex050003: 打开备份历史数据库出错: ") + csNewTableName);
42
rsTt->Close();
43
return E_FAIL;
44
}
45
}
46
else
47
{
48
CSasLog::WriteLog(_T("Ex050004: 打开备份历史数据库出错: ") + csNewTableName);
49
rsTt->Close();
50
}
51
52
VARIANT vtIndex, vtValue;
53
vtIndex.vt = VT_I4;
54
vtIndex.intVal = 0;
55
long lAttribute = 0;
56
BSTR bstrFieldName;
57
58
while (! rsTt->adoEOF)
59
{
60
hr = rsAn->AddNew();
61
if (FAILED(hr))
62
{
63
break;
64
}
65
66
for(int i=0; i<iFieldCount; i++)
67
{
68
AdoNS::FieldPtr pField;
69
vtIndex.intVal = i;
70
pFields->get_Item(vtIndex, &pField);
71
lAttribute = 0;
72
pField->get_Attributes(&lAttribute);
73
if (lAttribute == 16)
74
{
75
continue;
76
}
77
78
pField->get_Value(&vtValue);
79
pField->get_Name(&bstrFieldName);
80
rsAn->PutCollect(bstrFieldName, vtValue);
81
}
82
83
rsAn->Update();
84
rsTt->MoveNext();
85
}
86
87
rsTt->Close();
88
}
89
catch(_com_error ex)
90
{
91
CSasLog::WriteLog(_T("TransferHistoryRecords[") + csTableName + _T("] error: ") + CString(ex.ErrorMessage()));
92
return E_FAIL;
93
}
94
95
return S_OK;
96
}
97
HRESULT TransferHistoryRecords(const CString csTime, const CString csTableName, const CString csTimeFieldName)2
{3
try4
{5
CString csQuerySql = _T(""), csOverdueDays, csNewTableName;6
csOverdueDays.Format(_T("%d"), m_iHistoryOverdueDays);7
csNewTableName.Format(_T("%s_%s"), csTableName, csTime);8
csQuerySql.Format(_T("SELECT * FROM %s "), csTableName);9
csQuerySql += _T(" WHERE (") + csTimeFieldName + _T("<DATEADD(dd,-") + csOverdueDays + _T(",GETDATE()))");10
}11

12
AdoNS::_RecordsetPtr rsTt;13
HRESULT hr = rsTt.CreateInstance(__uuidof(AdoNS::Recordset));14
rsTt->CursorLocation=AdoNS::adUseClient;15
hr = rsTt->Open(_bstr_t(csQuerySql),_variant_t((IDispatch *)m_objDbConn.m_pDbConnAlarm,true),AdoNS::adOpenDynamic,AdoNS::adLockUnspecified,AdoNS::adCmdText);16
if (FAILED(hr))17
{18
CSasLog::WriteLog(_T("Ex050001: 历史数据库查询出错: ") + csTableName);19
return E_FAIL;20
}21

22
AdoNS::FieldsPtr pFields;23
rsTt->get_Fields(&pFields);24
long iFieldCount = 0;25
hr = pFields->get_Count(&iFieldCount);26
if (FAILED(hr))27
{28
CSasLog::WriteLog(_T("Ex050002: 历史数据库查询出错: ") + csTableName);29
rsTt->Close();30
return E_FAIL;31
}32

33
AdoNS::_RecordsetPtr rsAn;34
hr = rsAn.CreateInstance(__uuidof(AdoNS::Recordset));35
rsAn->CursorLocation = AdoNS::adUseClient;36
if ((m_objHistoryBackDbConnPrm.m_pDbConn != NULL) && (m_objHistoryBackDbConnPrm.m_pDbConn->State == 1))37
{38
hr = rsAn->Open(_bstr_t(csNewTableName), m_objHistoryBackDbConnPrm.m_pDbConn.GetInterfacePtr(), AdoNS::adOpenKeyset, AdoNS::adLockOptimistic, AdoNS::adCmdTable);39
if (FAILED(hr))40
{41
CSasLog::WriteLog(_T("Ex050003: 打开备份历史数据库出错: ") + csNewTableName);42
rsTt->Close();43
return E_FAIL;44
}45
}46
else47
{48
CSasLog::WriteLog(_T("Ex050004: 打开备份历史数据库出错: ") + csNewTableName);49
rsTt->Close();50
}51

52
VARIANT vtIndex, vtValue;53
vtIndex.vt = VT_I4;54
vtIndex.intVal = 0;55
long lAttribute = 0;56
BSTR bstrFieldName;57

58
while (! rsTt->adoEOF)59
{60
hr = rsAn->AddNew();61
if (FAILED(hr))62
{63
break;64
}65

66
for(int i=0; i<iFieldCount; i++)67
{68
AdoNS::FieldPtr pField;69
vtIndex.intVal = i;70
pFields->get_Item(vtIndex, &pField);71
lAttribute = 0;72
pField->get_Attributes(&lAttribute);73
if (lAttribute == 16)74
{75
continue;76
}77

78
pField->get_Value(&vtValue);79
pField->get_Name(&bstrFieldName);80
rsAn->PutCollect(bstrFieldName, vtValue);81
}82

83
rsAn->Update();84
rsTt->MoveNext();85
}86

87
rsTt->Close();88
}89
catch(_com_error ex)90
{91
CSasLog::WriteLog(_T("TransferHistoryRecords[") + csTableName + _T("] error: ") + CString(ex.ErrorMessage()));92
return E_FAIL;93
}94

95
return S_OK;96
}97

其它代码较为简单,在此就不贴出来了。


