C# 如何使用c代码检查sql server中是否存在存储过程

C# 如何使用c代码检查sql server中是否存在存储过程,c#,sql,sql-server,stored-procedures,C#,Sql,Sql Server,Stored Procedures,我试过下面的代码来检查SP是否存在。如果不存在,我正在创建 但每次显示sp未创建时……但我的数据库中已存在此sp 让我知道我哪里做错了 string checkSP = String.Format( "IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'", "GP_SOP_AdjustTax"); SqlCommand command = new SqlCommand(checkSP, myCo

我试过下面的代码来检查SP是否存在。如果不存在,我正在创建

但每次显示sp未创建时……但我的数据库中已存在此sp

让我知道我哪里做错了

string checkSP = String.Format(
  "IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'", 
  "GP_SOP_AdjustTax");

SqlCommand command = new SqlCommand(checkSP, myConnection);
command.CommandType = CommandType.Text;

if (myConnection == null || myConnection.State == ConnectionState.Closed)
{
    try
    {
        myConnection.Open();
    }
    catch (Exception a)
    {
        MessageBox.Show("Error " + a.Message);
    }
}

bool Exist = false;
Exist = Convert.ToBoolean(command.ExecuteScalar());
if (Exist == false)   //false : SP does not exist
{ 
    // here i am writing code for creating SP
}

您可以使用以下适用于SQL Server的tsql查询进行检查:

select * from sysobjects where ytype='P' and name='MyStoredProcedureName'
若查询返回行,则存在名为“MyStoredProcedureName”的存储过程

下面是如何在代码中使用它:

        //TODO: set connection string
        string connString = "";
        string query = "select * from sysobjects where ytype='P' and name='MyStoredProcedureName'";
        bool spExists = false;
        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            using (SqlCommand command = new SqlCommand(query,conn))
            {
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        spExists = true;
                        break;
                    }
                }
            }
        }
尝试:

我发现这个

尝试:

试试这个

if object_id('YourStoredProcedureName') is null
    exec ('create procedure dbo.YourSp as select 1')
go
alter procedure dbo.YourStoredProcedure
as
如果将“U”改为“p”,则可以。 使用“U”查询用户表,其中“P”提供存储过程

对于使用实体框架和DbContext的用户:

internal static class DbContextExtensions
{
    public static bool StoredProcedureExists(this DbContext context,
        string procedureName)
    {
        string query = String.Format(
            @"select top 1 from sys.procedures " +
              "where [type_desc] = '{0}'", procedureName);
        return dbContext.Database.SqlQuery<string>(query).Any();
    }
}
为DbContext创建扩展类:

internal static class DbContextExtensions
{
    public static bool StoredProcedureExists(this DbContext context,
        string procedureName)
    {
        string query = String.Format(
            @"select top 1 from sys.procedures " +
              "where [type_desc] = '{0}'", procedureName);
        return dbContext.Database.SqlQuery<string>(query).Any();
    }
}
正如Robii所说,此代码不应发布给外部世界,因为它会使数据库易受黑客攻击谢谢Robii!。要防止这种情况,请使用参数化语句

解决方案是将procedureName作为参数放入SQL语句中。SQL将检查字符串参数是否具有所需的格式,从而禁止恶意调用:

public static bool ImprovedExists(this DbContext dbContext, string procedureName)
{
    object[] functionParameters = new object[]
    {
        new SqlParameter(@"procedurename", procedureName),
    };
    const string query = @"select [name] from sys.procedures where name= @procedurename";
    return dbContext.Database.SqlQuery<string>(query, functionParameters).Any();
}
我的一针见血:

可重用扩展方法 最小Sql/最小C 作为OP隐式请求从.Net调用 由于object_id函数,速度可能会更快 公共静态布尔存储过程存在此字符串源 { 使用var conn=new SQLConnectionConfiguration Manager.ConnectionString[ConnectionString].ConnectionString { 康涅狄格开放大学; 使用var cmd=new SqlCommand$select object_id'{source}',conn return!cmd.ExecuteScalar.ToString.IsNullOrWhiteSpace; } } 处理具有不同架构的过程名称 带括号和不带括号的名称[] 使用参数来避免SQL注入 注意:调用方拥有SQL连接

public static class SqlConnectionExtensions
{        
    public static Task<bool> StoredProcedureExistsAsync(this SqlConnection sqlConnection, string storedProcedureName)
    {
        string query = "SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(@storedProcedureName) AND type in (N'P', N'PC')";

        using (SqlCommand command = new SqlCommand(query, sqlConnection))
        {
            command.Parameters.AddWithValue("@storedProcedureName", storedProcedureName);
            using (SqlDataReader reader = command.ExecuteReader())
            {
                return reader.ReadAsync();
            }
        }
    }
}

我认为以下内容适用于MySQL、SQL Server和Oracle:

SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE='PROCEDURE'
AND (ROUTINE_SCHEMA='questionnaire' OR ROUTINE_CATALOG = 'questionnaire')
AND SPECIFIC_NAME='create_question';
用法:

string procedureName = "create_question";
using (DbConnection conn = new SqlConnection("Server=localhost;Database=questionnaire;Trusted_Connection=True;")) // Connection is interchangeable
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = $"SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE='PROCEDURE' AND (ROUTINE_SCHEMA='{conn.Database}' OR ROUTINE_CATALOG = '{conn.Database}') AND SPECIFIC_NAME='{procedureName}';";
        return cmd.ExecuteScalar() != null;
    }
}

有些系统视图应该可以访问,只需对它们进行查询,查看您是否有SP或特定SP。我记不起系统视图/表的名称,但很容易在数据库中找到。为什么要使用读卡器。在while循环中阅读?有一个if检查就足够了吗?如果你真的要返回超过一行,那么你应该把它放在一个while循环中。如果只需要0行或1行,则可以使用If check…或使用select top 1。。。。;这将确保您将始终获得0不存在或1存在的行。这不是架构感知,您将获得具有相同名称和不同架构的过程的误报。例如dbo.MyStoredProcedureName和SomeSchema.MyStoredProcedureName。它也不会使名称正常化,因此[MyStoredProcedureName]不会返回任何结果。以下雅各布·科内基的回答涉及这两种情况使用
internal static class DbContextExtensions
{
    public static bool StoredProcedureExists(this DbContext context,
        string procedureName)
    {
        string query = String.Format(
            @"select top 1 from sys.procedures " +
              "where [type_desc] = '{0}'", procedureName);
        return dbContext.Database.SqlQuery<string>(query).Any();
    }
}
public static bool ImprovedExists(this DbContext dbContext, string procedureName)
{
    object[] functionParameters = new object[]
    {
        new SqlParameter(@"procedurename", procedureName),
    };
    const string query = @"select [name] from sys.procedures where name= @procedurename";
    return dbContext.Database.SqlQuery<string>(query, functionParameters).Any();
}
public static class SqlConnectionExtensions
{        
    public static Task<bool> StoredProcedureExistsAsync(this SqlConnection sqlConnection, string storedProcedureName)
    {
        string query = "SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(@storedProcedureName) AND type in (N'P', N'PC')";

        using (SqlCommand command = new SqlCommand(query, sqlConnection))
        {
            command.Parameters.AddWithValue("@storedProcedureName", storedProcedureName);
            using (SqlDataReader reader = command.ExecuteReader())
            {
                return reader.ReadAsync();
            }
        }
    }
}
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE='PROCEDURE'
AND (ROUTINE_SCHEMA='questionnaire' OR ROUTINE_CATALOG = 'questionnaire')
AND SPECIFIC_NAME='create_question';
string procedureName = "create_question";
using (DbConnection conn = new SqlConnection("Server=localhost;Database=questionnaire;Trusted_Connection=True;")) // Connection is interchangeable
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = $"SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE='PROCEDURE' AND (ROUTINE_SCHEMA='{conn.Database}' OR ROUTINE_CATALOG = '{conn.Database}') AND SPECIFIC_NAME='{procedureName}';";
        return cmd.ExecuteScalar() != null;
    }
}