Проверьте, существует ли база данных перед созданием - PullRequest
33 голосов
/ 09 февраля 2010

Это кажется довольно тривиальным, но теперь это меня расстраивает.

Я использую C # с SQL Server 2005 Express.

Я использую следующий код.Я хочу проверить, существует ли база данных перед ее созданием.Однако возвращаемое целое число равно -1, и именно так MSDN определяет, что ExecuteNonQuery () также будет возвращать.Сейчас база данных существует, но она все еще возвращает -1.Сказав это, как я могу сделать эту работу, чтобы получить желаемый результат?

private static void checkInventoryDatabaseExists(ref SqlConnection tmpConn, ref bool databaseExists)
{
    string sqlCreateDBQuery;
    try
    {
        tmpConn = new SqlConnection("server=(local)\\SQLEXPRESS;Trusted_Connection=yes");

        sqlCreateDBQuery = "SELECT * FROM master.dbo.sysdatabases where name = 
        \'INVENTORY\'";

        using (tmpConn)
        {
            tmpConn.Open();
            tmpConn.ChangeDatabase("master");

            using (SqlCommand sqlCmd = new SqlCommand(sqlCreateDBQuery, tmpConn))
            {
                int exists = sqlCmd.ExecuteNonQuery();

                if (exists <= 0)
                    databaseExists = false;
                else
                    databaseExists = true;
            }
        }
    }
    catch (Exception ex) { }

}

Ответы [ 7 ]

54 голосов
/ 09 февраля 2010

Начиная с SQL Server 2005, устаревшие sysobjects и sysdatabases и эти представления каталога устарели. Сделайте это вместо этого - используйте схему sys. - представления как sys.databases

private static bool CheckDatabaseExists(SqlConnection tmpConn, string databaseName)
{
    string sqlCreateDBQuery;
    bool result = false;

    try
    {
        tmpConn = new SqlConnection("server=(local)\\SQLEXPRESS;Trusted_Connection=yes");

        sqlCreateDBQuery = string.Format("SELECT database_id FROM sys.databases WHERE Name 
        = '{0}'", databaseName);

        using (tmpConn)
        {
            using (SqlCommand sqlCmd = new SqlCommand(sqlCreateDBQuery, tmpConn))
            {
                tmpConn.Open();

                object resultObj = sqlCmd.ExecuteScalar();

                int databaseID = 0;    

                if (resultObj != null)
                {
                    int.TryParse(resultObj.ToString(), out databaseID);
                }

                tmpConn.Close();

                result = (databaseID > 0);
            }
        }
    } 
    catch (Exception ex)
    { 
        result = false;
    }

    return result;
}

Это будет работать с любым именем базы данных, которое вы передаете в качестве параметра, и возвращает bool true = база данных существует, false = база данных не существует (или произошла ошибка).

32 голосов
/ 18 ноября 2015

Прочтите это через несколько лет, и есть более чистый способ выразить это:

public static bool CheckDatabaseExists(string connectionString, string databaseName)
{
      using (var connection = new SqlConnection(connectionString))
      {
           using (var command = new SqlCommand($"SELECT db_id('{databaseName}')", connection))
           {
                connection.Open();
                return (command.ExecuteScalar() != DBNull.Value);
           }
      }
}
7 голосов
/ 09 февраля 2010

не должно это

"SELECT * FROM master.dbo.sysdatabases where name = \'INVENTORY\'"

быть этим?

"SELECT * FROM master.dbo.sysdatabases where name = 'INVENTORY'"

Также по MSDN

Для операторов UPDATE, INSERT и DELETE возвращаемое значение - это количество строк, затронутых командой. Если для вставляемой или обновляемой таблицы существует триггер, возвращаемое значение включает количество строк, на которые влияет операция вставки или обновления, и количество строк, на которые влияет триггер или триггеры. Для всех других типов операторов возвращаемое значение равно -1. Если происходит откат, возвращаемое значение также равно -1.

Вы делаете SELECT, а не оператор DML. Почему бы вам не использовать метод ExecuteReader вместо этого?

3 голосов
/ 07 июля 2011

Альтернативой запросу системных представлений является использование функции db_id, которая возвращает идентификатор базы данных, если он существует, в противном случае - ноль. Пример T-SQL ниже:

if (db_id('INVENTORY') is null)
begin
    return 0
end
else
begin
    return 1
end
3 голосов
/ 09 февраля 2010

Вы не можете использовать ExecuteNonQuery , потому что он всегда будет возвращать -1 для SELECT, как показывает ссылка MSDN.

Вам нужно будет обработать набор результатов, например, SELECT DB_ID('INVENTORY') AS DatabaseID или использовать переменную / параметр: SELECT @DatabaseID = DB_ID('INVENTORY')

0 голосов
/ 15 октября 2018

Взял код Стивена Ллойда и добавил некоторые асинхронные и SQL-инъекции.

public static async Task<bool> TestDatabase(string connectionString, string databaseName)
{
   using (var connection = new SqlConnection(connectionString))
   using (var command = new SqlCommand("SELECT db_id(@databaseName)", connection))
   {
       command.Parameters.Add(new SqlParameter("databaseName", databaseName));

       connection.Open();

       return (await command.ExecuteScalarAsync() != DBNull.Value);
   }
}
0 голосов
/ 05 января 2018

Для удобства пользователей, если вы используете Entity Framework, это будет работать:

using (var ctx = new MyDataModel())
{
    dbExists = System.Data.Entity.Database.Exists(ctx.Database.Connection);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...