Compruebe si la Base de Datos Existe Antes De Crear


Esto parece bastante trivial, pero ahora me está frustrando.

Estoy usando C# con SQL Server 2005 Express.

Estoy usando el siguiente código. Quiero comprobar si existe una base de datos antes de crearla. Sin embargo, el entero devuelto es -1 y así es como MSDN define lo que ExecuteNonQuery() devolverá también. Ahora, la base de datos existe, pero todavía se devuelve -1. Dicho esto, ¿cómo puedo hacer que esto funcione para obtener el resultado deseado?

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) { }

}
Author: sandeep.gosavi, 2010-02-09

6 answers

A partir de SQL Server 2005, el estilo antiguo sysobjects y sysdatabases y esas vistas de catálogo han sido obsoletas. Haga esto en su lugar-use las vistas de esquema sys. como 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;
}

Esto funcionará con cualquier nombre de base de datos que pase como parámetro, y devolverá un bool true = database exists, false = database does not exist (o ocurrió un error).

 48
Author: marc_s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-27 06:17:12

Leyendo esto unos años después y hay una forma más limpia de expresar esto:

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);
           }
      }
}
 30
Author: Stephen Lloyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-30 11:10:25

¿No debería esto

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

Ser esto?

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

También según MSDN

Para las instrucciones UPDATE, INSERT y DELETE, el valor devuelto es el número de filas afectadas por el comando. Cuando existe un desencadenador en una tabla que se está insertando o actualizando, el valor devuelto incluye el número de filas afectadas por la operación insertar o actualizar y el número de filas afectadas por el desencadenador o desencadenadores. Para todos los demás tipos de sentencias, el valor devuelto es -1. Si a se produce la reversión, el valor devuelto también es -1.

Está haciendo una instrucción SELECT not an DML. ¿Por qué no usas un método ExecuteReader en su lugar?

 7
Author: SQLMenace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-09 20:39:07

Una alternativa a consultar las vistas del sistema es usar la función db_id que devuelve el Id de la base de datos si existe, de lo contrario null. Ejemplo T-SQL a continuación:

if (db_id('INVENTORY') is null)
begin
    return 0
end
else
begin
    return 1
end
 3
Author: Daniel James Bryars,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-07 05:49:15

No puede usar ExecuteNonQuery porque siempre devolverá -1 para SELECT, como muestra el enlace MSDN.

Tendrá que usar un conjunto de resultados del proceso, por ejemplo SELECT DB_ID('INVENTORY') AS DatabaseID o usar una variable / parámetro: SELECT @DatabaseID = DB_ID('INVENTORY')

 3
Author: gbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-16 16:09:32

Para el beneficio de los buscadores, si está utilizando Entity Framework, esto funcionará:

using (var ctx = new MyDataModel())
{
    dbExists = System.Data.Entity.Database.Exists(ctx.Database.Connection);
}
 0
Author: HockeyJ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-05 17:00:46