Often I wish to do the reverse of what you are asking. For example if the user has customized a procedure, and I don’t want to lose their changes, yet I want to apply a uniform update script for all my clients, I’d like to be able to do something like the following:
if not exists ( select * from sys.objects
where name='myProc' and objectproperty(object_id,'IsProcedure')=1 )
create proc myProc
as begin
-- proc stmts here
end
go
This logic would allow me to create something only if it DOESN’T exist, but to my great frustration, SQL Server prevents this too.
I get around this problem easily enough as follows:
if not exists ( select * from sys.objects
where name='myProc' and objectproperty(object_id,'IsProcedure')=1 )
exec('create proc myProc
as begin
-- proc stmts here
declare @object int = 0
end')
go
By passing the create proc command as a string and placing it in an exec statement we circumvent the stupid rule that prevents one from doing this in the first place.
Problem
When you’re executing a CREATE/ALTER statement to create a procedure/view/function/trigger, you get one of the following errors:
‘CREATE/ALTER PROCEDURE’ must be the first statement in a query batch
‘CREATE VIEW’ must be the first statement in a query batch.
‘CREATE FUNCTION’ must be the first statement in a query batch.
‘CREATE TRIGGER’ must be the first statement in a query batch.
You can’t execute these CREATE/ALTER statements with other statements.
Solution
The solution is to execute the CREATE/ALTER statement separately from other statements. How you do that depends on if you’re using SSMS/sqlcmd/osql or executing from C#.
If you’re executing from SSMS (or sqlcmd/osql)
Add the keyword GO right before CREATE statement. This is the default batch separator in SSMS. It splits the query into multiple batches. In other words, it executes the CREATE statement by itself in its own batch, therefore solving the problem of it needing to be the first statement in a batch. Here’s an example:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'spGetAllPosts') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].spGetAllPosts
GO
CREATE PROCEDURE [dbo].spGetAllPosts
AS
BEGIN
SELECT * FROM Posts
END
Code language: SQL (Structured Query Language) (sql)
If you’re executing from C#
You can’t use the GO keyword in C#. Instead you have to execute the two queries separately. The best way to do that is to execute the first part, then change the CommandText and execute the second part.
using System.Data.SqlClient;
string dropProcQuery =
@"IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'spGetAllPosts') AND type in (N'P', N'PC'))
DROP PROCEDURE[dbo].spGetAllPosts";
string createProcQuery =
@"CREATE PROCEDURE [dbo].spGetAllPosts
AS
BEGIN
SELECT * FROM Posts
END";
using (var con = new SqlConnection(ConnectionString))
{
using (var cmd = new SqlCommand(dropProcQuery, con))
{
//Execute the first statement
con.Open();
cmd.ExecuteNonQuery();
//Then execute the CREATE statement
cmd.CommandText = createProcQuery;
cmd.ExecuteNonQuery();
}
}
Code language: C# (cs)
I am trying to create a stored procedure in the database called DB_Interface like this:
USE [DB_Interface]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROCEDURE [dbo].[ProcToCCreate]
It throws error:
Msg 156, Level 15, State 1, Line 6
Incorrect syntax near the keyword ‘OR’.Msg 111, Level 15, State 1, Line 10
‘CREATE/ALTER PROCEDURE’ must be the first statement in a query batch.`
This is my first stored procedure — not sure if I cannot use Create or Alter like I used it. Any help is greatly appreciated
marc_s
733k175 gold badges1330 silver badges1459 bronze badges
asked Dec 21, 2016 at 5:10
4
CREATE OR ALTER PROCEDURE [dbo].[ProcToCCreate]
AS
RETURN;
is allowed Syntax in (probably) SQL-Server 2016 (only tested on SQL-Server 2016 with SP1)
answered Dec 22, 2016 at 10:02
EbisEbis
3801 silver badge4 bronze badges
CREATE PROCEDURE [dbo].[ProcToCCreate]
OR
CREATE PROC [dbo].[ProcToCCreate]
are only valid syntax in SQL Server.
If you want to ALTER procedure, here is the syntax
ALTER PROCEDURE [dbo].[ProcToCCreate]
answered Dec 21, 2016 at 5:13
![]()
Sateesh PagoluSateesh Pagolu
9,2822 gold badges30 silver badges48 bronze badges
4
CREATE:
USE [DB_Interface]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[ProcToCCreate]
AS
RETURN
ALTER:
USE [DB_Interface]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ProcToCCreate]
AS
RETURN
answered Dec 21, 2016 at 5:19
![]()
Genish ParvadiaGenish Parvadia
1,4373 gold badges17 silver badges30 bronze badges
try this
GO
declare @sqlCmd varchar(max)
select @sqlCmd =
‘
GO
USE [CRM]
ALTER PROC [dbo].[uspReportTrasnlationOpticalCabinetToNormal]
(
@requestsId varchar(max) = null
—@IsSuccess bit output
)
AS
BEGIN
Set XACT_ABORT ON
SET NOCOUNT ON
BEGIN TRY
—SELECT @IsSuccess = 0
SELECT
R.ID RequestID,
TC.ToTelephoneNo,
TC.FromTelephoneNo,
ISNULL(C.FirstNameOrTitle,»») FirstNameOrTitle,
ISNULL(C.LastName,»») LastName,
ISNULL(A.AddressContent,»») InstallAddress,
ISNULL(A.PostalCode,»») InstallPostalCode,
ISNULL(AA.AddressContent,») CorrespondenceAddress,
ISNULL(AA.PostalCode,»») CorrespondencePostalCode
FROM
Request R
INNER JOIN
TranslationOpticalCabinetToNormal TN ON TN.ID = R.ID
INNER JOIN
TranslationOpticalCabinetToNormalConncetions TC ON TN.ID = TC.RequestID
LEFT JOIN
[Address] A ON A.ID = TC.InstallAddressID
LEFT JOIN
[Address] AA ON AA.ID = TC.CorrespondenceAddressID
LEFT JOIN
Customer C ON C.ID = TC.CustomerID
WHERE
TN.[Type] = 2
AND
(@requestsId IS NULL OR LEN(@requestsId) = 0 OR R.ID IN (SELECT * FROM DBO.ufnSplitList(@requestsId)))
—SELECT @IsSuccess = 1
END TRY
BEGIN CATCH
EXEC [dbo].[uspLogError]
—SELECT @IsSuccess = 0;
THROW;
END CATCH
END
‘
EXECUTE (@sqlCmd) AT [mylinkedserver]
GO
Я пытаюсь создать sql script, но получаю сообщение об ошибке:
‘CREATE/ALTER PROCEDURE’ должен быть первым оператором в запросе пакетный??
Здесь мой код:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'myproc') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[myproc]
create PROCEDURE [dbo].[myproc]
AS
BEGIN
select * from mytable
END
GO
Ответ 1
Запустите свой оператор в следующей форме:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'myproc') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[myproc]
GO
create PROCEDURE [dbo].[myproc]
AS
BEGIN
select * from mytable
END
GO
Обратите внимание на разделитель партий GO после DROP PROCEDURE
Ответ 2
Сообщение об ошибке, которое вы получаете, является правильным. Вы можете завершить пакет (и запустить другой) с помощью ключевого слова GO.
Поместите GO прямо перед оператором Create procedure. Вывод GO должен быть на отдельной строке.
Ответ 3
Часто я хочу сделать обратное тому, что вы просите. Например, если пользователь настроил процедуру, и я не хочу терять их изменения, но я хочу применить единообразное обновление script для всех моих клиентов, я хотел бы иметь возможность сделать что-то вроде следующего:
if not exists ( select * from sys.objects
where name='myProc' and objectproperty(object_id,'IsProcedure')=1 )
create proc myProc
as begin
-- proc stmts here
end
go
Эта логика позволила бы мне создать что-то только в том случае, если оно НЕ существует, но, к моему большому разочарованию, SQL Server также предотвращает это.
Я легко обойду эту проблему следующим образом:
if not exists ( select * from sys.objects
where name='myProc' and objectproperty(object_id,'IsProcedure')=1 )
exec('create proc myProc
as begin
-- proc stmts here
declare @object int = 0
end')
go
Пропустив команду create proc в виде строки и поместив ее в инструкцию exec, мы обходим глупое правило, которое не позволяет делать это в первую очередь.
Ответ 4
Моя проблема исчезла после добавления следующих утверждений:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Ответ 5
Возможно, вы захотите попробовать это, чтобы создать хранимую процедуру в другой базе данных, а не создавать ее в текущем контексте.
set @myScript = 'exec '+ QUOTENAME(@DBName) + '..sp_executesql N''create PROCEDURE [dbo].[myproc]
AS
BEGIN
select * from mytable
END'''
execute(@myScript)
