Подтвердить что ты не робот

Проверьте, существует ли таблица SQL

Какой лучший способ проверить, существует ли таблица в базе данных 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-сервера, Oracle, но ничего не работает для всех баз данных.

4b9b3361

Ответ 1

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

Ответ 2

Я не думаю, что существует один общий способ, который работает для всех баз данных, поскольку это что-то очень специфическое, которое зависит от того, как создается БД.

Но почему вы хотите сделать это, используя конкретный запрос? Не можете ли вы отвлечь выполнение от того, что хотите? Я имею в виду: почему бы не создать общий интерфейс, среди которого, например, метод "TableExists (string tablename)". Затем для каждой СУБД, которую вы хотите поддерживать, вы создаете класс, который реализует этот интерфейс, и в методе TableExists вы пишете конкретную логику для этой СУБД.
Затем реализация SQLServer будет содержать запрос, который запрашивает sysobjects.

В вашем приложении вы можете иметь класс factory, который создает правильную реализацию для данного контекста, а затем вы просто вызываете метод TableExists.

Например:

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

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

Я думаю, именно так я должен это делать.

Ответ 3

Если вы пытаетесь добиться независимости базы данных, вам придется принять минимальный стандарт. IIRC ANSI INFORMATION_SCHEMA виды необходимы для соответствия ODBC, поэтому вы можете запросить их:

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

Учитывая, что вы используете ODBC, вы также можете использовать различные методу однократной записи в любом месте, поэтому вам все равно придется тестировать приложение на каждой платформе, которую вы планируете поддерживать. Это означает, что вы по сути ограничены конечным числом возможных платформ базы данных, поскольку у вас есть только столько ресурсов для тестирования.

Результат заключается в том, что вам нужно найти самый низкий общий знаменатель для вашего приложения (что намного сложнее, чем он ищет SQL) или построить секцию, зависящую от платформы, где не переносные функции могут быть подключены к на основе платформы.

Ответ 4

Я полностью поддерживаю ответ Фредерика Гейзеля. Если вам необходимо поддерживать несколько систем баз данных, вы должны реализовать свой код против абстрактного интерфейса с конкретными реализациями в системе баз данных. Существует еще много примеров несовместимого синтаксиса, чем просто проверка существующей таблицы (например: ограничение запроса на определенное количество строк).

Но если вам действительно нужно выполнить проверку, используя обработку исключений из вашего примера, вы должны использовать следующий запрос, который более эффективен, чем COUNT (*), потому что в базе данных нет фактической работы выбора:

SELECT 1 FROM my_table WHERE 1=2

Ответ 5

Я бы не выполнил select count(x) from xxxxxx, поскольку СУБД действительно продолжит работу и сделает это, что может занять некоторое время для большой таблицы.

Вместо этого просто подготовьте a select * from mysterytable запрос. Подготовка не сработает, если таинственный не существует. Нет необходимости фактически выполнять подготовленный оператор.

Ответ 6

В текущем проекте моей работы мне нужно написать "агент данных", который будет поддерживать множество типов баз данных.

Итак, я решил сделать следующее: напишите базовый класс с базовыми (независимыми от базы данных) функциями с использованием виртуальных методов и переопределите в подклассах все моменты, относящиеся к базе данных

Ответ 7

Следующее хорошо работает для меня...

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

Ответ 8

Если вы хотите избежать решений 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;
    }

Ответ 9

Очень просто

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

Если ответ равен 1, существует таблица. Если ответ равен 0, таблицы нет.