Is it possible to pass db name as a parameter - sql-server

I have about 100 sites built in a cms, each with its own database. Each database has the same tables.
My stored procedure needs to select all of the pages in a database given a sitename.
Below I am trying to pass the database name as a parameter, but it doesn't seem to work.
...
#site nvarchar(250)
AS
SELECT *
FROM #site..cmsDocument
WHERE published = 1
Is there some other way to do this?

SELECT #dbname = quotename(dbname)
SELECT #sql = ' SELECT ... FROM ' + #dbname + '.dbo.tablename WHERE ...'
EXEC sp_executesql #sql, #params, ...
Refs:
sp_executesql (Transact-SQL)
The Curse and Blessings of Dynamic SQL

You can specify the database in the connection string:
Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;

Almost no DBMSes allow you to use a parameter in this manner. Build a dynamic query via concatenation and execute it.

You can use the undocumented stored procedure sp_MSforeachdb:
sp_MSforeachdb 'SELECT * FROM ?..table_name_here'

If the query / procedure is being executed from a .NET application, you can also programmatically change the database of the connection object (VB.NET):
Using da As New SqlDataAdapter("SELECT * FROM cmsDocument WHERE published = 1", GetDatabaseConnection(ServerName))
da.SelectCommand.Connection.ChangeDatabase("Foobar")
End Using

Related

Passing Multi-Value Parameter to Oracle Linked Server in SQL Server from SSRS

I'm currently building a report in SSRS using a MSSQL datasource. In that datasource I have a linked Oracle server that I am pulling my base dataset from. I'm trying to pass a multi-value text parameter from SSRS to MSSQL which then will be used in an OPENQUERY to the Oracle DB. Put simply my query in MSSQL looks something like this:
DECLARE #SQL VARCHAR(MAX)
SET #SQL = 'SELECT id, type, name FROM sample WHERE type IN (''''A'''',''''B'''')'
SET #SQL = 'SELECT * FROM OPENQUERY(oracledb,''' + #SQL + ''')'
EXEC (#SQL)
Typically with SSRS, using MSSQL, I can replace the
type IN (''''A'''',''''B'''')
with
type IN (#Parameter)
How would I go about doing this when passing the multivalue parameter to the above mentioned query since its using a linkedserver to oracle?
This works for openquery to DB2, but I will point out you're missing a + after #SQL in your example. Once I added that it worked.
SET #SQL = 'SELECT * FROM OPENQUERY(oracledb,''' + #SQL +''')'

How to get database name automatically into script to use in stored procedure execution?

I need to TRIM databases as per requirement. So, I'm using below script and giving database names manually. All I need is to automate the script to get database names automatically. Can anyone please suggest how to get the database name automatically.
Use [Sales_backup_2015_05_31_230001_7137975]
Exec [spMaint_TrimTestDB] 1
Go
for Eg:
instead of giving manually Sales_backup_2015_05_31_230001_7137975 I need to get db name automatically
Thanks.
There is a function DB_NAME() that would return the name of the current database if no parameters are passed. Check this.
I guess dynamic SQL might help you to run SP in different databases:
DECLARE #sql nvarchar(max)
SELECT #sql = (
SELECT N'Use '+QUOTENAME([name]) +' Exec [spMaint_TrimTestDB] 1;'
FROM sys.databases
WHERE database_id >= 5 AND [name] like 'Sales_backup%'
FOR XML PATH('')
)
EXEC sp_executesql #sql
This script will create and execute dynamic statement like:
Use [sales_backup_2015] Exec [spMaint_TrimTestDB] 1;
Use [sales_backup_2016] Exec [spMaint_TrimTestDB] 1;
etc...

How to Select from a database using a dynamic variable

I have a SQL 2008 database that is stored on the same instance, but this database is created by the user and name is stored in SQL table. How do I write a select statement using dynamic sql or is there a another way
So for example:
Main database - myDB
User database - userDB (this is stored in a myDB.dbo.tblUserDatabase)
userDB has a table called tblUserReports
I want to write something like this in dynamic sql:
SELECT * FROM userDB.dbo.tblUserReports
So tried:
declare #dbUser varchar(50)
set #dbUser = (SELECT strDBName FROM myDB.dbo.tblUserDatabase)
SELECT * FROM #dbUser.dbo.tblUserReports
You can do this... dynamic sql can become unmanageable very quickly so be careful.
declare #dbUser varchar(50)
set #dbUser = (SELECT strDBName FROM myDB.dbo.tblUserDatabase)
DECLARE #sql NVARCHAR(1000)
SET #sql = 'SELECT * FROM ' + QUOTENAME(#dbUser) + '.dbo.tblUserReports'
EXEC sp_executesql #sql
You cannot parameterise the table name. You will have to use dynamic SQL in your client or stored procedures. It's a very unusual thing to want to do so think long & hard about if this is a good design. Maybe if you share what you are doing then you'll get some additional ideas as to how to approach your problem.

Split database into two databases

I would like to split my database into two databases, a quick check showed that I can easily query, join, update tables across databases.
My main problem now is that to do this, I will have to do something like this.
SELECT *
FROM Database1.dbo.Table1,
Database2.dbo.Table2
As you can see I have to explicit mentioned database names, which means that if database name is deployed with a different name, this code will not work anymore.
Any ideas to overcome this problem?
You can use db_name() to get the current database name and dynamic sql to build a dynamic query.
Something like:
declare #databaseName nvarchar(max) = db_name()
declare #dynamicSql nvarchar(max) = 'SELECT * FROM '+ #databaseName + '.dbo.Table1'
exec sp_executesql #dynamicSql

Is it possible to query the ##DBTS on a database other than the current database?

For a rigorous marker of the source database state, I'd like to capture the ##DBTS
of an external database in a sproc. Yeah, I think I could issue
USE ExternalDB
GO
SELECT #myVarbinary8 = ##DBTS
GO
USE OriginalDB
GO
but, even if I could, it seems ugly.
For now, I've embedded a scalar-valued function in the source database to invoke the
SET #Result = SELECT ##DBTS
which worked fine until I forgot to ask the DBA to grant the appropriate rights for a new user, which crashed a process.
Something akin to
SELECT ExternalServer.dbo.##DBTS
(I know that doesn't work).
See MSDN ##DBTS documentation
##DBTS (Transact-SQL)
Returns the value of the current timestamp data type for the current database.
This timestamp is guaranteed to be unique in the database.
one way is to put that scalar function in the master database and mark it as system object. that way it gets called in the context of the current database
see here for more info:
http://weblogs.sqlteam.com/mladenp/archive/2007/01/18/58287.aspx
Create a stored procedure in your "other" database:
CREATE PROCEDURE dbo.GetDatabaseTimestamp AS
SET NOCOUNT ON;
SELECT ##DBTS AS CurrentRowversion, MIN_ACTIVE_ROWVERSION() AS ActiveRowversion
And then from your current database you can call:
EXECUTE ExternalDB.dbo.GetDatabaseTimestamp;
Thanks for the info, Mladen, that tip is good to know :)
But while that helps me call a function residing in master from in the current database context "ContextCurrent", what I really want is to be able to call the scalar-valued function from the context of the source database "ContextSource".
While in general, I have my reservations against dynamic sql, I ended up using it here as follows.
DECLARE #sourceDbName nvarchar(128)
SET #sourceDbName = N'sbaportia1'
DECLARE #strQuery nvarchar(max)
DECLARE #parmDefn nvarchar(max)
DECLARE #DbtsCapture varbinary(8)
SET #strQuery =
'
N' ' + N'USE' + N' ' + #sourceDbName + N' '
+ N' ' + N'SELECT #dbtsCapture = min_active_rowversion()'
'
SET #parmDefn =
N'
#dbName varchar(128),
#dbtsCapture varbinary(8) OUTPUT
'
EXEC sp_executesql #strQuery
,#parmDefn
,#dbName = 'autobahn'
,#dbtsCapture = #dbtsCapture OUTPUT
SELECT #dbtsCapture
Furthermore, since sp_executesql runs in a separate thread,
the database context within the script below will be
automatically be the same upon the exit of sp_executesql
as upon the entry of sp_executesql.
(I learned waaayy too much about sp_executesql in the early 2000's.)

Resources