How to redirect a request for DB1 to DB2 - sql

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

Related

Stored Procedure Select data from Server A and Insert data to Server B

I would like to ask about how to write the Stored Procedure Select data from Server A and Insert data to Server B?
1 . Create a linked server using steps at below link
https://www.sqlshack.com/how-to-create-and-configure-a-linked-server-in-sql-server-management-studio/
Create a synonym for the table from the linked server you are going to use if there is only one table otherwise create synonym for that server so you dont have to use the complete name and if the server changes in future you dont have to go and change in every procedure instead you can just change the synonym.
CREATE SYNONYM MySyn
FOR LinkedServerName.DatabaseName.SchemaName;
GO
Use the synonym in your query to fetch the data.
create procedure procedureName
as
begin
insert into destDB.schema.tablename select * from mysyn.sourcetablename
end

How do I update triggers across multiple databases?

I have a query that I can select the databases from the sys.databases with the triggers that I wish to update. From there I can create a cursor. However when I go into the cursor to update my triggers using a dynamic db name #DatabaseExecuteName that is set to MyDatabaseName.dbo I receive the error ''CREATE/ALTER TRIGGER' does not allow specifying the database name as a prefix to the object name.' Because I am in a cursor I am not able to execute a USE MyDatabaseName ... GO, the GO statement is not allowed inside the CURSOR. I have tried SQLCMD MODE :setvar DatabaseName "MyDatabaseName" with USE [$(DatabaseName)]; to try to set the use database. I feel I am very close however my strength is not SQL queries. I could use some assistance on what I am missing.
You can nest EXEC calls so that you can use a USE and then execute a further statement and you don't need to use GO to seperate the batches. This is a complete script to demonstrate the technique:
create database DB1
go
create database DB2
go
use DB2
go
create table T1 (ID int not null)
go
create table T2 (ID int not null)
go
use DB1
go
exec('use DB2; exec(''create trigger T_T on T1 after insert as
insert into T2(ID) select i.ID from inserted i'')');
select DB_NAME()
insert into DB2..T1(ID) values (1),(2);
select * from DB2..T2
Which then shows that this connection is still in the DB1 database, but the trigger was successfully created on the T1 table within the DB2 database.
What you have to watch for is getting your quote-escaping correct.

Executing Dynamic SQL Using A Results Set

I'm using SQL Server and I want to construct a dynamic SQL statement. I have several databases that are exact clones of each other e.g. TestDatabase1 is the same as TestDatabase2 and etc. Since the schemas and tables in all of the cloned databases are exactly the same, I want to execute a SQL statement that updates each table. Here's the pseudo-code:
for each table x in a test database
update x.SomeColumn
I have code to grab the databases:
SELECT name
FROM sys.databases
WHERE name LIKE '%Test%'
but now I don't know what to do with that data. How can I update each table in each database?
You can use sp_MSforeachtable to run Update statements against every table in a database. For example:
-- First set the database you want to use:
USE TempDatabase1
GO
EXEC sp_MSforeachtable 'UPDATE ? SET SomeColumn = 2'
GO
USE TempDatabase2
GO
EXEC sp_MSforeachtable 'UPDATE ? SET SomeColumn = 2'
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

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

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