这看起来很微不足道,但现在让我感到沮丧。
我正在使用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) { }
}
答案 0 :(得分:54)
从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 = database exists,false = database不存在(或发生错误)。
答案 1 :(得分:32)
阅读这几年,有一种更清晰的表达方式:
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);
}
}
}
答案 2 :(得分:7)
不应该这个
"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 :(得分:3)
您不能使用ExecuteNonQuery,因为对于SELECT,它总是会返回-1,如MSDN链接所示。
您必须使用结果集处理,例如SELECT DB_ID('INVENTORY') AS DatabaseID
或使用变量/参数:SELECT @DatabaseID = DB_ID('INVENTORY')
答案 4 :(得分:3)
查询系统视图的另一种方法是使用函数db_id,如果存在则返回数据库的Id,否则返回null。下面的示例T-SQL:
if (db_id('INVENTORY') is null)
begin
return 0
end
else
begin
return 1
end
答案 5 :(得分:0)
为了搜索者的利益,如果您使用的是实体框架,this将起作用:
using (var ctx = new MyDataModel())
{
dbExists = System.Data.Entity.Database.Exists(ctx.Database.Connection);
}
答案 6 :(得分:0)
采用Stephen Lloyd的代码,并添加了一些异步和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);
}
}
答案 7 :(得分:0)
使用此程序集:Microsoft.SqlServer.SqlManagementObjects
=> NuGet
using Microsoft.SqlServer.Management.Smo;
var dbExists = new Server(serverOrInstanceName).Databases.Contains(dataBaseName);