【问题标题】:Check if table exists in c#检查表是否存在于c#中
【发布时间】:2010-06-11 06:33:57
【问题描述】:

我想从一个名称由用户提供的表中读取数据。所以在实际开始读取数据之前,我想检查数据库是否存在。

我在 NET 上看到了几段声称可以做到这一点的代码。但是,它们似乎都只适用于 SQL 服务器、mysql 或其他一些实现。没有通用的方法来做到这一点吗?

(我已经在单独检查是否可以连接到提供的数据库,所以我相当确定可以打开到数据库的连接。)

【问题讨论】:

  • Check if a SQL table exists. 的可能重复项
  • @Graphain 好像是重复的,我应该做些什么吗?
  • 通常只是等待其他用户关闭并重定向,但这真的不是问题。

标签: c# sql


【解决方案1】:

您不能以跨数据库的方式执行此操作。一般来说,DDL(即创建表、索引等的代码)因数据库而异,因此检查表是否存在的逻辑也不同。

不过,我想说最简单的答案就是:

SELECT * FROM <table> WHERE 1 = 0

如果该查询出错,则该表不存在。如果它有效(尽管它会返回 0 行),则该表存在。

不过,要非常小心让用户输入的内容。是什么阻止他将“sysusers”指定为表名(在 SQL Server 中,这将是所有数据库用户的列表)

【讨论】:

  • 依靠错误来检查是否存在任何东西似乎是一个非常糟糕的主意!
  • 相反,我们知道这个查询没有错误。唯一的依赖是给定的表应该存在于给定连接的上下文中。任何错误都表示无法访问该表(或无法处理的奇怪/随机事件),因此我认为将引发的异常与无法访问所提供的表等同起来没有任何问题。
  • @Greg B:我不同意,我会说这是一种非常常见的模式:除了尝试打开文件之外,您如何检查文件是否存在?您如何检查域名是否有效,除非尝试将其解析为 IP?除了尝试向其发送电子邮件外,您如何检查电子邮件地址是否有效?等等……
  • 我不同意这是最好的方法。在您可以访问 information_schema.tables 的地方,您应该使用它。
【解决方案2】:

您可以使用 DbConnection.GetSchema 系列方法来检索有关数据库的元数据。它将返回带有模式对象的 DataTable。确切的对象类型和限制值可能因供应商而异,但我相信您可以以适用于大多数数据库的方式设置对特定表的检查。

这是一个使用 GetSchema 的示例,它将打印由“模式名称”拥有并称为“表名称”的每个表的名称和所有者。这是针对 oracle 进行测试的。

static void Main(string[] args)
{
    string providerName = @"System.Data.OracleClient";
    string connectionString = @"...";

    DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
    using (DbConnection connection = factory.CreateConnection())
    {
        connection.ConnectionString = connectionString;
        connection.Open();
        DataTable schemaDataTable = connection.GetSchema("Tables", new string[] { "schema name", "table name" });
        foreach (DataColumn column in schemaDataTable.Columns)
        {
            Console.Write(column.ColumnName + "\t");
        }
        Console.WriteLine();
        foreach (DataRow row in schemaDataTable.Rows)
        {
            foreach (object value in row.ItemArray)
            {
                Console.Write(value.ToString() + "\t");
            }
            Console.WriteLine();
        }
    }
}

【讨论】:

  • 当表不存在时,OracleConnectionSqlConnectionGetSchema 的实现将返回一个零行的DataTable。此结果可能与存在但没有列的表无法区分。但是,在 Oracle 和 SQL Server 中都不允许使用没有列的表。所以,bool doesTableExist = (schemaDataTable.Rows.Count == 0) 应该适合你。
【解决方案3】:

这就像在数据库中询问“是否存在获取相关数据的通用方法”。答案当然是否定的——唯一的“通用方式”是拥有一个隐藏特定数据源的实现细节并进行适当查询的数据层。

如果您真的支持和访问许多不同类型的数据库而不使用Stategy design pattern 或类似方法,我会感到非常惊讶。

话虽如此,最好的方法是这样的代码:

bool exists;

try
{
    // ANSI SQL way.  Works in PostgreSQL, MSSQL, MySQL.  
    var cmd = new OdbcCommand(
      "select case when exists((select * from information_schema.tables where table_name = '" + tableName + "')) then 1 else 0 end");

    exists = (int)cmd.ExecuteScalar() == 1;
}
catch
{
    try
    {
        // Other RDBMS.  Graceful degradation
        exists = true;
        var cmdOthers = new OdbcCommand("select 1 from " + tableName + " where 1 = 0");
        cmdOthers.ExecuteNonQuery();
    }
    catch
    {
        exists = false;
    }
}

来源:Check if a SQL table exists

【讨论】:

    【解决方案4】:

    你可以这样做:

    string strCheck = "SHOW TABLES LIKE \'tableName\'";
                    cmd = new MySqlCommand(strCheck, connection);
                    if (connection.State == ConnectionState.Closed)
                    {
                        connection.Open();
                    }
                    cmd.Prepare();
                    var reader = cmd.ExecuteReader();
                    if (reader.HasRows)
                    {                             
                      Console.WriteLine("Table Exist!");
                    }
                    else (reader.HasRows)
                    {                             
                      Console.WriteLine("Table Exist!");
                    }
    

    【讨论】:

      猜你喜欢
      • 2013-09-19
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多