I am preparing a group of sql queries for a dashboard. I want to declare the database name at the beginning so that the queries will work on the database specified on top without making any changes in the underlying code
Original query:
SELECT *
FROM Check.dbo.Dates_table
The query I want:
DECLARE #Databasename VARCHAR(200)
SET #Databasename = 'Check.dbo'
SELECT * FROM #Databasename.Dates_table
You can use "USE" operator: https://msdn.microsoft.com/en-AU/library/ms188366.aspx
use Check
SELECT * FROM dbo.Dates_table
Related
It is possible in SSMS to run the same query on some databases?
I was thinking something like an array with database names and cycling through it, maybe with SQLCMD mode.
some pseudocode:
:setvar arr ["db1", "db2", "db3"]
foreach $db in $arr
:setvar database $db
use $(database)
go
select * from table
Thanks
-- To Achive your Desire OutpUt You Have to Use Dynamic Query
-- you can Achieve this in TSQL
-- TO Know The Database ID Run Below Query
/*
SELECT * FROM Sys.databases WHERE database_id >4
*/
USE MASTER
GO
BEGIN TRAN
DECLARE #strt INT,#End INT,#Database NVARCHAR(255)
SELECT * INTO #T FROM Sys.databases WHERE database_id IN (4,5,6)-- Here you Have to Defined the Database ID
ORDER BY 1
SELECT ROW_NUMBER ()OVER (ORDER BY database_Id)Db_Id,* INTO #TT FROM #T
SET #strt=1
SELECT #End=Max(Db_ID)FROM #tt
WHILE #strt<=#END
BEGIN
DECLARE #string NVARCHAR(MAX)
SELECT #Database=NAME FROM #TT WHERE Db_ID=#strt
Set #string=' Select * from '+#Database+'..Table_Name'
SET #strt=#strt+1
PRINT #string
EXEC(#string)
END
ROLLBACK TRAN
Here's an example using two of my databases (Staging and Warehouse) to hit the sys.columns table in each. Just change out the IN filter with the names of whichever databases you want, and the ".sys.columns" with the schema/table name you need.
DECLARE #query NVARCHAR(MAX) = ''
;
SELECT #query += CONCAT('SELECT * FROM ',[name],'.sys.columns;')
FROM sys.databases
WHERE [name] IN ('Staging','Warehouse')
;
EXEC sp_executesql #query;
You can do this with a Local Server Group as well.
View --> Registered Servers
Right-click Local Server Group and create new
Add new server registrations to the group (any databases you want to query). Be sure to specify the database in the Connection Properties tab
Now you can right-click the Local Server Group folder and execute a new query, which will run on all the databases in that folder.
Observe the following simple SQL code:
CREATE TABLE #tmp (...) -- Here comes the schema
INSERT INTO #tmp
EXEC(#Sql) -- The #Sql is a dynamic query generating result with a known schema
All is good, because we know the schema of the result produced by #Sql.
But what if the schema is unknown? In this case I use Powershell to generate a Sql query like that:
SET #Sql = '
SELECT *
INTO ##MySpecialAndUniquelyNamedGlobalTempTable
FROM ($Query) x
'
EXEC(#Sql)
(I omit some details, but the "spirit" of the code is preserved)
And it works fine, except that there is a severe limitation to what $Query can be - it must be a single SELECT statement.
This is not very good for me, I would like to be able to run any Sql script like that. The problem, is that no longer can I concatenate it to FROM (, it must be executed by EXEC or sp_executesql. But then I have no idea how to collect the results into a table, because I have no idea of the schema of that table.
Is it possible in Sql Server 2012?
Motivation: We have many QA databases across different Sql servers and more often than not I find myself running queries on all of them in order to locate the database most likely to yield best results for my tests. Alas, I am only able to run single SELECT statements, which is inconvenient.
We use SP and OPENROWSET for this purpose.
At first create SP based on a query you need, than use OPENROWSET to get data into temp table:
USE Test
DECLARE #sql nvarchar(max),
#query nvarchar(max)
SET #sql = N'Some query'
IF OBJECT_ID(N'SomeSPname') IS NOT NULL DROP PROCEDURE SomeSPname
SET #query =N'
CREATE PROCEDURE SomeSPname
AS
BEGIN
'+#sql+'
END'
EXEC sp_executesql #query
USE tempdb
IF OBJECT_ID(N'#temp') IS NOT NULL DROP TABLE #temp
SELECT *
INTO #temp
FROM OPENROWSET(
'SQLNCLI',
'Server=SERVER\INSTANCE;Database=Test;Trusted_Connection=yes;',
'EXEC dbo.SomeSPname')
SELECT *
FROM #temp
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.
How can I use a variable as db context?
Create Procedure [dbo].[prName] (#dbname varchar(25)) as
begin
use master
some sql
<!-- I need to use master for some functions stored in master -->
use #dbname
exec('SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE [TABLE_CATALOG] = '+#dbname+' and TABLE_NAME=table123')
end
GO
Thanks
I think you might want to use the following:
CREATE Procedure [dbo].[prName] (#dbname varchar(25)) as
begin
exec('select top 5 * from '+#dbname+'.yourSchema.yourTable')
end
The USE statement is not allowed in a stored procedure. If you are passing in the database name, then you do not need the USE statement, the database name will be included in your sql query.
Edit: Based on your edit that you need to access items in master, then all you need to do is execute your sql, specifying the need of master just use fully qualified sql.
CREATE Procedure [dbo].[prName] (#dbname varchar(25)) as
begin
select * from master.INFORMATION_SCHEMA.TABLES
exec('select top 5 * from '+#dbname+'.yourSchema.yourTable')
end
I have multi databases with same structure its name like that "Client1234" the different in numbers beside "client" i have table called "Transactions" inside each database and i want to run query to get count all raws in "transactions" table in all databases.
also when i select database i need to check it has the client word and it has numbers beside the word.
Try to use sp_msforeachdb stored procedure like so:
create table #temp ([rows] int, [client] varchar(100))
exec sp_msforeachdb '
if ''?'' like ''Client%'' and exists(select * from ?.sys.tables t where t.name = ''Transactions'')
begin
insert into #temp select count(*), ''?'' from ?..Transactions
end
'
select * from #temp
drop table #temp
You can use dynamic SQL to create these queries:
select 'select count(*) from ' + name + '.dbo.transactions'
from master..sysdatabases
where name like 'Client%'
and isnumeric(substring(name,6,1))
This would return a result set with each row being a SQL query to count a specific database. It could be consumed by a programming language, used as a cursor, etc.. If you provide more detail I may be able to provide a better example.
When using Fosco's method, it is a good idea to put in brackets [] around the database name:
SELECT 'SELECT count(*) FROM ' + '[' + name + ']' + '.dbo.transactions'
FROM master..sysdatabases
WHERE name like 'Client%' and isnumeric(substring(name,6,1))
If the name and number of the databases you wish to query is not known beforehand then you can only do this by using a dynamic query. You'll need to generate a script like
SELECT COUNT(*) FROM Client1.dbo.Transactions
SELECT COUNT(*) FROM Client2.dbo.Transactions
...
Of course you need to have your appropriate permissions in place for each database.