I store all of my T-SQL DDL statements in a Visual Studio database project under version control. The scripts are meant to always run without error, so they include a drop/create syntax like so:
use MyDatabase
go
if objectproperty(object_id('dbo.MyProcName'), 'IsProcedure') = 1 begin
drop procedure dbo.MyProcName as
end
go
-----------------------------------------------------------------------
-- $Id: $
-- Notes: blah blah
-----------------------------------------------------------------------
create procedure dbo.MyProcName as
--...
go
Trouble is, we've moved to a replication scenario so I can no longer use my drop/create syntax because you cannot drop objects marked for replication. Now I need to create the proc if it doesn't exist, or alter it if it does. And I can't reverse my IF
开发者_开发百科logic because I can't create a proc within an IF
statement - I can only drop it. Any ideas?
EDIT: Thanks to Adam's answer, here's what I wound up using. Don't know why I didn't consider executing a SQL string... must drink more coffee.
use MyDatabase
go
if objectproperty(object_id('dbo.MyProcName'), 'IsProcedure') is null begin
exec('create proc dbo.MyProcName as')
end
go
-----------------------------------------------------------------------
-- $Id: $
-- Notes: blah blah
-----------------------------------------------------------------------
alter procedure dbo.MyProcName as
--...
go
What you can do is have the first portion of your script create a stub for the procedure if it doesn't exist, then turn the rest of the script into an ALTER
script instead of a CREATE
.
For example:
if objectproperty(object_id('dbo.MyProcName'), 'IsProcedure') <> 1 begin
exec sp_ExecuteSql N'create Procedure dbo.MyProcName as select 1'
end
go
-----------------------------------------------------------------------
-- $Id: $
-- Notes: blah blah
-----------------------------------------------------------------------
alter procedure dbo.MyProcName as
--...
go
Note that you'll have to use sp_ExecuteSql
(or something equivalent) here, since create procedure
must be the first statement in a batch.
Wrap the creation of the stored procedure into an EXEC and you can reverse your if logic:
exec (N'create procedure...
An example like Adam's answer would be something like:
declare @ID int
select @ID = ID from sysobjects where OBJECT_NAME(ID)='Proc1' and USER_NAME(uid) = 'dbo'
if @ID is null
begin
exec('create procedure dbo.Proc1 as')
end
else
begin
if OBJECTPROPERTY(@ID,N'IsProcedure')=0 or OBJECTPROPERTY(@ID,N'IsMSShipped')=1
begin
RAISERROR('An object called dbo.Proc1 exists in the database, but is of the wrong type',16,1) WITH NOWAIT
end
end
go
ALTER procedure [dbo].[Proc1]
/* Body of procedure */
Adding Examples for TABLE FUNCTIONS:
IF objectproperty(object_id('dbo.udf_MyFunction'), 'IsTableFunction') is null
EXEC sp_ExecuteSql N'CREATE FUNCTION dbo.udf_MyFunction () RETURNS @X TABLE (Id int) AS BEGIN RETURN END'
GO
and SCALAR FUNCTIONS:
IF objectproperty(object_id('dbo.udf_MyFunction'), 'IsScalarFunction') is null
EXEC sp_ExecuteSql N'CREATE FUNCTION dbo.udf_MyFunction () RETURNS int AS BEGIN RETURN 0 END'
GO
精彩评论