如何从Foxpro中删除大量数据

时间:2014-01-13 12:03:10

标签: sql visual-foxpro

问题

我们有一个带有许多表的传统Visual FoxPro预订系统。我被要求在桌子上做一些内务处理以减小它们的尺寸。

  • 表格设计严谨,没有自动递增的主键。
  • 最大的表是300万行。
  • 我正在尝试删除380,000行。
  • 由于表格中的数据量很大,我正在尝试开发批量删除的解决方案。

到目前为止我得到了什么

我创建了一个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()函数的组合导致了问题。依次使用每个子句测试查询会返回结果。

问题

  1. 是否有另一种批量删除Visual FoxPro数据的方法?
  2. 为什么recno()和in()不兼容?
  3. 还有什么我想念的吗?
  4. 其他信息

    • ANSI设置为TRUE
    • DELETED设置为TRUE
    • EXCLUSIVE设为TRUE

3 个答案:

答案 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文件,这些文件有时非常大。

我们做了很多,但这是一个讨厌的手动过程:

  1. 使用DTS将dbf文件导入临时数据库(2005版+管理工作室导入/导出向导)

  2. 使用SSMS运行清理脚本

  3. 导出dbf文件并用新修改的文​​件替换原始文件(备份它们)。

  4. 它对我们有用。

答案 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天内全功能试用期免费使用。