【问题标题】:fast/efficient way to run a query in Access based on datatable rows?基于数据表行在 Access 中运行查询的快速/高效方法?
【发布时间】:2013-07-01 16:05:05
【问题描述】:

我有一个可能有 1000 行左右的数据表。我需要逐行遍历数据表,获取列的值,运行查询(Access 2007 DB)并用结果更新数据表。到目前为止,这是我所拥有的,有效的:

String FilePath = "c:\\MyDB.accdb";

string QueryString = "SELECT MDDB.NDC, MDDB.NDC_DESC "
    + "FROM MDDB_MASTER AS MDDB WHERE MDDB.NDC = @NDC";

OleDbConnection strAccessConn = new OleDbConnection(string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FilePath));
strAccessConn.Open();
OleDbDataReader reader = null;

int rowcount = InputTable.Rows.Count; //InputTable is the datatable
int count = 0;

while (count < rowcount)
{
    string NDC = InputTable.Rows[count]["NDC"].ToString(); 
    //NDC is a column in InputTable                      

    OleDbCommand cmd = new OleDbCommand(QueryString, strAccessConn);
    cmd.Parameters.Add("@NDC", OleDbType.VarChar).Value = NDC;

    reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        //update the NDCDESC column with the query result
        //the query should only return 1 line
        dataSet1.Tables["InputTable"].Rows[count]["NDCDESC"] = reader.GetValue(1).ToString();
    }

    dataGridView1.Refresh();
    count++;
}
strAccessConn.Close();

但是这似乎非常低效,因为查询需要为数据表中的每一行运行一次。有没有更好的办法?

【问题讨论】:

  • 想知道如果您尝试在 sproc 中完成所有这些操作会怎样?
  • 什么版本的 Access?
  • @EkoostikMartin - 访问 2007
  • MDDB_MASTER 表是否很大?您可以通过运行不带 WHERE 子句的查询来复制整个表,然后使用 LINQ 搜索 .NET DataTable 对象
  • @nicholas - MDDB_MASTER 有 225,000 行和 75 列,因此相当大。

标签: c# sql ms-access datatable


【解决方案1】:

您正在考虑update query。您实际上不必逐行检查每一行。 SQL 是set based language,因此您只需编写一条语句,它应该为所有行执行。

这样做:

1) 创建 > 查询设计

2) 关闭选择表格的对话框

3) 确保您处于 sql 模式(左上角)

4) 粘贴:

UPDATE INPUTTABLE 
INNER JOIN MDDB_MASTER ON INPUTTABLE.NDC = MDDB_MASTER.NDC 
SET INPUTTABLE.NDCDESC = [MDDB_MASTER].[NDC_DESC];

5) 切换到设计模式看看会发生什么。您可能需要更正输入表,我找不到它的名称。我假设他们都在同一个数据库中。

您会看到查询类型现在是更新查询。

您可以通过cmd.ExecuteNonQuery(sql) 运行此文本,整个过程应该运行得非常快。如果没有,您需要在其中一张表上建立索引;

这是通过连接 NDC 上的两个表,然后将 NDC_DESC 从 MDDB_MASTER 复制到输入表来工作的。

【讨论】:

  • 有趣!我会试一试。谢谢!!
  • InputTable 是否也在 Access 中?根据 OP cmets,它是从 Excel 电子表格加载的。
  • 好吧,错过了关于 Excel 的那部分,你可能不得不把它吸进一个临时表中,然后把它放回 Excel。
  • 我可以将 Excel 文件“InputTable”复制到 Access 中的临时表中,但我想我会将 MDDB_MASTER 复制到临时数据表中。
【解决方案2】:

我错过了来自 Excel 的关于 InputTable 的部分。

为了更快的速度,您可以在一个 select 语句中将所有行从 MDDB_MASTER 获取到数据表中,而不是一遍又一遍地执行 Access 中的查询:

SELECT MDDB.NDC, MDDB.NDC_DESC FROM MDDB_MASTER

然后使用DataTable.Select方法过滤右边的行。

mddb_master.Select("NDC = '" + NDC +'")

这将在内存中完成,并且应该比您现在所有的往返速度快得多。尤其是通过网络,这些往返行程非常昂贵。 225k 行应该只有几 MB(大约是 JPEG 图像),所以这不成问题。

【讨论】:

  • 谢谢 gjvdkamp .. 我认为将数据从 MDDB_MASTER 拉到临时数据表中是可行的方法。
【解决方案3】:

您可以使用“IN”子句来构建更大的查询,例如:

string QueryString = "SELECT MDDB.NDC, MDDB.NDC_DESC "
    + "FROM MDDB_MASTER AS MDDB WHERE MDDB.NDC IN (";

int rowcount = InputTable.Rows.Count; //InputTable is the datatable
int count = 0;

while (count < rowcount)
{
    string NDC = InputTable.Rows[count]["NDC"].ToString(); 
    QueryString += (count == 0 ? "" : ",") + "'" + NDC + "'";
}
QueryString += ")";

您可以使用 StringBuilders 对其进行优化,因为这可能是很多字符串,但这是您的工作。 :)

然后在单个查询中,您将获得所需的所有 NDC 描述,并避免执行 1000 次查询。然后,您将翻阅阅读器,在 InputTable 中查找值并更新它们。当然,在这种情况下,您将多次循环通过 InputTable,但这可能是一个更好的选择。特别是如果你的 InputTable 可以保存重复的 NDC 值。

另外,请注意您的代码中存在 OleDbDataReader 泄漏。在处置旧阅读器之前,您不断将阅读器引用重新分配给阅读器的新实例。与命令相同。您不断实例化一个新命令,但没有正确处理它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    相关资源
    最近更新 更多