Creating procedure inside IF section - sql-server

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
.................

Related

Executing T-SQL query from table

I have the following stored procedure:
CREATE PROCEDURE MergeTable #TableName VARCHAR(256)
AS
BEGIN
DECLARE #Test VARCHAR(max)
SET #Test = (SELECT Query
FROM dbo.QueryMergeDWH
WHERE SourceTableName = #TableName)
EXEC #Test
END
GO
EXEC MergeTable #TableName = 'SGPREINVOICE'
The table dbo.QueryMergeDWH holds queries for different tables I want to run using the stored procedure. The variable #Test holds the query (a MERGE statement) for the table 'SGPREINVOICE' in this case.
However, when I run this code I get the following error:
Msg 203, Level 16, State 2, Procedure MergeTable, Line 11 [Batch Start Line 19]
The name 'MERGE dwh.SGPREINVOICE t
USING stg.SGPREINVOICE s
ON t.VOUCHER = s.VOUCHER
WHEN NOT MATCHED
THEN INSERT VALUES (BATCHNAME, COMPANYNR, BUDGETHOUDER, VENDORNR, BANKACCOUNTID, [DESCRIPTION], EXTERNALINVOICENR, TAXVERLEGD, INVOICEDATE, BOOKINGDATE, INVOICEAMOUNTDEB, INVOICEAMOUNTCRED, SGAMOUNTHIGH, SGAMOUNTLOW, SGAMOUNTNOTAX, SGTAXAMOUNTLOW, SGTAXAMOUNTHIGH, SGTAXTTV, G_ACCOUNT, G_AMOUNT, INVOICETYPE, SGAUTOINCASSO, SGIMPORTPROCESSID, SGINVOICEBLOCKED, SGCOMPANYNRORIG, SGVENDORNRORIG, SGBANKACCOUNTIDORIG, SGG_ACCOUNTORIG, SGPOSTBUSNR, SGADDRESS, SGHUISNR, SGHUISNRTOEV, SGPOSTCODE, SGWOONPL, SGBTWNR, SGBEDRIJFSNM, SGINVOICEAMOUNTORIG, V' is not a valid identifier.
It seems like the variable #Test does not contain the entire statement but only part of it. How can I solve this problem?
The actual reason for this error is the difference between EXEC #Test (to execute a stored procedure or function) and EXEC (#Test) (to execute a dynamic statement). Note, that you may use sp_executesql to execute a dynamically generated statement:
CREATE PROCEDURE MergeTable #TableName VARCHAR(256)
AS
BEGIN
DECLARE #Test VARCHAR(max)
SELECT #Test = Query
FROM dbo.QueryMergeDWH
WHERE SourceTableName = #TableName
EXEC (#Test)
-- Or using sp_executesql
-- DECLARE #err int
-- EXEC #err = sp_executesql #Test
-- IF #err <> 0 PRINT 'Error'
END
GO
EXEC MergeTable #TableName = 'SGPREINVOICE'

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;

If NOT EXISTS in SQL not function

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.

Drop and re-create procedure if it exists in T-SQL not working

IF EXISTS ( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'LOCATION') AND type IN (N'P', N'PC'))
DROP PROCEDURE [dbo].[LOCATION]
GO
CREATE PROCEDURE [dbo].[LOCATION]
#IP NVARCHAR(100)
AS
BEGIN
DECLARE #IPNumber BIGINT
SELECT #IPNumber = dbo.ConvertIp2Num(#IP)
SELECT [country_code],[country_name]
FROM [myDatabase].[dbo].[CountryIP]
WHERE #IPNumber BETWEEN ip_from AND ip_to
END
I have the above code to check if stored procedure LOCATION exists in the current database. I expect it to drop and re-create the procedure if it exists.
However, if the procedure exists the code is still executing and as a result i get the following error 'There is already an object named 'LOCATION' in the database.'
Why is that code failing to drop the procedure if it exists?
The same code works properly for a another procedure in the same database.
Try this (preferred method using a view):
IF EXISTS(SELECT 1
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'PRC_NAME'
AND SPECIFIC_SCHEMA = 'schema_name')
BEGIN
DROP PROCEDURE PRC_NAME
END
or this (not recommended using direct access to a system table):
IF EXISTS (SELECT 1
FROM SYS.PROCEDURES
WHERE NAME = 'PRC_NAME'
AND SCHEMA_NAME(SCHEMA_ID) = 'SCHEMA_NAME'
AND [TYPE] IN (N'P',N'PC'))
BEGIN
DROP PROCEDURE PRC_NAME
END
Why the first method is preferred you can find out for example in this question: SQL Server: should I use information_schema tables over sys tables?
This is kind of late, but others that end up here might want to check out the MSDN documentation that say you could use:
DROP PROCEDURE IF EXISTS dbo.uspMyProc;
GO
This is however available from SQL Server 2016 Community Technology Preview 3.3 (CTP 3.3).
You could use:
IF OBJECT_ID('MSL_GET_IP_LOCATION', 'P') IS NOT NULL
DROP PROCEDURE MSL_GET_IP_LOCATION
GO
Further thought on this is you will need to make sure you have unique names across all objects.
SQL Server -
Drop List of Stored Procedures if existed on Customer DB +
Copy List of Stored Procedures from master to another DB (recreate dynamically). P.S.: #TargetDBName=your DB.
I hope it will help someone
--Drop SPs from Customer DB if existed---
DECLARE #TargetDBName NVARCHAR(255)
SET #TargetDBName = DB_NAME()
DECLARE #SQL NVARCHAR(max)
SET #SQL = ''
DECLARE v CURSOR
FOR
SELECT [NAME]
FROM [Master].[sys].[procedures] p WITH(NOLOCK)
INNER JOIN [Master].sys.sql_modules m WITH(NOLOCK) ON p.object_id = m.object_id
WHERE p.[NAME] LIKE 'mySPs_list_%'
AND [type] = 'P'
OPEN v
FETCH NEXT
FROM v
INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = REPLACE(#sql, '''', '''''')
SET #sql = 'USE [' + #TargetDBName + ']; IF OBJECT_ID('''+#sql+''', ''P'') IS NOT NULL DROP PROCEDURE '+ #sql+';'
EXEC SP_EXECUTESQL #sql
FETCH NEXT
FROM v
INTO #sql
END
CLOSE v
DEALLOCATE v;
--COPY SPs from master to Another DB-------------
DECLARE c CURSOR
FOR
SELECT [Definition]
FROM [Master].[sys].[procedures] p
INNER JOIN [Master].sys.sql_modules m ON p.object_id = m.object_id
WHERE p.[NAME] LIKE 'mySPs_list_%'
AND [type] = 'P'
OPEN c
FETCH NEXT
FROM c
INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = REPLACE(#sql, '''', '''''')
SET #sql = 'USE [' + #TargetDBName + ']; EXEC(''' + #sql + ''')'
EXEC SP_EXECUTESQL #sql
FETCH NEXT
FROM c
INTO #sql
END
CLOSE c
DEALLOCATE c;

Resources