简体   繁体   中英

how to check if stored procedure exists or not in sql server using c# code

I tried below code for cheking SP is alredy exist or not. if not exist i am creating..

But every time it is showing sp is not created.....But my database already have this sp.

Let me know where i am doing mistake.

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
}

Try:

if exists(select * from sys.objects where type = 'p' and name = '<procedure name>' )

Also you can check that with c#:

string connString = "";
string query = "select * from sysobjects where type='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;
            }
        }
    }
}

For those who use Entity Framework and a DbContext:

create an extension class for 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();
    }
}

As robIII remarked, this code should not be published to the outside world as it makes the database vulnerable for hackers (thank you RobIII!). To prevent this use a parameterized statement. The problem with the above mentioned method is described here

The solution is to put procedureName as a parameter in an SQL statement. SQL will check if the string parameter has the desired format, thus inhibiting malicious calls:

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

我在MSDN上找到了这个

select * from sys.objects where type_desc = 'SQL_STORED_PROCEDURE' AND name = 'Sql_PersonInsert'

Try:

SELECT * 
FROM sys.objects 
WHERE object_id = OBJECT_ID(N'GP_SOP_AdjustTax') AND type in (N'P', N'PC')

My stab at it:

  • Reusable extension method
  • Minimal Sql / Minimal C#
  • Called from .Net as the OP implicitly requested
  • Could be faster because of the object_id function
public static bool StoredProcedureExists(this string source)
{
  using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
  {
    conn.Open();
    using (var cmd = new SqlCommand($"select object_id('{source}')", conn))
      return !cmd.ExecuteScalar().ToString().IsNullOrWhiteSpace();
  }
}

You can check with following tsql query (suitable for SQL Server):

select * from sysobjects where ytype='P' and name='MyStoredProcedureName'

If query returns row then stored procedure named 'MyStoredProcedureName' exists.

And here is how you can use it in code:

        //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;
                    }
                }
            }
        }
string checkSP = String.Format(
  "IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'", 
  "GP_SOP_AdjustTax");

is fine if you change the 'U' to 'P'. With 'U' you query for user-tables, where 'P' gives you stored-procedures.

private static bool StoredProcedureExists(string sp)
{    
      var connString = @"<your string here>";
      var query = string.Format("SELECT COUNT(0) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = '{0}'", sp);
      using (var conn = new SqlConnection(connString))
      {
          conn.Open();
          using (var cmd = new SqlCommand(query, conn))
          {
              return Convert.ToInt32(cmd.ExecuteScalar()) > 0;  
          }
      }
 }
  • Handles procedure names with different schemas
  • Names with and without brackets ([])
  • Uses parameter to avoid SQL injection

Note: Caller owns SQL Connection

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

The following works with MySQL, SQL Server, and Oracle I think:

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

Usage:

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

If you use Microsoft.SqlServer.Management.Smo , try

private static bool CheckIfStoredProcedureExists(Database db, string spName, string schema)
{
   db.StoredProcedures.Refresh();
   return (db.StoredProcedures[spName, schema] != null);
}

Try this;

if object_id('YourStoredProcedureName') is null
    exec ('create procedure dbo.YourSp as select 1')
go
alter procedure dbo.YourStoredProcedure
as

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM