Entire DB find replace in all procedures - sql-server

I have inherited a db that contains approx 150 stored procs that have references to db objects on that same server. It worked fine, until the db was moved to another server, now the procedures cannot find those objects.
for example: what is commonplace is simply [database].[dbo].[object], when what should have occurred is [server].[database].[dbo].[object], for these references not be break.
I am presently using
select [definition]
into #test
from sys.sql_modules
where definition like '%(db name)%'
To locate the procs with references to the db, and possibly doing a REPLACE on each db match.
But is there simpler way?

You may consider use SYNONYM
USE [database];
GO
CREATE SYNONYM [object] FOR [server].[database].[dbo].[object];
GO

Related

Way to get the CREATE statement of global temporary table?

I have stored procedures I need to rewrite that used global temporary tables but now must use local temporary tables so that there is no cross over between users/the prod and dev db which are on the same SQL Server instances or any other new databases this database will be share the instance with.
I have to convert a lot of code that is like this
EXEC sp_executesql
N'SELECT manyDynamicallyCreatedColumns INTO ##someTempTable
I now for this to work for local tables I must instead create the table first and then INSERT INTO like
CREATE TABLE #tempTable (manyColumns);
EXEC sp_executesql
N'INSERT INTO #tempTable SELECT manyColumns FROM somewhere'
The issue I face is that this stored procedure has 8 different scenarios that lead to the global temp table. The select statement of the SQL is dynamically generated via a number of other queries. I think what would be the easiest way for me to figure out what my CREATE TABLE #tempTable should look like is if I could print/select what global temporary table looks like after it is made, for each of these 8 scenarios. Then I would just need a If/Else If statement that creates the local table appropriately before proceeding. But I don't know how or if this is possible.
For real tables I can right click -> Script to...-> Create. I don't know if there is an analogous way to do this via scripting that works for global temporary tables. Is there?

SQL Server Stored Procedure, View and Table Unique Identifier

Where does SQL Server save its unique identifier for stored procedures, views and tables? When I rename a stored procedure, how does SQL Server know what stored procedure to rename?
I'm hoping it's something like a row number that I can select in a query. By looking at the INFORMATION_SCHEMA, I'm able to get a table of objects but can't figure out how SQL Server keeps track of any changes
I would guess you are talking about object_id. SELECT * FROM sys.objects has all objects and their ID's
You can also do:
select OBJECT_ID('your_proc_name_here')
to see what the object_id is.
As for tracking changes, there is not a table that keeps what your proc was prior to an alter statement or tells you what the view definition was 2 weeks ago. You would have to make a user defined table and write logic to handle that, or use a VCS.

Neater way of dynamically selecting a database other than sp_executesql

I am looking to set up a high availability architecture whereby two mirror databases exist (DB1 & DB2) that serve another database with views (DBV) on it. DB1 has the overnight ETL on it, whilst DBV looks at DB2 until the etl is complete on DB1, at which point its views switch to the underlying tables on DB1. Once the ETL is complete on DB1, DB2 is restored with DB1 data before the next day's ETL. The next day, DB1 and DB2 switch roles.
I am looking for a neater/more secure way of switching between the two views than running sp_executesql to run a dynamically built string. I will be looking to also do this on stored procedures from a staging database which need to have their scripts dynamically altered to use the correct database to run the ETL on. Essentially, I am looking to pass the USE statement dynamically and then execute the rest of the script outside of any dynamic statement.
I want to avoid sp_executesql for support reasons for other developers and also to get around any possible extensive concatenation of strings if the stored procedure/view gets particularly lengthy.
Any ideas / different approaches to high availability in this context would be welcome.
One option might be to create a copy of each view in DBV for both target databases - i.e.
some_schema.DB1_myview
some_schema.DB2_myview
and then use a synonym to expose the views under their final names.
CREATE SYNONYM some_schema.myview ON some_schema.DB1_myview
Your switch process would then need only to drop and recreate the synonyms, rather than the views themselves. This would still need to be done with a dynamic SQL statement, but the complexity would be much lower.
A downside would be that there would be a risk of the definitions of the underlying views getting out of sync.
Edit
At the cost of more risk of getting out of sync, it would be possible to avoid dynamic SQL altogether by creating (for instance) a pair of stored procedures each of which generated the synonyms for one database or the other. Your switch code would then only need to work out which procedure to call.
Have you considered renaming the databases as you switch things around? I.e. the following prints 1 followed by 2, nothing in DBV had to be modified:
create database DB1
go
use DB1
go
create table T (ID int not null);
insert into T(ID) values (1);
go
create database DB2
go
use DB2
go
create table T (ID int not null);
insert into T(ID) values (2);
go
create database DBV
go
use DBV
go
create view V
as
select ID
from DB1..T
go
select * from V
go
alter database DB1 modify name = DBt
go
alter database DB2 modify name = DB1
go
alter database DBt modify name = DB2
go
select * from V
Obviously better names than 1 and 2 may be used. This way, DB1 is always the one used for live and DB2 is used for any staging work.

Database name as variable

I have a database with stored procedures which selects data from another database
select * from Users in AnotherDatabase.dbo.Users
I have a couple of versions of the other database, i.e.
AnotherDatabaseProduction, AnotherDatabaseDevelopment, AnotherDatabaseStage
I remember a while back that I created some kind of global variable like AnotherDatabase_Pointer which I could set by running some stored procedure like SetAnotherDatabaseToStage:
AnotherDatabase_Pointer = 'AnotherDatabaseStage' //pseudo-code
Which I could then use in my stored procedures.
But I cannot seem to remember how it was done. All I can find is how to do this with string replacing/concatenating: variable database name :(
Is this possible? MS SQL.
You are probably thinking of a Synonym.
CREATE SYNONYM dbo.whatever FOR dbname.dbo.procedure_name;
Now, if you want to change it to some other database, you just drop and re-create the synonym:
DROP SYNONYM dbo.whatever;
GO
CREATE SYNONYM dbo.whatever FOR other_dbname.dbo.procedure_name;

Database name while referencing tables - Sybase

How do I get away with hardcoding the database name in referencing a table within a stored procedure. For example there are two databases db1 and db2. I am writing a stored procedure in db2 which references two tables, one from db1 and another from db2. Both are on the same sybase server.
If I understand your question correctly, on the one hand, in your stored procedure you can refer to the table in the same database directly by name
SELECT ...
FROM table_in_db2
You can refer to a table in database db1 by prefixing the database name and an empty owner:
SELECT ...
FROM db1..table_in_db1
On the other hand, if you want to avoid hard-coding database names in the procedure you might create a view in database db2 that references the db1 table:
CREATE VIEW view_in_db2
AS
SELECT *
FROM db1..table_in_db1
and use that in the procedure:
SELECT ...
FROM view_in_db2
You need to keep the code portable, involve 2 databases, but avoid referencing databases by name. Then you can create proxy tables (or proxy views, if such views exist in 12.5). Refer to proxy tables as to local objects.
This will work, but will require some extra care, every time you move/change databases. But anyway the separation of concerns you are after can be achieved.

Resources