checking for existence of a stored procedure - sql

Does any body know why the following SQL returns a syntax error (Incorrect syntax near 'IF') in SQL Server 2012?
DROP PROCEDURE IF EXISTS MyStoredProcedure;
I know I can use the following instead:
IF EXISTS(SELECT 1 FROM sys.procedures
WHERE Name = 'MyStoredProcedure')
But I wonder why the first one produces the error.
Thanks!

This works:
IF EXISTS(SELECT 1 FROM sys.procedures
WHERE Name = 'MyStoredProcedure')
print 'yes'
-- drop procedure mystoredprocedure
You must have something else in your query window that's throwing the error, or you're running things in the wrong order.
For what it's worth, this is my "go to" for dropping/building procedures before I CREATE PROCEDURE... all my saved proc scripts have this.
IF OBJECT_ID('dbo.uspSomeProcName') IS NOT NULL
BEGIN
DROP PROCEDURE dbo.uspSomeProcName
IF OBJECT_ID('dbo.uspSomeProcName') IS NOT NULL
PRINT '<<< FAILED DROPPING PROCEDURE dbo.uspSomeProcName>>>'
ELSE
PRINT '<<< DROPPED PROCEDURE dbo.uspSomeProcName>>>'
END

Related

Running a conditional sql script dependent on existence of database

I'm trying to automate a sql script to add a column to existing databases on a given system. The script will be run on a system with one database or a different one. The script should not cause error in any of the cases:
1. One of the two databases exists
2. Both databases exist
3. Neither database exists.
I tried this but I keep getting error when the database 'DatabaseName' does not exist. I want the script to be ignored in that case.
IF DB_ID('DatabaseName') IS NOT NULL
BEGIN
PRINT 'DatabaseName Exists'
IF COL_LENGTH('[DatabaseName].[dbo].[Table]', 'NewColumn') IS NULL
BEGIN
ALTER TABLE [DatabaseName].[dbo].[Table]
ADD [NewColumn] bit NOT NULL DEFAULT 0;
PRINT 'Modified DatabaseName.Table'
END
END
ELSE
BEGIN
PRINT 'DatabaseName Does Not Exist'
-- therefore do nothing
END
This gives me the error:
Msg 2702, Level 16, State 2, Line 6
Database 'DatabaseName' does not exist.
I had also tried different variations of
Use 'DatabaseName'
with the same or similar errors because they are not existent.
To clarify: it is okay if it does not exist. I am just trying to handle the error gracefully so an installation continues
Use dynamic SQL. The problem is occurring during the compilation phase of the code. Dynamic SQL will "hide" the reference to the database from the initial compilation phase.
For instance, in SQL Server, this looks like:
IF COL_LENGTH('[DatabaseName].[dbo].[Table]', 'NewColumn') IS NULL
BEGIN
exec sp_executesql N'
ALTER TABLE [DatabaseName].[dbo].[Table]
ADD [NewColumn] bit NOT NULL DEFAULT 0';
PRINT 'Modified DatabaseName.Table'
END
You can use a try catch block:
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
-- Execute code if error
END CATCH;

SQL Updating column after adding it giving "Invalid column name" error

I have the following SQL in SQL Server 2005 but I get an error stating "Invalid column name 'ExpIsLocalTime' (ln 7) when I run it:
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = N'ExpIsLocalTime' AND Object_ID = Object_ID(N'[dbo].[tbl_SessionsAvailable]'))
BEGIN
ALTER TABLE dbo.tbl_SessionsAvailable ADD
ExpIsLocalTime bit NOT NULL CONSTRAINT DF_tbl_SessionsAvailable_ExpIsLocalTime DEFAULT (0)
UPDATE dbo.tbl_SessionsAvailable
SET ExpIsLocalTime = 1
END
GO
This will be in a script file that may be run more than once so I'm trying to make sure the UPDATE only runs once. Is there something about BEGIN/END that delays the execution of the DDL statement?
Your SQL query to do the UPDATE refers to a column that has not yet been created. At compile time, SQL Server detects that the column does not exist, so it gives you the error "Invalid column name 'ExpIsLocalTime'".
In order to include the UPDATE in this query, you will need to encapsulate it in a dynamic SQL query. In other words, something like this:
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = N'ExpIsLocalTime' AND Object_ID = Object_ID(N'[dbo].[tbl_SessionsAvailable]'))
BEGIN
ALTER TABLE dbo.tbl_SessionsAvailable ADD
ExpIsLocalTime bit NOT NULL CONSTRAINT DF_tbl_SessionsAvailable_ExpIsLocalTime DEFAULT (0)
DECLARE #SQL NVARCHAR(1000)
SELECT #SQL = N'UPDATE dbo.tbl_SessionsAvailable SET ExpIsLocalTime = 1'
EXEC sp_executesql #SQL
END
GO
We have the same issue in our SQL scripts that maintain tables. After a table is created, if we add a column to it later, we have to use dynamic SQL to avoid these compilation errors.
Another possibly simpler solution is using the GO statement after the Alter statement. This would send the DDL to the server. Then run the rest of your SQL. This should work if you are using sqlcmd osql or SSMS.

TSQL Alter procedure if it exists - syntax error

I'm trying to understand what specifically is happening in SQL that means the following syntax is not allowed (and I'm finding it hard to search for):
IF (OBJECT_ID('..sp_cake', 'P') is not null)
ALTER PROC sp_cake
as
select 1
I would expect the ALTER to be valid because T-SQL is wrapping it up in its own BEGIN-END block and nothing bad could happen with the rest of the script block.
This is what T-SQL is doing, wrapping everything up and keeping it cleanly separated:
IF (OBJECT_ID('..sp_cake', 'P') is not null)
BEGIN
ALTER PROC [dbo].[sp_cake]
as
BEGIN
select 1
END
END
And these examples would be the simplest expression of what I think I'm doing (and these are syntactically correct)
IF (OBJECT_ID('..sp_cake', 'P') is not null)
select 1
IF (OBJECT_ID('..sp_cake', 'P') is null)
select 1 -- i.e. this works and 1 is the output
I have read that the CREATE or ALTER must be the first statement in a query block, but I don't understand why.
I know that I can get around this problem by either:
creating a dummy sproc and then altering it outside of an IF block, or;
creating a string of the entire sproc and executing it as a statement;
but I don't see why it is not valid to test for existence and then ALTER.
I'm not sure what you mean by this statement:
I have read that the CREATE or ALTER must be the first statement in a
query block, but I don't understand why.
You are correct that these need to be the first statements in a batch. That is a property of the T-SQL language -- not something whose cause needs to be understood but something that you need to know to use the language properly. Typically, the structure to do what you want in SQL Server is:
IF (OBJECT_ID('..sp_cake', 'P') is not null)
BEGIN
DROP PROCEDURE dbo.sp_code
END;
GO
CREATE PROC [dbo].[sp_cake] as
BEGIN
select 1
END;
I do agree that it would be nice to have a create procedure if not exists or create or alter procedure. Getting that functionality requires lobbying Microsoft.

SQL Server 2012 stored procedure error Msg 102

I use SQL Server Management Studio 2012. When I try to create a stored procedure and I execute it, it returns an error every time. I really can not figure out whats wrong.
For example:
use AdventureWorks2012
CREATE PROCEDURE test () SELECT * FROM [Sales].[SalesPerson]
and the error is :
Msg 102, Level 15, State 1, Procedure test, Line 1
Incorrect syntax near ')'.
even If I just write CREATE PROCEDURE TEST
It will return error ? What am I doing wrong ?
Try this code:
CREATE PROCEDURE test
as
begin
SELECT * FROM [Sales].[SalesPerson]
end
go
You have to remove () if your procedure does not need parameters, and add as, optionally begin-end (it's more usable).
If you want to add parameters to your procedure in future:
CREATE PROCEDURE test
(
#param1 int
)
as
begin
SELECT * FROM [Sales].[SalesPerson]
where id = #param1
end
go
You should have AS keyword when creating procedure
use AdventureWorks2012
GO
CREATE PROCEDURE test
AS
SELECT * FROM [Sales].[SalesPerson]
GO
Additionally you can add BEGIN and END if you have multiple queries on it.

How do I solve these two errors when creating a trigger?

I'm creating a simple trigger that will email me when a table is updated or inserted into:
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'sportsNewsUpd' AND type = 'TR')
DROP TRIGGER sportsNewsUpd
GO
CREATE TRIGGER sportsNewsUpd
ON sportsNews
FOR Insert, UPDATE
AS
EXEC master.webdb.xp_sendmail
#recipients = 'name#email.com',
#subject = 'Sports News has been altered.'
GO
I am getting two errors:
Incorrect syntax near 'GO', 'CREATE TRIGGER' must be the first tatement in query batch., Incorrect syntax near 'GO'. (two 'GO', two errors).
My resources:
http://msdn.microsoft.com/en-us/library/aa258254(v=sql.80).aspx (B. under examples)
http://msdn.microsoft.com/en-us/library/ms189505.aspx
semicolon after DROP TRIGGER sportsNewsUpd?
so...
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'sportsNewsUpd' AND type = 'TR')
DROP TRIGGER sportsNewsUpd;
GO
try:
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'sportsNewsUpd' AND type = 'TR')
begin
DROP TRIGGER sportsNewsUpd
end
GO
CREATE TRIGGER sportsNewsUpd ON sportsNews FOR Insert, UPDATE AS
begin
EXEC master.webdb.xp_sendmail
#recipients = 'name#email.com',
#subject = 'Sports News has been altered.'
end
GO
How do you run the query(ies)?
I doubt very much that you would get these errors running the script from an SSMS query window. Also, you wouldn't get the errors if you were running it using sqlcmd or osql.
What I mean is I'm suspecting you are trying to run the script from the application and so you may have probably been unaware that GO is not a part of T-SQL.
Solution in this case would be to split the script in two and run each part in turn.