Database name as variable - sql-server

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;

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?

is it possible to create scripts in Netezza like SQL server?

I am trying to create the script in netezza like what we do in SQL server with variable declaration but I am not able to do it.
Need to create a temp table and then need to pass the parameter to it through a variable.
DECLARE var1 varchar(10);
through error message every time
How to drop a temp table. and how the temp table data is stored and cleared in the memory?
Netezza has its own language for stored procedures - same concept as SQLserver but closer to oracle syntax.
It is however not possible to use the 'variables' construct outside such a stored procedure, which leaves you with a couple of options in your case:
1. do a 'create or replace procedure' with your script embedded, and the execute the sp
2. store intermediate results in temporary tables, and do the 'if-then-else' logic in another scripting language (perl powershell or the like)
We went for option 1 in most cases when moving from SQLserver to Netezza about a year ago...

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.

How to create a table that exist temporarily and that is accessible from many stored procedures?

I query my database from within a .NET application (time recoding). I send the Windows user name to the database and query it depending on this information.
I query a lot of different information with stored procedures, such as holiday, overtime etc. and send them back to the .NET application where I show this data in one form.
Let's say I need the information from SP1, 3 and 4 on Form1:
FORM1:
SP1
SP3
SP4
My problem:
I have a quite complicated table that I need for these stored procedures. At the moment I create this table in every of those stored procedures as temporary tables what is obviously quite time consuming.
What I have tried so far is creating a stored procedure that creates a temp table but this one is not accessable within my other stored procedures.
My question: I am looking for a way to create this table for Form1 once, so I can just access these table in the other stored procedures.
I'm using SQL Server 2014 Express.
If you create the temporary table outside of any stored procedure, it will be accessible within each. Assuming that the actual table definition isn't too complex (but populating it may be), this may be doable.
So you'd execute (effectively):
CREATE TABLE #T (A int not null, B varchar(17) not null)
EXEC PopulateTempTable
EXEC SP1
EXEC SP3
EXEC SP4
All on a single connection. PopulateTempTable may or may not be required, depending on how complex the population of the table is and whether you want that to be performed by your calling code or the database.
You cannot create the temp table inside of a stored procedure since temp tables are automatically dropped when the scope of a stored procedure is exited.
Alternatively, you may want to simulate "session-global" temp tables, as I suggest in this answer1.
The risk with using a global temp table is that it is truly global - all sessions see and interact with the data in the same table. You have to be very careful in such circumstances if it's at all possible that two sessions will attempt to use it at the same time; You generally need some means to filter the data in the table so that each session only works with its own data.
1Probably enhanced these days by also adding a Logon Trigger to clear down the old contents of the table whenever a new connection is established.
You have to create global temp table
CREATE TABLE ##TEMP1
(
Name varchar(50)
)

How does SQL Server lookup object names in stored procedures?

I have a stored procedure in SQL Server 2008 such as:
CREATE PROCEDURE [dbo].[test]
AS
BEGIN
SET NOCOUNT ON;
SELECT user_name();
SELECT SCHEMA_NAME()
SELECT * FROM MyView
END
I have a view named testuser.MyView. I then call the SP using:
exec as user = 'testuser' exec test
This shows the user_name and SCHEMA_NAME are both set to testuser
However I also get a Invalid object name 'MyView'. message, as the SP is still looking up the view name in the dbo schema.
Is there anyway to change how the SP is executed so the MyView object references testuser.MyView without having to use a fully qualified name?
I am trying to use a single set of many stored procedures, on identical table structures in different schemas. I really want to avoid rewriting all the SPs using dynamic SQL, or to create copies of all the SPs each using qualified names.
Unqualified object names are resolved using the module owner's default schema. This behavior can't be changed so you'll need to resort to the other methods you mentioned.
Since you already create separate tables and views for each user with the same structure, why not create stored procedures in the user's schema at the same time?

Resources