How to DROP a version of a Stored Procedure in SQL Server - sql

We have some legacy stored procedures that use the now deprecated feature of SQL Server that allowed you to create multiple versions of a procedure within a procedure.
For instance we have..
[up_MyProc]
[up_MyProc];2
You can still create these "versions" by appending the version on the end of the name. However without dropping the procedure we'd like to drop the internal versions.
You cant seem to do
DROP PROC [up_MyProc];2
DROP PROC [up_MyProc;2]
Is there a way to drop the internal versions?

Unfortunately, no.
I've just tried sp_rename which failed too.
The new system views do not detect them either
CREATE PROC DBO.FOO;1
AS
SELECT 1
go
CREATE PROC DBO.FOO;2
AS
SELECT 2
go
--Can't find using new system views
SELECT * FROM sys.objects WHERE name LIKE '%foo%'
SELECT * FROM sys.sql_modules WHERE definition LIKE '%dbo.foo%SELECT%'
GO
--Found using legacy "system tables"
SELECT * FROM sysobjects WHERE name LIKE '%foo%'
SELECT * FROM syscomments WHERE text LIKE '%dbo.foo%SELECT%'
GO

Related

Create view must be the first statement in the batch

I'm running a set of script files from a .NET based windows application. One of the files has the following script -
IF EXISTS(SELECT * FROM SYS.VIEWS WHERE NAME = 'TP_LEAVEDATA') EXEC SP_RENAME 'TP_LEAVEDATA', 'TP_LEAVEDATA_BKP_EXPORT_TEST1'
CREATE VIEW TP_LEAVEDATA AS
SELECT USERNAME, Dept, LeaveType, LeaveFrom, LeaveUpto FROM LeaveRequest_DATA
When I execute the script I get an error create view must be the first statement in the batch
I can not use GO keyword here because I'm running the scripts through my application, I can not use execute sp_executesql because there are similar files for creating stored procedures as well (which contain single inverted commas inside the query itself). What are the options that i have now ??
PS: The issue doesn't occur with create table command though.
You can use put GO before it:
IF EXISTS(SELECT * FROM SYS.VIEWS WHERE NAME = 'TP_LEAVEDATA') BEGIN
EXEC SP_RENAME 'TP_LEAVEDATA', 'TP_LEAVEDATA_BKP_EXPORT_TEST1' ;
END;
GO
CREATE VIEW TP_LEAVEDATA AS
SELECT USERNAME, Dept, LeaveType, LeaveFrom, LeaveUpto
FROM LeaveRequest_DATA;
Another option is to use dynamic SQL for the view creation.

There is already an object named '#DIR_Cat' in the database

In my Stored procedure, I have added a command to create a hash temp table #DIR_CAT. But every time I execute the procedure I get this error:
"There is already an object named '#DIR_Cat' in the database."
Even when I have already created an Exists clause at the start of SP to check and drop the table if it is present. Any help is much appreciated.
The code goes like this.
if exists (select * from dbo.sysobjects where id = object_id(N'#DIR_Cat') )
drop table #DIR_Cat
/* some lines of code*/
CREATE TABLE #DIR_Cat (XMLDta xml)
/* some lines of code*/
INSERT #DIR_Cat exec (#stmt)
/* some lines of code*/
drop table #DIR_Cat
Main issue is you're not fully qualifying your objects. Your temp table lives in tempdb, whereas the system views use whatever database you're currently connected to by default. So essentially you're looking for the temp table, but you're looking in whatever database your currently connected to (which I'm guessing is not tempdb).
I'm assuming you're using SQL Server here, although you did also mention mysql in the tags. If that's what you're using, this code may not apply.
Here's the snippet I use for temp table drop/create
if object_id('tempdb.dbo.#<TableName, sysname, >') is not null drop table #<TableName, sysname, >
create table #<TableName, sysname, >
(
)
Side note, don't use dbo.sysobjects. That's a really old compatibility view. If you want to use objects, use sys.objects instead.
temp table does not exists in local DB sys.objects, it is in tempdb
you need to query tempb.sys.objects
the name of the temp table does not appear exactly as it is in the tempdb.sys.objects.
You can't query it just like
select *
from tempdb.sys.objects
where name = '#DIR_Cat' -- This does not works
you need to use object_id()
select *
from tempdb.sys.objects
where object_id = object_id('tempdb..#DIR_Cat')

How to redirect a request for DB1 to DB2

Suppose I have two databases named DB1 and DB2. In DB1, there is a table named Student, In DB2, there is a stored procedure named SP1. In SP1, I am selecting data of Student Table using below query :
Select *from DB1.dbo.Student.
I have more than 300 stored procedures having above said cross database communication. Now, I want to change my database from DB1 to DB3 that is identical to DB1 from data and schema perspective.
For this, I also have to modify all 300 stored procedures that are having fully-qualified database name. Now, the query will likely to be as follows :
Select *from DB3.dbo.Student
I don't want to change all stored procedure to point DB3 now, also don't want to change my queries written in stored procedure into dynamic SQL (I know this can be done by creating dynamic SQL).
Is it possible if We run DB1.dbo.Student, It will redirect to DB3.dbo.Student. Any intermediate layer or any SQL setting.
It'll be very big help for me. Thanks In Advance !!
If the purpose of your database renaming is to migrate a database, then why not rename the databases themselves?
e.g. say rename DB1 to DB1_old and then rename DB3 to DB1
I would simply script out all stored procedures using SQL Server script generator tool. Then do a find replace on the script and find text ‘DB1.dbo.’ and replace with ‘DB3.dbo.’
In the future you might want to consider using synonyms to reference external tables then you would only have to update the synonyms instead of all of your procedures. Please see following MSDN article on synonyms:
https://msdn.microsoft.com/en-us/library/ms187552.aspx
Example use of synonym:
USE [DB1]
GO
-- Create a synonym for table A located in DB2.
CREATE SYNONYM [dbo].[External_TableA] FOR [DB2].[dbo].[TableA]
GO
-- Synonym is pointing to TableA in DB2 , select statement will return data from DB2 tabla A.
SELECT *
FROM [External_TableA]
GO
-- Point the Synonym to same table but on DB3
DROP SYNONYM [dbo].[External_TableA]
CREATE SYNONYM [dbo].[External_TableA] FOR [DB3].[dbo].[TableA]
GO
-- No update was needed on views or stored procedure.
-- Synonym is pointing to TableA in DB3 , select statement will return data from DB3 tabla A.
SELECT *
FROM [External_TableA]
The follow query will generate the required DROP and CREATE script to remap your synonyms from the old database to the new database.
DECLARE #oldDB NVARCHAR(100) = 'DB2';
DECLARE #newDB NVARCHAR(100) = 'DB3';
SELECT 'DROP SYNONYM [dbo].[' + name + ']' AS [Drop Script]
,'CREATE SYNONYM [dbo].[' + name + '] FOR ' + REPLACE(base_object_name, #oldDB, #newDB) AS CreateScript
FROM sys.synonyms
ORDER BY name
its better to use USE Keyword
use [database name you want to access]
Queries and stored procedure you want to use
GO
eg
use [db1]
select *from yourTableName
exec yourStoredProcedure parm1,parm2,....
Go

Using synonyms in stored procedures

I have a synonym for a table in another DB defined
using
create synonym TableA for otherDb.dbo.TableA
I have a locally defined stored procedure
CREATE PROCEDURE dbo.spGetTableA
AS
BEGIN
SELECT * FROM TableA
END
Now when I call the SP
EXEC spGetTableA
I get the following error
Invalid object name 'TableA'
While calling the SQL directly SELECT * FROM TableA
works perfectly.
Any idea what I'm missing for this to work?
You are probably calling the stored procedure from a user whose default schema is not dbo. Therefore you should always reference the schema both when you create the synonym and when you reference the table in a query.
DROP SYNONYM TableA;
GO
CREATE SYNONYM dbo.TableA FOR OtherDB.dbo.TableA;
GO
ALTER PROCEDURE dbo.spGetTableA
AS
BEGIN
SELECT * FROM dbo.TableA;
END
GO
EXEC dbo.spGetTableA;
I wish I could bold all of those dbo. references within the code. They are important and should ALWAYS be there.
Please read:
Bad habits to kick : avoiding the schema prefix

What's the scoping rule for temporary tables within exec within stored procedures?

Compare the following stored procedures:
CREATE PROCEDURE testProc1
AS
SELECT * INTO #temp FROM information_schema.tables
SELECT * FROM #temp
GO
CREATE PROCEDURE testProc2
AS
EXEC('SELECT * INTO #temp FROM information_schema.tables')
SELECT * FROM #temp
GO
Now, if I run testProc1, it works, and #temp seems to only exist for the duration of that call. However, testProc2 doesn't seem to work at all, since I get an Invalid object name '#temp' error message instead.
Why the distinction, and how can I use a temp table to SELECT * INTO if the source table name is a parameter to the stored procedure and can have arbitrary structure?
Note that I'm using Microsoft SQL Server 2005.
From BOL:
Local temporary tables are visible
only in the current session... ...
Temporary tables are automatically
dropped when they go out of scope,
unless explicitly dropped using DROP
TABLE
The distinction between your first and second procedures is that in the first, the table is defined in the same scope that it is selected from; in the second, the EXEC() creates the table in its own scope, so the select fails in this case...
However, note that the following works just fine:
CREATE PROCEDURE [dbo].[testProc3]
AS
SELECT * INTO #temp FROM information_schema.tables
EXEC('SELECT * FROM #temp')
GO
And it works because the scope of EXEC is a child of the scope of the stored procedure. When the table is created in the parent scope, it also exists for any of the children.
To give you a good solution, we'd need to know more about the problem that you're trying to solve... but, if you simply need to select from the created table, performing the select in the child scope works just fine:
CREATE PROCEDURE [dbo].[testProc4]
AS
EXEC('SELECT * INTO #temp FROM information_schema.tables; SELECT * FROM #temp')
GO
You could try using a global temp table (named ##temp not #temp). However be aware that other connections can see this table as well.