I'm having quite the problem.
The process data from our machines is stored in multiple MS SQL Databases.
It is possible to mount and unmount data which is no longer used or which should be archived.
Thats the reason, why there are multiple databases.
In each Database there exists multiple tables with the data values for one or more measuring points.
Which a JOIN Query i can get the values from one table with the corresponding table and tagname:
> SELECT HA_DATA_yyyy.R_xxxxx.time HA_DATA_yyyy.R_xxxxx.value, HA_DATA_yyyy.tags.tagname FROM HA_DATA_yyyy.R_xxxxx
> INNER JOIN HA_DATA_yyyy.RI_xxxxx ON HA_DATA_yyyy.R_xxxxx.id = HA_DATA_yyyy.RI_xxxxx.id
> INNER JOIN HA_DATA_yyyy.tags on HA_DATA_yyyy.RI_xxxxx.tag_uuid = HA_DATA_yyyy.tags.tag_uuid
> WHERE (HA_DATA_yyyy.tags.tagname like 'tagname')
yyyy - represents a number for the database
xxxxx - represents a number which is unique on the database-server, but differents in each database.
But now I'm looking for a solution to get this for all R_xxxxx tables of a database and for all mounted databases.
Is there any way to do this without external software? Just with the right query request or user defined function / stored procedure?
maybe dynamic sql is an option.
as a starting point you could use the list of databases:
insert into #dblist (dbname)
select d.name from sys.databases d where d.name like 'HA_DATA_%'
then for each database gather the list of tables to read data from (you can go with cursors or other loop as you prefer):
declare #dbname varchar(128) = ''
declare #dynsql nvarchar(max)
create table #listoftables (name varchar(128), db varchar(128))
while exists(select top 1 dbname from #dblist where dbname > #dbname order by dbname)
begin
set #dynsql = 'insert into #listoftables(name,db) select name,''' + #db + ''' from '+ #db +'.sys.tables'
exec sp_executesql #statement = #dynsql
-- move on to next db
select top 1 #dbname = dbname from #dblist where dbname > #dbname order by dbname
end
now you have a table list to loop onto to build a dynamic query to read all the data at once.
beware of the many issues you may incur using dynamic sql; here and there you can find just the first 2 results gathered with some explanations on why you have to be careful using dynamic sql.
Please have a look at the answer of this Stackoverflow question:
Archiving large amounts of old data in SQL Server
I think it might be what you need.
Update:
You can query the mounted databases by using the SQL query:
select Name into #myDatabases -- get all mounted databases into #myDatabases
from sys.databases
where (has_dbaccess(name) > 0)
and name not in ('master', 'tempdb', 'model', 'msdb')
order by 1
select * from #myDatabases -- list all mounted databases
drop table #myDatabases -- don't forget to drop it at the end
This can be used to create a dynamic SQL statement, which you execute via the sp_executesql command:
EXECUTE sp_executesql #SQL_String, #Parameter_Definition, #Param1, ..., #ParamN
The parameter definition is a string containing the list of parameter names and their datatypes.
So you can build up your own query based on the database list above and then execute it.
I've searched here and elsewhere, and haven't found an answer yet. Hope I didn't miss it.
Using SQL Server Management Studio 2008 R2.
I have n specific databases on my server (there are other DBs as well, but I'm only interested in some of them)
Each of these databases has a table within it, which all have the same name. The only difference is the DB name. I want to aggregate these tables together to make one big table on a different database (different to the other DBs).
I can get the db names from the results of a query.
N is unknown.
Is a loop the way to go about this?
I was thinking something along the lines of the following pseudocode:
Set #dbnames = SELECT DISTINCT dbname FROM MyServer.dbo.MyTable
For each #name in #dbnames
INSERT INTO ADifferentDB.dbo.MyOtherTable
SELECT * FROM #name.dbo.table
Next name
(Clearly I'm new to using SQL variable as well, as you can see)
Your first problem is about iterating the databases: you cand do that with a cursor
Then you have another problem, executing a query where part of it is variable (database's name). You can do that with execute function.
All that is something similar to this:
DECLARE #query VARCHAR(max)
DECLARE #dbname VARCHAR(100)
DECLARE my_db_cursor CURSOR
FOR SELECT DISTINCT dbname FROM MyServer.dbo.MyTable
OPEN my_db_cursor
FETCH NEXT FROM my_db_cursor
INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = 'INSERT INTO ADifferentDB.dbo.MyOtherTable
SELECT * FROM ' + #dbname + '.dbo.table'
EXECUTE(#query)
FETCH NEXT FROM my_db_cursor
INTO #dbname
END
CLOSE my_db_cursor
DEALLOCATE my_db_cursor
what you want to do is define a CURSOR for row-level operation. here is some doc
I would suggest using sp_MSForEachDB:
EXEC sp_MSForEachDB '
-- Include only the databases you care about.
IF NOT EXISTS (
SELECT *
FROM MySever.dbo.MyTable
WHERE dbname = ''?''
)
-- Exit if the database is not in your table.
RETURN
-- Otherwise, perform your insert.
INSERT INTO ADifferentDB.dbo.MyOtherTable
SELECT * FROM ?.dbo.table
'
In this case, ? is a token that is replaced with each database on the server.
After some searching around i couldn't find a good answer that covers my issue.
I am working on the consolidation of around 100 databases. The structure is the same and they are all on the same server. All the databases have a table with login information.
We have created a core database with all the connection information from the other databases.
Now we need to create a view in the core database that contains all the login credentials from all the databases.
This means we need to use a loop to go through all the databases and select the user name and password.
Any ideas or suggestions are welcome
One possible solution is to create a stored procedure
DECLARE #sql varchar(max), #Database1 varchar(300)
set #Database1 = 'tempdb'
SET #sql='
USE '+#Database1+';
IF EXISTS (SELECT 1 FROM SYS.VIEWS WHERE NAME =''test_view'')
BEGIN
DROP VIEW test_view
PRINT ''VIEW EXISTS''
END'
PRINT #sql
EXEC(#sql)
declare #sql1 varchar(max)
// Modify below query as per your requirement its just for an idea
select #sql1 = IsNull(#sql1 + 'union all ','') +
'select * from ' + name + '.dbo.tblUser'
from sys.databases
where name like 'DbNamePrefix%'
set #sql1 = 'create view dbo.YourView as ' + #sql1
exec (#sql1)
Make a database job and schedule it as per your requirement.
To reference to your tables in the second database use this:
[DBName].[dbo].[TableName]
e.g.
CREATE VIEW [dbo].[ViewName]
as
select
a.ID,
a.Name,
b.Address
from TableA a
join SecondDBName.dbo.Table b
on ... ---Remaining code here...
NOTE: This will work only on the same server - if your databases are on different servers then you will need to create a linked server.
Take a look at this. Can this be one of the answers to your question?
http://blog.springsource.org/2007/01/23/dynamic-datasource-routing/
I have to move a table into other table using a stored procedure by passing the table names as parameters.
Syntax is:
alter procedure [dbo].[moving]
(
#to_table varchar(50),
#from_table varchar(50)
)
as
begin
EXEC('Select * into '+#to_table+'from '+#from_table)
end
while executing by.
exec moving newtable,hello
It is giving an error:
Incorrect syntax near 'hello'
pls anyone give solution for this
Try:
exec moving 'newtable','hello'
It also looks like you are going to need to fix your SP. You will need a space before from:
EXEC('Select * into '+#to_table+' from '+#from_table)
Read EXECUTE syntax and try,
EXEC moving 'newtable','hello'
SELECT ... INTO needs to create table, if table exists use INSERT INTO ... SELECT ..FROM
AND
in your case you need to run SP in such a way:
EXEC dbo.moving 'table1', 'table2'
BUT
EXEC('Select * into '+#to_table+' from '+#from_table)
will not work, you need to rewrite it with variable:
declare #sql nvarchar(max)
SET #sql = N'Select * into ['+#to_table+N'] from ['+#from_table+N']'
EXEC(#sql)
BUT
you also need to worry of sql injections and complex table names AT LEAST, so - for complex table names I already framed your tables with square braces, and you need to do something to prevent sql injections.
And once more - SELECT...INTO works only if you creating new table with name from #to_table parameter
add an extra space after single quote and FROM
EXEC('Select * into ' + #to_table + ' from ' + #from_table)
Is it possible that Execute SQL Query without Displaying results?
like
Select * from Table_Name
after running this query result should not be displayed in sql server.
I'm surprised nobody came up with the answer : switch on the "discard query results after execution" option; l I'm pretty sure that was what the interviewer was after. SET FMT ONLY is totally different thing IMHO.
In SSMS
open a new query
in the menu select Query / Query options
select the Results pane
check the "discard result after execution"
The reason you might want to do this is to avoid having to wait and waste resources for the results to be loaded into the grid but still be able to have e.g. the Actual Execution Plan.
Executing will return a recordset. It may have no rows of course but get a result
You can suppress rows but not the resultset with SET FMTONLY
SET FMTONLY ON
SELECT * FROM sys.tables
SET FMTONLY OFF
SELECT * FROM sys.tables
Never had a use for it personally though...
Edit 2018. As noted, see #deroby's answer for a better solution these days
Sounds like a dubious interview question to me. I've done it, I've needed to do it, but you'd only need to do so under pretty obscure circumstances. Obscure, but sometimes very important.
As #gbn says, one programmatic way is with SET FMTONLY (thanks, now I don't have to dig it out of my old script files). Some programs and utilities do this when querying SQL; first they submit a query with FMTONLY ON, to determine the layout of the resulting table structure, then when they've prepared that they run it gain with FMTONLY OFF, to get the actual data. (I found this out when the procedure called a second procedure, the second procedure returned the data set, and for obscure reasons the whole house of cards fell down.)
This can also be done in SSMS. For all querying windows, under Tools/Options, Query Results/SQL Server/Results to XX, check "Discard results after query executes"; for only the current window, under Query/Query Options, Results/XX, same checkbox. The advantage here is that the query will run on the database server, but the data results will not be returned. This can be invaluable if you're checking the query plan but don't want to receive the resulting 10GB of of data (across the network onto your laptop), or if you're doing some seriously looped testing, as SSMS can only accept so many result sets from a given "run" before stopping the query with a "too many result sets" message. [Hmm, double-check me on that "query plan only" bit--I think it does this, but it's been a long time.]
insert anothertable
Select * from Table_Name
Executes the select but returns nothing
set noexec on
Select * from Table_Name
Parses but does not execute and so returns nothing.
Perhaps the interviewer intended to ask a different question:
How would you execute a SQL query without returning the number of results?
In that case the answer would be SET NOCOUNT ON.
If you need the query to execute but don't need the actual resultset, you can wrap the query in an EXISTS (or NOT EXISTS) statement: IF EXISTS(SELECT * FROM TABLE_NAME...). Or alternately, you could select INTO #temp, then later drop the temp table.
Is the goal to suppress all rows? Then use a filter that evaluates to false for every row:
SELECT * FROM Table_Name WHERE 1 = 2
In my case I was testing that the data was behaving in all views, e.g. any cast() functions weren't causing conversion errors, etc. so supressing the actual data wasn't an option, displaying wasn't too bad but a bit of wasted resource and better not to diplsay if sending results only in text.
I came up with the following script to test all the views in this way, the only problem is when it encounters views that have text/ntext columns.
declare csr cursor local for select name from sys.views order by name
declare #viewname sysname
declare #sql nvarchar(max)
open csr
fetch next from csr into #viewname
while ##fetch_status = 0 begin
--set #sql = 'select top 1 * from ' + #viewname
set #sql = 'declare #test nvarchar(max) select #test = checksum(*) from ' + #viewname
print #viewname
exec sp_executesql #sql
fetch next from csr into #viewname
end
close csr
deallocate csr
If you are using PostgreSQL you can put your select in a function and use
PERFORM
The PERFORM statements execute a parameter and forgot result.
A PERFORM statement sets FOUND true if it produces (and discards) one or more rows, false if no row is produced.
https://www.postgresql.org/docs/9.1/plpgsql-statements.html#:~:text=A%20PERFORM%20statement%20sets%20FOUND,if%20no%20row%20is%20returned.
Yet another use case is when you just want to read all the rows of the table, for example testing against corruptions. In this case you don't need the data itself, only the fact that it is readable or not.
However, the option name "Discard results AFTER execution" is a bit confusing - it tells me that the result is fetched and only then discarded. In contrary, it fetches the data for sure but does not store it anywhere (by default the rows are put into the grid, or whatever output you have chosen) - the received rows are discarded on the fly (and not AFTER execution).
I am surprised the community can't easily find a use case for this. Large result sets take memory on the client, which may become a problem if many SSMS windows are active (it is not unusual for me to have 2-3 instances of SSMS opened, each with 50-70 active windows). In some cases, like in Cyril's example, SSMS can run out of memory and simply unable to handle a large result set. For instance, I had a case when I needed to debug a stored procedure returning hundreds of millions of rows. It would be impossible to run in SSMS on my development machine without discarding results. The procedure was for an SSIS package where it was used as a data source for loading a data warehouse table. Debugging in SSMS involved making non-functional changes (so the result set was of no interest to me) and inspecting execution statistics and actual query execution plans.
I needed a proc to return all records updated by a specified user after a certain point in time, only showing results where records existed. Here it is:
-- Written by David Zanke
-- Return all records modified by a specified user on or after a specified date.
If mod date does not exist, return row anyhow
Set Nocount on
Declare #UserName varchar(128) = 'zanked'
, #UpdatedAfterDate Varchar( 30) = '2016-10-08'
, #TableName varchar( 128)
, #ModUser varchar( 128)
, #ModTime varchar( 128)
, #sql varchar( 2000 )
-- In a perfect world, left join would be unecessary since every row that captures the last mod user would have last mod date.
-- Unfortunately, I do not work in a perfect world and rows w/ last mod user exist w/o last mod date
Declare UserRows Cursor for Select distinct c1.table_name, c1.column_name, c2.column_name From INFORMATION_SCHEMA.COLUMNS c1
Left Join INFORMATION_SCHEMA.COLUMNS c2 On c1.Table_Name = c2.Table_Name And c2.Column_name like '%DTTM_RCD_LAST_UPD%'
Where c1.column_name like '%UPDATED_BY_USER%'
Open UserRows
Fetch UserRows Into #tablename, #ModUser, #ModTime
While ( ##FETCH_STATUS = 0 )
Begin
-- capture output from query into a temp table
Select #sql = 'Select ''' + #TableName + ''' TableName, * Into ##HoldResults From ' + #TableName + ' Where ' + #ModUser + ' = ''' + #userName + ''''
+ Case When #ModTime Is Null Then '' Else ' And ' + #ModTime + ' >= ''' + #UpdatedAfterDate + '''' End
Exec ( #sql)
-- only output where rows exist
If ##ROWCOUNT > 0
Begin
Select * from ##HoldResults
End
Drop Table ##HoldResults
Fetch UserRows Into #tablename, #ModUser, #ModTime
End
Close UserRows;
Deallocate UserRows