If NOT EXISTS in SQL not function - sql-server

I put this in the SQL Query editor of SQL Server 2008 and doesn't work:
If not EXISTS (Select * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA= 'dbo' AND TABLE_NAME='PK01')
CREATE TABLE [dbo].['PK01'] (Articulo varchar(MAX),Referencia varchar(MAX),Lote varchar(MAX),Cantidad Int,Ubicacion varchar(MAX));
INSERT INTO [UBICACIONES].[dbo].['PK01'] (Articulo,Referencia,Lote,Cantidad,Ubicacion)VALUES ('998','kk','ll',0,'pp')
else
UPDATE [UBICACIONES].[dbo].['PK01'] Set Cantidad = (Cantidad + 23) WHERE Articulo LIKE '998'
Error I am getting:
Msg 156, Level 15, State 1, Line 4 Incorrect syntax near the keyword
'else'.

Your if statement only acts on the first statement after the IF unless you put a BEGIN/END around the statements. This is the reason I like to have BEGIN/ENDs around even one statement IFs.
If not EXISTS (Select * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA= 'dbo' AND TABLE_NAME='PK01')
BEGIN
CREATE TABLE [dbo].['PK01'] (Articulo varchar(MAX),Referencia varchar(MAX),Lote varchar(MAX),Cantidad Int,Ubicacion varchar(MAX));
INSERT INTO [UBICACIONES].[dbo].['PK01'] (Articulo,Referencia,Lote,Cantidad,Ubicacion)VALUES ('998','kk','ll',0,'pp')
END
ELSE
BEGIN
UPDATE [UBICACIONES].[dbo].['PK01'] Set Cantidad = (Cantidad + 23) WHERE Articulo LIKE '998'
END

This is highly not desirable. You should really create tables before you use them. But, you can do this using dynamic SQL:
DECLARE #sql NVARCHAR(MAX);
If not EXISTS (Select * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'PK01')
BEGIN
SET #sql = 'CREATE TABLE [dbo].[''PK01''] (Articulo varchar(MAX),Referencia varchar(MAX),Lote varchar(MAX),Cantidad Int,Ubicacion varchar(MAX))';
EXEC sp_executesql #sql;
SET #sql = '
INSERT INTO [UBICACIONES].[dbo].[''PK01''] (Articulo,Referencia,Lote,Cantidad,Ubicacion)VALUES (''998'',''kk'',''ll'',0,''pp'')';
EXEC sp_executesql #sql;
END;
else
BEGIN
SET #sql = '
UPDATE [UBICACIONES].[dbo].[''PK01''] Set Cantidad = (Cantidad + 23) WHERE Articulo LIKE ''998'' ' ;
EXEC sp_executesql #sql;
END;
Having done all that, I'll repeat. This seems like a really bad application design.

Related

T-SQL variable not used in sp_execsql

I am running a cursor that executes dynamic SQL using a variable.
SET #Wk = CAST(#Cntr AS nvarchar(5))
DECLARE #params nvarchar(30) = N'#Wk nvarchar(5)'
-- .. start cursor
EXEC sp_executesql N'ALTER TABLE #Temp DROP COLUMN [WK #WK Sold]', #params, #Wk
I get the error
Msg 4924, Level 16, State 1, Line 4
ALTER TABLE DROP COLUMN failed because column 'WK #WK Sold' does not exist in table #Temp
I know that #param and #Wk work because I ran
EXEC sp_executesql N'select #Wk', #params, #Wk
and it worked. I know I can just run
EXEC ('ALTER TABLE #Temp DROP COLUMN [WK ' + #Wk + ' Sold]')
but I'd like to use sp_executesql.
Is it even possible the way I have tried?
Thank you
The problem has nothing to do with the variable here. The problem is that you think that a variable/parameter when used in the context of an object results in that variable being injected into the statement. That doesn't happen. SELECT 1 AS [#a] return return a column aliased as literally #a not a column where the alias is the value of a variable called #a.
What you need to do here is safely inject the value into the dynamic statement and ideally validate the name too:
DECLARE #Cntr SomeDataType; --I don't know what the datatype should be.
DECLARE #wk nvarchar(5),
#Column sysname;
SET #wk = #Cntr; --No need for the cast here
SET #Column = (SELECT c.name
FROM tempdb.sys.tables t
JOIN tempdb.sys.columns c ON t.object_id = c.object_id
WHERE t.[name] LIKE N'#temp%'
AND c.name = N'WK
' + #wk + N' Sold');--Does your column name really have a carriage return and line break in it?
DECLARE #SQL nvarchar(MAX) = N'ALTER TABLE #Temp DROP COLUMN ' + QUOTENAME(#Column) + N';';
EXEC sys.sp_executesql #SQL;

SQL script running with error while using sys.obejcts to pre-check

I want to write a script, its function is to create a stored procedure and before create it the script should have to check if it exists in DB, so I write the procedure like below, If I comment out first 2 lines the scripts will create procedure successfully if the stored procedure not exist, but I add the first two lines, the SSMS will throw error:
IF NOT EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[User_Own_Restore_From_Job]') AND type in (N'P'))
CREATE PROCEDURE [dbo].[User_Own_Restore_From_Job]
#dbname varchar(500),
#backuppath varchar (500)
AS
BEGIN
SET NOCOUNT ON
DECLARE #XPConfig int = 1
--To keep the existing value
SELECT #XPConfig = cast(value AS INT) FROM sys.configurations WHERE name LIKE 'xp_cmdshell';
--Enabling xp_cmdshell for getting registry and creating directory structure
BEGIN TRY
EXEC sp_configure 'show advanced options', 1
RECONFIGURE with override
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE with override
END TRY
BEGIN CATCH
--empty
END CATCH
DECLARE #datapath nvarchar(500);
DECLARE #logpath nvarchar(500);
--read data and log path details from registry
EXECUTE master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\Setup', N'SQLDataRoot', #datapath OUTPUT
EXECUTE master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultLog', #logpath OUTPUT
SET #datapath=#datapath+'\Data';
--creating a database folder if not already exists on log and data drives
DECLARE #datapath2 varchar(500)=''
DECLARE #logpath2 varchar(500)=''
SET #DataPath2 = #datapath+ N'\'+#dbname
SET #LogPath2 = #logpath+ N'\'+#dbname
--reading all folders from DATA directory
DECLARE #DirTree TABLE (subdirectory nvarchar(255), depth INT)
INSERT INTO #DirTree(subdirectory, depth)
EXEC master.sys.xp_dirtree #DataPath
--creating a folder on DATA drive with database name if not already exists
IF NOT EXISTS (SELECT 1 FROM #DirTree WHERE subdirectory = #DBName)
EXEC master.dbo.xp_create_subdir #DataPath2
DELETE FROM #DirTree
--reading all folders from LOG directory
INSERT INTO #DirTree(subdirectory, depth)
EXEC master.sys.xp_dirtree #LogPath
--creating a folder on LOG drive with database name if not already exists
IF NOT EXISTS (SELECT 1 FROM #DirTree WHERE subdirectory = #DBName)
EXEC master.dbo.xp_create_subdir #LogPath2
DECLARE #PhysicalName nvarchar(260)=''
DECLARE #LogicalName nvarchar(128)=''
DECLARE #Type char(1)=''
DECLARE #text nvarchar(2000)=''
DECLARE #sql nvarchar(max)=''
DECLARE #restoredb TABLE ( LogicalName nvarchar(128), PhysicalName nvarchar(260),Type char(1)
,FileGroupName nvarchar(128),Size numeric(20,0),MaxSize numeric(20,0),FileID bigint,CreateLSN numeric(25,0),DropLSN numeric(25,0)
,UniqueID uniqueidentifier,ReadOnlyLSN numeric(25,0),ReadWriteLSN numeric(25,0),BackupSizeInBytes bigint,SourceBlockSize int
,FileGroupID int,LogGroupGUID uniqueidentifier,DifferentialBaseLSN numeric(25,0),DifferentialBaseGUID uniqueidentifier
,IsReadOnly bit,IsPresent bit,TDEThumbprint varbinary(32),SnapshotUrl nvarchar(128))
--reading header section of backup file
INSERT #restoredb EXECUTE(N'RESTORE FILELISTONLY FROM DISK = '''+#backuppath +'''')
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
BEGIN TRY
--***taking backup of all permissions**********************************
CREATE TABLE #Permissions (id int identity(1,1), qry nvarchar(4000),Stat bit default 0)
SET #sql='USE ['+#dbname+'];
-- Create Users If not exists
INSERT INTO #Permissions (qry)
select
txt=case when isnull(l.name,'''')=''''
then ''IF NOT EXISTS (SELECT 1 FROM sys.database_principals where name = '''''' + p.name + '''''') BEGIN CREATE USER ['' + p.name +''] FOR LOGIN ['' + p.name +''] END''
else ''IF NOT EXISTS (SELECT 1 FROM sys.database_principals where name = '''''' + p.name + '''''') BEGIN CREATE USER ['' + p.name +''] FOR LOGIN ['' + l.name +''] END''
end
from sys.database_principals p
left join master..syslogins l on l.sid = p.sid
where p.type NOT IN (''R'') AND p.name NOT IN (''dbo'',''guest'',''INFORMATION_SCHEMA'',''sys'')
UNION ALL
--Create Role If not exists
select
txt=case when isnull(l.name,'''')=''''
then ''IF NOT EXISTS (SELECT 1 FROM sys.database_principals where name = '''''' + p.name + '''''') BEGIN CREATE Role ['' + p.name +''] END''
else ''''
end
from sys.database_principals p
left join master..syslogins l on l.sid = p.sid
where p.type =''R'' and p.name NOT IN (''dbo'',''guest'',''INFORMATION_SCHEMA'',''sys'',
''db_owner'',''db_accessadmin'',''db_securityadmin'',''db_ddladmin'',''db_backupoperator'',''db_datareader'',''db_datawriter'',''db_denydatareader'',''db_denydatawriter'',''public'')
UNION ALL
--User Permissions
select
txt=case when isnull(p.type ,'''')<>''G''
then ''ALTER USER ['' + p.name +''] WITH DEFAULT_SCHEMA = ''+ isnull(p.default_schema_name, ''[NULL]'') +'';''
else ''''
end
+ '' EXEC sp_addrolemember '''''' + q.name + '''''', '''''' + p.name + '''''';''
from sys.database_principals p
join (select * from sys.database_principals a
join sys.database_role_members r on a.principal_id=r.role_principal_id) q
on q.member_principal_id = p.principal_id
where (p.type NOT IN (''R'')) AND p.name NOT IN (''dbo'',''guest'',''INFORMATION_SCHEMA'',''sys'')
UNION ALL
--Orphaned users
select
txt=case when isnull(l.name,'''')=''''
then ''Exec sp_change_users_login ''''update_one'''', '''''' + p.name + '''''', '''''' + p.name + '''''' ''
else ''Exec sp_change_users_login ''''update_one'''', '''''' + p.name + '''''', '''''' + l.name + '''''' ''
end
from sys.database_principals p
left join master..syslogins l on l.sid = p.sid
where p.type=''S'' AND p.name NOT IN (''dbo'',''guest'',''INFORMATION_SCHEMA'',''sys'')
'
--get all permissions in text format
EXECUTE sp_executesql #sql
--**Permissions end******************************************************************--
--**preparing a restore statement****************************************************--
SET #SQL='USE [master];ALTER DATABASE ['+#dbname+N'] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE ['+#dbname+N'] SET SINGLE_USER;
ALTER DATABASE ['+#dbname+N'] set offline with NO_WAIT;'
--set database to single user mode
EXECUTE sp_executesql #sql
SET #SQL='RESTORE DATABASE ['+#dbname+N'] FROM DISK = '''+#backuppath+''' WITH FILE = 1'
--preparing move statement for all files
DECLARE c1 CURSOR FOR SELECT PhysicalName,LogicalName,Type FROM #restoredb
OPEN c1;
FETCH NEXT FROM c1 INTO #PhysicalName,#LogicalName,#Type -- fetch first value
WHILE ##fetch_status = 0
BEGIN
SET #text = RIGHT(#PhysicalName,CHARINDEX( '\', REVERSE(#PhysicalName)));
SET #SQL=#SQL+', MOVE '''+#LogicalName+N''''
IF (#Type = 'L')
SET #SQL=#SQL+' TO '''+#logpath+N'\'+#dbname+#text+N''''
ELSE
SET #SQL=#SQL+' TO '''+#datapath+N'\'+#dbname+#text+N''''
FETCH NEXT FROM c1 INTO #PhysicalName,#LogicalName,#Type -- fetch next value
END; --WHILE ##fetch_status = 0
CLOSE c1
DEALLOCATE c1;
-- replace ersetzt die alte db
SET #SQL=#SQL+', NOUNLOAD , replace , STATS = 10 ;'
--perform restore database operation
EXECUTE sp_executesql #sql
--setting database to online mode
SET #SQL='USE [master];
ALTER DATABASE ['+#dbname+N'] set ONLINE with NO_WAIT;
ALTER DATABASE ['+#dbname+N'] SET MULTI_USER; '
EXECUTE sp_executesql #sql
-- changes database owner to sa
SET #SQL='USE [' + #dbname + N'];
EXEC sp_changedbowner ''sa'' '
EXECUTE sp_executesql #sql
--**Database a restore is completed**********************************************--
--**restore permissions on database****************************************************--
DECLARE #ptxt nvarchar(4000)='',#Id int=0
WHILE 0=0
BEGIN
SELECT #ptxt='',#Id=0
SELECT TOP 1 #Id=Id, #ptxt=qry FROM #Permissions WHERE Stat=0 ORDER BY Id
IF Isnull(#Id,0)<=0 BREAK;
SET #ptxt= N'USE [' + #dbname + N'];' + #ptxt
--skip if any invalid login/user exists
BEGIN TRY
--print #ptxt
EXECUTE (#ptxt)
END TRY
BEGIN CATCH
--No action is needed
END CATCH
UPDATE #Permissions SET Stat=1 WHERE Id=#Id
END
END TRY
BEGIN CATCH
--setting database to online mode
SET #SQL='USE [master];
ALTER DATABASE ['+#dbname+N'] set ONLINE with NO_WAIT;
ALTER DATABASE ['+#dbname+N'] SET MULTI_USER; '
EXECUTE sp_executesql #sql
SELECT #ErrorMessage = ERROR_MESSAGE(), #ErrorSeverity = ERROR_SEVERITY(), #ErrorState = ERROR_STATE();
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
END CATCH
BEGIN TRY
EXEC sp_configure 'show advanced options', 1
RECONFIGURE with override
--Retain original setting
EXEC sp_configure 'xp_cmdshell', #XPConfig
RECONFIGURE with override
END TRY
BEGIN CATCH
SELECT #ErrorMessage = ERROR_MESSAGE(), #ErrorSeverity = ERROR_SEVERITY(), #ErrorState = ERROR_STATE();
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
END CATCH
END
The error message like below:
Msg 156, Level 15, State 1, Line 4
Incorrect syntax near the keyword 'PROCEDURE'.
Msg 137, Level 15, State 2, Line 69
Must declare the scalar variable "#dbname".
Msg 137, Level 15, State 2, Line 70
Must declare the scalar variable "#dbname".
Msg 137, Level 15, State 2, Line 79
Must declare the scalar variable "#DBName".
Msg 137, Level 15, State 2, Line 90
Must declare the scalar variable "#DBName".
Msg 137, Level 15, State 2, Line 105
Must declare the scalar variable "#backuppath".
Msg 137, Level 15, State 2, Line 116
Must declare the scalar variable "#dbname".
Msg 137, Level 15, State 2, Line 177
Must declare the scalar variable "#dbname".
Msg 137, Level 15, State 2, Line 184
Must declare the scalar variable "#dbname".
Msg 137, Level 15, State 2, Line 198
Must declare the scalar variable "#dbname".
......
can anyone explain this for me how to fix this issue if I want to have a pre-check?
CREATE PROCEDURE has to be the only statement in a batch. To conditionally execute it, you can use dynamic SQL.
...
IF ...
BEGIN
EXECUTE(N'CREATE PROCEDURE ...');
END;
...
If you only need the conditional execution to prevent errors of the procedure already existing and your version of SQL Server is high enough, you can alternatively use the CREATE OR ALTER PROCEDURE ... statement. It's available since 2016, I believe. That way the procedure simply gets overwritten, if it already exists, without the statement throwing any errors because of the procedure already existing.
Basically the constraint is 'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
Depends on what you want, there are several option, each has different effect.
CREATE OR ALTER PROCEDURE
create or alter procedure [dbo].[User_Own_Restore_From_Job]
as
begin
...
end;
GO
the effect is the procedure is altered and the modify_date in sys.procedures will be updated every time it executes
DROP PROCEDURE + CREATE PROCEDURE
If you are using a earlier version of SQL Server without the CREATE OR ALTER option, you can check for existence of the store procedure, drop it and create it.
if object_id('dbo.User_Own_Restore_From_Job') is not null
drop procedure dbo.User_Own_Restore_From_Job
GO
create procedure [dbo].[User_Own_Restore_From_Job]
as
begin
...
end;
GO
the effect is the procedure is drop and create everytime it executes. And also the create_date and modify_date will be change also.
Don't execute if exists
this make use of set noexec settings. If the procedure exists set noexec to off (The subsequent commands will not be executed). And set it back to on at the end.
IF object_id('dbo.User_Own_Restore_From_Job') is not null
set noexec on;
GO
create procedure [dbo].[User_Own_Restore_From_Job]
as
begin
...
end;
GO
set noexec off;

How to debug the procedure error `Must declare the table variable "#table1"`

CREATE PROC AllRowsAndagain
#table1 NVARCHAR(128)
AS
BEGIN
select count(*) FROM #table1
END;
I am getting this error -
Msg 1087, Level 16, State 1, Procedure AllRowsAndagain11, Line 9 [Batch Start Line 0]
Must declare the table variable "#table1".
I want to pass the tablename as a parameter here
You can't use a variable to replace the name of a table. You would need to use dynamic code for that. Fortunately, there's a more efficient way to retrieve the row count from any table.
CREATE PROC AllRowsAndagain
(
#table1 NVARCHAR(128)
)
AS
BEGIN
SELECT SUM(row_count) AS row_count
FROM sys.dm_db_partition_stats
WHERE OBJECT_NAME( object_id) = #table1
AND index_id IN (0,1);
END;
Like many have hinted in the comments you will need to use dynamic SQL. Dynamic SQL however can be unsafe and you should try and avoid using it.
To answer your question you would need to use something like this:
CREATE PROCEDURE AllRowsAndagain
#table1 NVARCHAR(128)
AS
BEGIN
DECLARE #SafeTableName AS NVARCHAR(128)
SELECT #SafeTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #table1
DECLARE #sql AS NVARCHAR(MAX) = 'select count(*) from ' + #SafeTableName + ';'
EXEC(#SQL)
END
Checking the table against INFORMATION_SCHEMA.TABLES makes your dynamic sql a lot safer. As it will only execute the dynamic statement if a table has been passed as the variable and not some malicious statement.
Your problem is that you are trying to count the number of rows in a string variable.
Seems a bit OTT but here you are.......
CREATE PROC AllRowsAndagain
#table1 NVARCHAR(128)
AS
BEGIN
--DECLARE A VARIABLE TO HOLD THE STATEMENT
DECLARE #Statement NVARCHAR(1024);
--BUILD THGE STATMENT USING THE TABLE NAME YOU PASS IN
SET #Statement = CONCAT('SELECT COUNT(*) FROM ', #table1, ';');
--ONLY RUN FIRST COMMAND
SET #Statement = SUBSTRING(#Statement, 1, CHARINDEX(';', #Statement));
--RUN THE SQL
exec sp_executesql #Statement;
END;

How to insert Dynamic SQL Result INTO Temporary Table

I implement some code:
BEGIN
DECLARE
#SQL AS NVARCHAR(MAX),
#TempTable AS NVARCHAR(MAX)
SET #SQL = 'SELECT * from Employee where Instance_ID = 1';
BEGIN
CREATE TABLE ##tempResults (SQL NVARCHAR(4000))
INSERT INTO ##tempResults EXEC #SQL;
SET #TempTable= 'select * from #tempResults ORDER BY CASE WHEN ' + #index+ ' =1 THEN [First Name] END DESC '+ ',' + ' CASE WHEN ' + #index + '=2 THEN [Last name] END DESC'
END
EXEC sp_executesql #TempTable;
END
I want to insert the dynamic results into temp table but I can't execute statement and get error. Please advice me for how should I need to do ?
As the error shown:
"Msg 203 is not a valid identifier."
You should use EXEC(#SQL) See here
It is advisable to switch to exec sp_executesql #SQL, it gives you parameterization and helps agains sql injection. Especially since you already use this later on in your query (it's never a good idea to use different methods to accomplish the same thing). See here

Creating procedure inside IF section

I need some help with simple SQL code:
DECLARE #procExists int
SET #procExists = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'dbo' AND ROUTINE_NAME = 'Table_Exists' AND ROUTINE_TYPE = 'PROCEDURE')
IF NOT #procExists > 0
BEGIN
-- test query
-- SELECT 'Something' = #procExists;
-- error throwing code
-- CREATE PROCEDURE Table_Exists
-- #schemaName varchar(50),
-- #tableName varchar(50)
-- AS
-- RETURN (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = #schemaName AND TABLE_NAME = #tableName)
END
The simple code above:
- declares an int variable
- checks if procedure dbo.Table_Exists exists
- IF NOT exists it creates it
My problem is this error information:
Msg 156, Level 15, State 1, Line 9
Incorrect syntax near the keyword 'PROCEDURE'.
Msg 137, Level 15, State 2, Line 13
Must declare the scalar variable "#schemaName".
I don't know why, but..
- when i execute 'CREATE PROCEDURE' body alone it works
- when i execute whole IF section excluding 'CREATE PROCEDURE' body, simple query works
- when i execute whole IF section including 'CREATE PROCEDURE' body, error is thrown
What am i missing?
CREATE PROCEDURE has to be in it's own batch
So, dynamic SQL is one way:
IF OBJECT_ID('Table_Exists') IS NULL
BEGIN
EXEC ('CREATE PROCEDURE Table_Exists
#schemaName varchar(50),
#tableName varchar(50)
AS
RETURN (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = #schemaName AND TABLE_NAME = #tableName)
')
END
or DROP first
IF OBJECT_ID('Table_Exists') IS NOT NULL
DROP PROC Table_Exists
GO
CREATE PROCEDURE Table_Exists
#schemaName varchar(50),
#tableName varchar(50)
AS
RETURN (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = #schemaName AND TABLE_NAME = #tableName)
GO
Note the use of OBJECT_ID to see if the proc exists.
You can do this using SET NOEXEC ON. This instructs SQL Server to ignore all SQL code until SET NOEXEC OFF is reached.
IF EXISTS (SELECT *
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = 'PROCEDURE'
AND ROUTINE_SCHEMA = 'dbo'
AND ROUTINE_NAME = 'HelloWorld')
BEGIN
SET NOEXEC ON
END
GO
CREATE PROCEDURE dbo.HelloWorld
AS
PRINT 'Hello world'
GO
SET NOEXEC OFF
GO
From MSDN:
The CREATE PROCEDURE statement cannot be combined with other Transact-SQL statements in a single batch.
Therefore, what you are trying to do is not possible, unless you are fine with implementing it via a dynamic query.
if OBJECT_ID('PROC1') IS NULL
EXEC('CREATE PROCEDURE DBO.PROC1 AS SELECT 1')
GO
ALTER PROCEDURE DBO.PROC1(#PARAM1 INT, #PARAM2 INT)
AS
.................

Resources