5

I want to read data from a table whose name is supplied by a user. So before actually starting to read data, I want to check if the database exists or not.

I have seen several pieces of code on the NET which claim to do this. However, they all seem to be work only for SQL server, or for mysql, or some other implementation. Is there not a generic way to do this?

(I am already seperately checking if I can connect to the supplied database, so I'm fairly certain that a connection can be opened to the database.)

apoorv020
  • 5,420
  • 11
  • 40
  • 63

4 Answers4

3

You cannot do this in a cross-database way. Generally DDL (that is, the code for creating tables, indexes and so on) is completely different from database to database and so the logic for checking whether tables exist is also different.

I would say the simplest answer, though, would simply be something like:

SELECT * FROM <table> WHERE 1 = 0

If that query gives an error, then the table doesn't exist. If it works (though it'll return 0 rows) then the table exists.

Be very careful with what you let the user input, though. What's to stop him from from specifying "sysusers" as the table name (in SQL Server, that'll be the list of all database users)

Dean Harding
  • 71,468
  • 13
  • 145
  • 180
  • 1
    Relying on an error to check for the existence of anything seems like a really bad idea! – Greg B Jun 11 '10 at 07:45
  • 3
    On the contrary, we know that this query contains no errors. The only dependency is that the given table should exist in the context of the given connection. ANY error would signify that the table cannot be accessed(or something so weird/random that cannot be dealt with) , so I dont see any problems in equating a raised exception with the lack of access to the supllied table. – apoorv020 Jun 11 '10 at 08:14
  • 1
    @Greg B: I disagree, I would say it's a very common pattern: how do you check a file exists, except by trying to open it? How do you check a domain name is valid, except by trying to resolve it to an IP? How do you check an email address is valid, except by trying to send an email to it? And so on... – Dean Harding Jun 11 '10 at 09:25
  • 1
    I'd disagree that this is the best way. Where you have access to information_schema.tables you should use that. – Matt Mitchell Jun 14 '10 at 13:05
3

You can use the DbConnection.GetSchema family of methods to retreive metadata about the database. It will return a DataTable with schema objects. The exact object types and restriction values may vary from vendor to vendor, but I'm sure you can set up your check for a specific table in a way that will work in most databases.

Here's an example of using GetSchema that will print the name and owner of every table that is owned by "schema name" and called "table name". This is tested against 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();
        }
    }
}
kicsit
  • 638
  • 5
  • 6
  • When a table does not exist, both `OracleConnection`'s and `SqlConnection`'s, implementation of `GetSchema` will return a DataTable with zero rows. This result may be indistinguishable from a table that exists, but has no columns. However, tables with no columns are not allowed in both Oracle and SQL Server. So, `bool doesTableExist = (schemaDataTable.Rows.Count == 0)` should work for you. – Walter Stabosz Nov 03 '17 at 16:13
1

That's like asking "is there a generic way to get related data" in databases. The answer is of course no - the only "generic way" is to have a data layer that hides the implementation details of your particular data source and queries it appropriately.

If you are really supporting and accessing many different types of databases without a Stategy design pattern or similar approach I would be quite surprised.

That being said, the best approach is something like this bit of code:

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;
    }
}

Source: Check if a SQL table exists

Community
  • 1
  • 1
Matt Mitchell
  • 40,943
  • 35
  • 118
  • 185
0

You can do something like this:

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!");
                }
Manish Jain
  • 448
  • 1
  • 5
  • 11