我们有一个带有许多表的传统Visual FoxPro预订系统。我被要求在桌子上做一些内务处理以减小它们的尺寸。
我创建了一个C#应用程序,它通过vfpoledb.1驱动程序访问数据库文件。此应用程序使用recno()批量删除。这是我正在使用的查询的一个示例:
delete from TableA
where TableA.Key in (
select Key from TableB
where Departure < date(2010,01,01) and Key <> ""
) and recno() between 1 and 10000
通过vfpoledb.1执行此操作不会删除任何内容。使用相同的where子句执行select语句不会返回任何内容。
似乎recno()函数和in()函数的组合导致了问题。依次使用每个子句测试查询会返回结果。
答案 0 :(得分:1)
为什么不采用更简单的方法,而不是批量记录这么多记录。你希望在某个日期之前杀掉所有东西(2010-01-01)。
为什么不尝试基于2009-12-31开始,并继续向后工作到您试图清除的最早日期。另请注意,我不知道离境是否是日期与日期时间,因此我将其更改为
TTOD(离开)(意味着将时间转换为日期组件)
DateTime purgeDate = new DateTime(2009, 12, 31);
// the "?" is a parameter place-holder in the query
string SQLtxt = "delete from TableA "
+ " where TableA.Key in ( "
+ " select Key from TableB "
+ " where TTOD( Departure ) < ? and Key <> \"\" )";
OleDbCommand oSQL = new OleDbCommand( SQLtxt, YourOleDbConnectionHandle );
// default the "?" parameter place-holder
oSQL.Parameters.AddWithValue( "parmDate", purgeDate );
int RecordsDeleted = 0;
while( purgeDate > new DateTime(2000,1,1) )
{
// always re-apply the updated purge date for deletion
oSQL.Parameters[0].Value = purgeDate;
RecordsDeleted += oSQL.ExecuteNonQuery();
// keep going back one day at a time...
purgeDate = purgeDate.AddDays(-1);
}
这样,无论你正在处理什么RECNO(),它只会为那一天做任何关键。如果你在一天内有超过10,000个条目,那么我可能采用不同的方法,但由于这更像是一次性清理,我不会太担心做1000多次迭代(多年来每年365天) )通过数据...或者,您可以使用日期范围并且可能每周执行一次,只需更改WHERE子句并调整参数......类似于......(2000年1月1日的日期只是猜测数据有多远)。此外,由于这是整个日期范围,因此无需转换出发地的可能TTOD()。
DateTime purgeDate = new DateTime(2009, 12, 31);
DateTime lessThanDate = new DateTime( 2010, 1, 1 );
// the "?" is a parameter place-holder in the query
string SQLtxt = "delete from TableA "
+ " where TableA.Key in ( "
+ " select Key from TableB "
+ " where Departure >= ? "
+ " and Departure < ? "
+ " and Key <> \"\" )";
OleDbCommand oSQL = new OleDbCommand( SQLtxt, YourOleDbConnectionHandle );
// default the "?" parameter place-holder
oSQL.Parameters.AddWithValue( "parmDate", purgeDate );
oSQL.Parameters.AddWithValue( "parmLessThanDate", LessThanDate );
int RecordsDeleted = 0;
while( purgeDate > new DateTime(2000,1,1) )
{
// always re-apply the updated purge date for deletion
oSQL.Parameters[0].Value = purgeDate;
oSQL.Parameters[1].Value = lessThanDate;
RecordsDeleted += oSQL.ExecuteNonQuery();
// keep going back one WEEK at a time for both the starting and less than end date of each pass
purgeDate = purgeDate.AddDays(-7);
lessThanDate = lessThanDate.AddDays( -7);
}
答案 1 :(得分:0)
我对实现这一目标的最佳方式感兴趣。我们使用了许多设计不佳的dBaseIII文件,这些文件有时非常大。
我们做了很多,但这是一个讨厌的手动过程:
使用DTS将dbf文件导入临时数据库(2005版+管理工作室导入/导出向导)
使用SSMS运行清理脚本
导出dbf文件并用新修改的文件替换原始文件(备份它们)。
它对我们有用。
答案 2 :(得分:0)
看起来您的日期条件不起作用。尝试使用CTOD()函数而不是您使用过的DATE()来执行SELECT语句。
当您的条件有效时,您将能够运行DELETE语句。但请记住,作为DELETE执行的结果,行只会被标记为已删除。要完全删除它们,您应该在DELETE之后运行PACK语句。
另一方面,您也可以尝试我们的DBF editor - DBF Commander Professional。它允许执行SQL查询,包括命令行(批处理)模式。 E.g:
dbfcommander. exe -q "DELETE FROM 'D:\table_name.dbf' WHERE RECNO()<10000"
dbfcommander. exe -q "PACK 'D:\table_name.dbf'"
您可以在20天内全功能试用期免费使用。