检查SQL表是否存在

发布于 2024-07-13 07:30:52 字数 487 浏览 4 评论 0原文

以独立于数据库的方式检查 Sql 数据库中是否存在表的最佳方法是什么?

我想出了:

   bool exists;
   const string sqlStatement = @"SELECT COUNT(*) FROM my_table";

   try
    {
       using (OdbcCommand cmd = new OdbcCommand(sqlStatement, myOdbcConnection))
       {
            cmd.ExecuteScalar();
            exists = true;
       }
    }
    catch
    {
        exists = false;
    }

有更好的方法吗? 当数据库连接失败时,此方法将不起作用。 我已经找到了适用于 Sybase、SQL Server、Oracle 的方法,但没有一种方法适用于所有数据库。

What's the best way to check if a table exists in a Sql database in a database independant way?

I came up with:

   bool exists;
   const string sqlStatement = @"SELECT COUNT(*) FROM my_table";

   try
    {
       using (OdbcCommand cmd = new OdbcCommand(sqlStatement, myOdbcConnection))
       {
            cmd.ExecuteScalar();
            exists = true;
       }
    }
    catch
    {
        exists = false;
    }

Is there a better way to do this? This method will not work when the connection to the database fails. I've found ways for Sybase, SQL server, Oracle but nothing that works for all databases.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

走过海棠暮 2024-07-20 07:30:52
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;
    }
}
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;
    }
}
白龙吟 2024-07-20 07:30:52

如果您尝试实现数据库独立性,则必须采用最低标准。 IIRC ANSI INFORMATION_SCHEMA 视图是 ODBC 一致性所必需的,因此您可以查询反对他们,例如:

select count (*) 
  from information_schema.tables 
 where table_name = 'foobar'

鉴于您使用的是 ODBC,您还可以使用各种 ODBC API 调用也可检索此元数据。

请记住,可移植性等同于在任何地方编写一次测试,因此您仍然可以继续必须在您打算支持的每个平台上测试应用程序。 这意味着您本质上仅限于有限数量的可能数据库平台,因为您只有这么多的资源用于测试。

结果是您需要为您的应用程序找到一个最小公分母(这比 SQL 难得多)或构建一个依赖于平台的部分,其中不可移植的函数可以插入到每个平台上基础。

If you're trying for database independence you will have to assume a minimum standard. IIRC The ANSI INFORMATION_SCHEMA views are required for ODBC conformance, so you could query against them like:

select count (*) 
  from information_schema.tables 
 where table_name = 'foobar'

Given that you are using ODBC, you can also use various ODBC API calls to retrieve this metadata as well.

Bear in mind that portability equates to write-once test anywhere so you are still going to have to test the application on every platform you intend to support. This means that you are inherently limited to a finite number of possible database platforms as you only have so much resource for testing.

The upshot is that you need to find a lowest common denominator for your application (which is quite a lot harder than it looks for SQL) or build a platform-dependent section where the non-portable functions can be plugged in on a per-platform basis.

雨轻弹 2024-07-20 07:30:52

我认为不存在一种适用于所有数据库的通用方法,因为这是非常具体的方法,取决于数据库的构建方式。

但是,为什么要使用特定查询来执行此操作?
你不能将实现从你想做的事情中抽象出来吗?
我的意思是:为什么不创建一个通用接口,其中包括一个名为“TableExists( string tablename )”的方法。
然后,对于您想要支持的每个 DBMS,您创建一个实现此接口的类,并在 TableExists 方法中为该 DBMS 编写特定逻辑。
然后,SQLServer 实现将包含一个查询 sysobjects 的查询。

在您的应用程序中,您可以有一个工厂类,它为给定的上下文创建正确的实现,然后您只需调用 TableExists 方法。

例如:

IMyInterface foo = MyFactory.CreateMyInterface (SupportedDbms.SqlServer);

if( foo.TableExists ("mytable") )
...

我认为我应该这样做。

I don't think that there exists one generic way that works for all Databases, since this is something very specific that depends on how the DB is built.

But, why do you want to do this using a specific query ?
Can't you abstract the implementation away from what you want to do ?
I mean: why not create a generic interface, which has among others, a method called 'TableExists( string tablename )' for instance.
Then, for each DBMS that you want to support , you create a class which implements this interface, and in the TableExists method, you write specific logic for this DBMS.
The SQLServer implementation will then contain a query which queries sysobjects.

In your application, you can have a factory class which creates the correct implementation for a given context, and then you just call the TableExists method.

For instance:

IMyInterface foo = MyFactory.CreateMyInterface (SupportedDbms.SqlServer);

if( foo.TableExists ("mytable") )
...

I think this is how I should do it.

断舍离 2024-07-20 07:30:52

我完全支持 Frederik Gheysels 的回答。 如果必须支持多个数据库系统,则应该针对抽象接口实现代码,并为每个数据库系统提供特定的实现。 除了检查现有表之外,还有更多不兼容语法的示例(例如:将查询限制为一定数量的行)。

但是,如果您确实必须使用示例中的异常处理来执行检查,则应该使用比 COUNT(*) 更有效的以下查询,因为数据库没有实际的选择工作要做:

SELECT 1 FROM my_table WHERE 1=2

I fully support Frederik Gheysels answer. If you have to support multiple database systems, you should implement your code against an abstract interface with specific implementations per database system. There are many more examples of incompatible syntax than just checking for an existing table (e.g.: limiting the query to a certain number of rows).

But if you really have to perform the check using the exception handling from your example, you should use the following query that is more efficient than a COUNT(*) because the database has no actual selection work to do:

SELECT 1 FROM my_table WHERE 1=2
孤凫 2024-07-20 07:30:52

我会避免执行 select count(x) from xxxxxx ,因为 DBMS 实际上会继续执行此操作,这对于大型表可能需要一些时间。

相反,只需准备一个select * from mymytable查询。 如果神秘表不存在,准备将失败。 不需要实际执行准备好的语句。

I would avoid executing the select count(x) from xxxxxx as the DBMS will actually go ahead and do it which may take some time for a large table.

Instead just prepare a select * from mysterytable query. The prepare will fail if mysterytable does not exist. There is no need to actually execute the prepared statement.

旧情别恋 2024-07-20 07:30:52

以下对我来说效果很好......

private bool TableExists(SqlConnection conn, string database, string name)
{
    string strCmd = null;
    SqlCommand sqlCmd = null;

    try
    {
        strCmd = "select case when exists((select '['+SCHEMA_NAME(schema_id)+'].['+name+']' As name FROM [" + database + "].sys.tables WHERE name = '" + name + "')) then 1 else 0 end";
        sqlCmd = new SqlCommand(strCmd, conn);

        return (int)sqlCmd.ExecuteScalar() == 1;
    }
    catch { return false; }
}

The following works well for me...

private bool TableExists(SqlConnection conn, string database, string name)
{
    string strCmd = null;
    SqlCommand sqlCmd = null;

    try
    {
        strCmd = "select case when exists((select '['+SCHEMA_NAME(schema_id)+'].['+name+']' As name FROM [" + database + "].sys.tables WHERE name = '" + name + "')) then 1 else 0 end";
        sqlCmd = new SqlCommand(strCmd, conn);

        return (int)sqlCmd.ExecuteScalar() == 1;
    }
    catch { return false; }
}
吻泪 2024-07-20 07:30:52

在我当前的工作项目中,我需要编写支持多种数据库类型的“数据代理”。

所以我决定下一步:使用虚拟方法编写具有基本(独立于数据库)功能的基类,并在子类中覆盖所有特定于数据库的时刻

In current project on my job I need to write 'data agent' which would support a lot of database types.

So I decided to do next: write a base class with the base (database independent) functionality using virtual methods and override in subclasses all database-specific moments

得不到的就毁灭 2024-07-20 07:30:52

很简单

use YOUR_DATABASE --OPTIONAL
SELECT count(*) as Exist from INFORMATION_SCHEMA.TABLES where table_name = 'YOUR_TABLE_NAME'

如果答案是1,就有一个表。
如果答案为 0,则没有表。

Very Simple

use YOUR_DATABASE --OPTIONAL
SELECT count(*) as Exist from INFORMATION_SCHEMA.TABLES where table_name = 'YOUR_TABLE_NAME'

If the answer is 1, There is a table.
If the answer is 0, There is no table.

小女人ら 2024-07-20 07:30:52

如果您想避免 try-catch 解决方案,我建议使用 sys.tables 这种方法

private bool IsTableExisting(string table)
    {
        string command = $"select * from sys.tables";
        using (SqlConnection con = new SqlConnection(Constr))
        using (SqlCommand com = new SqlCommand(command, con))
        {
            SqlDataReader reader = com.ExecuteReader();
            while (reader.Read())
            {
                if (reader.GetString(0).ToLower() == table.ToLower())
                    return true;
            }
            reader.Close();
        }
        return false;
    }

If you want to avoid try-catch solutions, I'm suggesting this method, using sys.tables

private bool IsTableExisting(string table)
    {
        string command = $"select * from sys.tables";
        using (SqlConnection con = new SqlConnection(Constr))
        using (SqlCommand com = new SqlCommand(command, con))
        {
            SqlDataReader reader = com.ExecuteReader();
            while (reader.Read())
            {
                if (reader.GetString(0).ToLower() == table.ToLower())
                    return true;
            }
            reader.Close();
        }
        return false;
    }
一个人练习一个人 2024-07-20 07:30:52

尝试下面的代码:

public bool CheckTableExists(string connectionString, string tableName)
{
    var connection = new SqlConnection(connectionString);

    try
    {
        var command = new SqlCommand($"IF OBJECT_ID('{tableName}') IS NOT NULL SELECT 'TRUE' ELSE SELECT 'FALSE'", connection);
        connection.Open();
        return bool.Parse(command.ExecuteScalar().ToString());
    }
    catch(Exception ex)
    {
        return false;   
    }
    finally
    {
        if(connection.State == ConnectionState.Open) connection.Close();
    }
}

Try the below code:

public bool CheckTableExists(string connectionString, string tableName)
{
    var connection = new SqlConnection(connectionString);

    try
    {
        var command = new SqlCommand(
quot;IF OBJECT_ID('{tableName}') IS NOT NULL SELECT 'TRUE' ELSE SELECT 'FALSE'", connection);
        connection.Open();
        return bool.Parse(command.ExecuteScalar().ToString());
    }
    catch(Exception ex)
    {
        return false;   
    }
    finally
    {
        if(connection.State == ConnectionState.Open) connection.Close();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文