1

这个查询:

string.Format("SELECT COUNT(*) FROM {0}", tableName);

...我将其用作“isValidTable(string tableName)”方法的核心,如果 tableName 不存在(特别是“指定的表不存在”),则会引发异常。

既然如此(它玩得不好,如果它不识别表名,它就会举手)让我想知道这段代码是否:

public bool isValidTable(string tableName)
{
    bool validTable = false;
    string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
    try
    {
        SqlCeCommand cmd = new SqlCeCommand();
        cmd.CommandText = tblQuery;
        object objcnt = cmd.ExecuteScalar();
        if ((objcnt != null) && (objcnt != DBNull.Value)) 
        {
            validTable = Int32.Parse(objcnt.ToString()) > 0;
        } 
        else 
        {
            MessageBox.Show("NULL returned from isValidTable(). Remove this line."); //<- I never see this; if this is the case, an exception has been thrown
        }
    }
    catch 
    {
        return false;
    }
    return validTable;
}

...可以/应该简化为:

public bool isValidTable(string tableName)
{
    string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
    try
    {
        SqlCeCommand cmd = new SqlCeCommand();
        cmd.CommandText = tblQuery;
        cmd.ExecuteScalar();
    }
    catch 
    {
        return false;
    }
    return true;
}

?

更新

jp2code 认为:“在存在时选择案例((从 information_schema.tables 中选择 *,其中 table_name = '{0}'))然后 1 else 0 end”

是否有类似的代码来检查列是否存在?目前我的 isValidTable() 和 isValidColumn() 查询是相似的:

string tableQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
string columnQuery = string.Format("SELECT COUNT({0}) FROM {1}", columnName, tableName);

...但是如果我能够将其用于 isValidTable():

string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end",
tableName);

...是否还有可用于检查有效列的扩展?就像是:

string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}' and column_name = '{1}')) then 1 else 0 end",
tableName, columnName);

???

更新 2

我意识到建议的 sql 比“我的方式”“更好”,但无论出于何种原因,当我使用“首选方法”时,所需的数据表不会被识别为存在(尽管它们确实存在) . 我正在使用的旧版软件不接受嵌套选择/子选择,或者......???

无论如何,评论讲述了这个故事:

string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
// This is doubtless "more better," but when I use it, I get "No current work; no inventory file"
//string tblQuery = string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end", tableName);
4

3 回答 3

2

您应该只对异常(超出规范)的事物使用异常,无法找到表被认为是该方法的正常执行,因此不应依赖异常发生。

对于您的示例来说,超出标准的事情是连接超时,这不是您的方法的标准操作。

相反,您应该查询sys.tablesorINFORMATION_SCHEMA.TABLES表以查看您的表是否存在。

于 2013-04-02T21:11:29.850 回答
1

如果我遇到同样的问题,我更喜欢在系统表中查找,正如 Matthew 指出的那样,检查表是否存在,以及我使用的数据库是否不给我这样做的可能性,我将通过创建一个跟踪现有表的表来模拟它。查询该表,而不是将代码包装在 by try catch 块中。不是一个优雅的解决方案,但在我谦虚的角度来看更干净

于 2013-04-02T22:04:52.983 回答
1

如果您继续使用它,至少指定一个SqlCeException您捕获并忽略的,这样您就不会在不知不觉中忽略可能发生的其他错误。

至于检查表是否存在,请参阅这篇热门帖子:

检查 SQL Server 中是否存在表

真的,如果你的代码有效,你就不应该有任何例外。所以在调试并且你的代码准备好发布之后,它应该看起来更像这样:

public bool isValidTable(string tableName)
{
  bool validTable = false;
  string tblQuery =
    string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end",
    tableName);
  SqlCeCommand cmd = new SqlCeCommand();
  cmd.CommandText = tblQuery;
  try
  {
    cmd.Connection.Open();
    object objcnt = cmd.ExecuteScalar();
    if ((objcnt != null) && (objcnt != DBNull.Value)) 
    {
      validTable = Int32.Parse(objcnt.ToString()) > 0;
    } 
  }
  finally
  {
    cmd.Connection.Close();
  }
  return validTable;
}

该特定 SQL 查询使用此 SO question 的解决方案:

检查是否存在 SQL 表

更新:这个DataReader Check 例程怎么样:

public bool isValidTable(string tableName)
{
  bool validTable = false;
  string tblQuery =
    string.Format("select * from information_schema.tables where table_name='{0}'",
    tableName);
  SqlCeCommand cmd = new SqlCeCommand();
  cmd.CommandText = tblQuery;
  try
  {
    cmd.Connection.Open();
    // I don't know if this works because I don't have .NET 1.1
    SqlCeDataReader r = cmd.ExecuteReader();
    validTable = r.Read();
  }
  finally
  {
    cmd.Connection.Close();
  }
  return validTable;
}

MSDN 上关于 DataReader 1.1的文档说(在备注中)SqlCeDataReader 的默认位置在第一条记录之前。要开始访问任何数据,您必须调用 Read。因此,它应该从 Index = -1 开始,并且需要一个 Read 调用才能进入数据的第一步。

于 2013-04-03T13:34:54.827 回答