Execute saved queries in table SQL Server - sql

I have a table with the list of select statements:
query
----------------------------
Select Max(acc),Min(acc) from my_table1
Select Max(acc),Min(acc) from my_table2
Select Max(acc),Min(acc) from my_table3
.......
I want to execute all saved queries in the table and save the all result in a new table. because all the result should matches(MAX and MIN).

Just use UNION ALL like this:
declare #sql nvarchar(max);
select
#sql = case when #sql is null then '' else #sql + ' union all ' end + query
from
t;
insert into destinationTable (max, min)
EXEC sp_executesql (#sql);

Use cursor over your table and execute as dynamic t-sql adding insert into at the beginning of every value with SQL statement.
CREATE TABLE tSELECT
(
query VARCHAR(1000)
);
INSERT INTO tselect VALUES ('Select Max(acc),Min(acc) from my_table1')
CREATE TABLE result (min INT, max int);
BEGIN
DECLARE #stmt VARCHAR(1000);
DECLARE db_cursor CURSOR FOR SELECT * FROM tselect;
OPEN db_cursor FETCH NEXT FROM db_cursor INTO #stmt
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC('insert into result ' + #stmt);
FETCH NEXT FROM db_cursor INTO #stmt
END
CLOSE db_cursor
DEALLOCATE db_cursor
END;

Related

Displaying multiple database tables in one table

I have multiple databases with the same table (an Eventlog with different values). The names of these databases are subject to change. I am trying to display the Eventlog tables in one consolidated table with the corresponding database name.
I tried to using cursor and dynamic SQL statement to achieve this with no luck. As well, I'm not sure if that is the best approach. Would love some help!
-- Create a new table variable to record all the database name
DECLARE #Database_Table table ([TimeStamp] nvarchar(500)
,[EventIDNo] nvarchar(100)
,[EventDesc] nvarchar(1000))
--Create variable for database name and query variable
DECLARE #DB_Name VARCHAR(100) -- database name
DECLARE #query NVARCHAR(1000) -- query variable
--Declare the cursor
DECLARE db_cursor CURSOR FOR
-- Populate the cursor with the selected database name
SELECT name
FROM sys.databases
WHERE name NOT IN ('master','model','msdb','tempdb')
--Open the cursor
OPEN db_cursor
--Moves the cursor to the first point and put that in variable name
FETCH NEXT FROM db_cursor INTO #DB_Name
-- while loop to go through all the DB selected
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = N'INSERT INTO #Database_Table
SELECT #DB_Name, *
FROM ['+ #DB_Name +'].dbo.EventLog_vw as A'
EXEC (#query)
--Fetch the next record from the cursor
FETCH NEXT FROM db_cursor INTO #DB_Name
END
--Close and deallocate cursor
CLOSE db_cursor
DEALLOCATE db_cursor
SELECT *
FROM #Database_Table
If you need a single resultset and all tables have the same layout, this should work:
DECLARE #sql nvarchar(4000) =
(SELECT STRING_AGG(CONCAT(
'SELECT ''',
QUOTENAME(name),
''',
* FROM ',
QUOTENAME(name),
'..Table ',
CHAR(10)
), ' UNION ALL ' + CHAR(10))
FROM sys.databases);
SELECT #sql; -- for checking
EXEC(#sql);
If you're on compatibility level 130 or lower, you will have to use XML PATH(TYPE, '') to aggregate. I will leave that to you.
I notice a bug in this code:
SET #query = N'INSERT INTO #Database_Table
SELECT #DB_Name, *
FROM ['+ #DB_Name +'].dbo.EventLog_vw as A'
In the SELECT clause you reference #DB_Name inside the string itself without concatenating the value as a variable. You did do this correctly in the FROM clause.
Something like:
SET #query = N'INSERT INTO #Database_Table
SELECT ''' + #DB_Name + ''', *
FROM ['+ #DB_Name +'].dbo.EventLog_vw as A'

Using multiple select statements inside single query and display the results as a new rows

I want to create a query which returns the sum of certain select statement parameters within the query and create a new result table with new rows which is the results derived from select statements as below.
This is my table.
I want the result to be like below where Col4 is the result of a select statement with row 2, 3 and 5 and column 5 is the result of the calculation on the col values as below
and the result will look like this below. Is that possible to do in MS SQL SERVER.
Demo
--http://sqlfiddle.com/#!18/87a6f/4
--Schema
create table mytable(col1 int,col2 int,col3 int,col4 int)
insert into mytable values
(111,1,0,4),
(112,3,1,2),
(113,1,2,2),
(114,2,4,3),
(115,3,1,0),
(116,1,0,2),
(117,2,1,0),
(118,4,1,3),
(119,3,2,1)
create table tabscript (col4 varchar(max),col5 varchar(max))
create table tabresult(col4 varchar(max),col5 int)
--Put here th scripts you wish to execute
insert into tabscript(col4,col5) values('112,113,115','sum(col2+col3+col4)'),
('115,117,119','sum(col2+col3+col4)'),('114,118,111','sum(col2+col3+col4)')
--Kamel Gazzah
--kamelgazzah#gmail.com
--29/10/2019
declare #script as varchar(max)
declare #sqlCommand as nvarchar(max)
declare #result as int
declare mycursor cursor for
select concat('select #result=',col5, ' from mytable where col1 in(',col4,')')
from tabscript
open mycursor
declare #sql as nvarchar(max)
fetch mycursor into #sqlCommand
while ##fetch_status=0
begin
--print #sql
--print #sqlCommand
exec sp_executesql #sqlCommand,N'#result int output',#result output
insert into tabresult values(#sqlcommand,#result)
fetch mycursor into #sqlCommand
end
close mycursor
deallocate mycursor
go
select * from tabresult

Execute SELECT-resulted statements

I've been searching for hours on how to execute the statements I have stored in a table that has the results of a SELECT statement.
I have found similar questions but none of them works.
So now I have a table where the first column's cells contain
DROP TABLE table1
DROP TABLE table2
..... and so on.
I've tried using the EXEC command but I can't make it work.
Please help. Thank you.
I think you need to implement a cursor if you want to execute all statements
DECLARE #Query VARCHAR(250)
DECLARE crs_ExecStatement CURSOR FAST_FORWARD
FOR
SELECT Column1 FROM YourTable
OPEN crs_ExecStatement
FETCH NEXT FROM crs_ExecStatement INTO #Query
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC(#Query)
FETCH NEXT FROM crs_ExecStatement INTO #Query
END
CLOSE crs_ExecStatement
DEALLOCATE crs_ExecStatement
use EXEC and separate the values with GO as next demo:-
Create database Demo
go
use Demo
go
Create table MyTable (Value varchar (200))
go
insert into MyTable values ('Drop Table table1')
go
insert into MyTable values ('Drop Table table2')
go
insert into MyTable values ('Drop Table table3')
go
declare #Query nvarchar(max)
SELECT #Query = isnull(#Query,'') + Value + char (10) + 'Go'
FROM MyTable
--print #Query
SET #Query = 'EXEC (''' + REPLACE(REPLACE(#Query, '''', ''''''), 'GO', '''); EXEC(''') + ''');'
EXEC (#Query)
The idea of executing dynamic Query with go is taken from here.

Using a variable string in a select * from statement

Is something like this possible?:
DECLARE #test nvarchar(30) = 'Appt'
SELECT * FROM #test.dbo.tablename with (NOLOCK)
or possibly
DECLARE #test nvarchar(30) = 'Appt'
SELECT * FROM #test + '.dbo.tablename' with (NOLOCK)
No, right?
I'm not looking to put the whole string into a variable and then use "EXEC." I have long scripts that I want to just try to replace that with when it occurs.
Thank you.
This requires Dynamic SQL. Basically you create a string that builds the SQL statement dynamically based on your query. That string is then executed with an EXEC Statement. A basic example is like this:
DECLARE #test nvarchar(30) = 'Appt'
DECLARE #sql as varchar(max)
SET #SQL = 'SELECT * FROM' + #test + '.dbo.tablename' + 'with (NOLOCK)'
EXEC #SQL
Assuming your tablename was Appt.dbo.tablename
I think you meant:
SET #SQL = 'SELECT * FROM' + 'dbo.' + #test + ' with (NOLOCK)'
Nice explanation logixologist.
Because Tom wants to run it for multiple select statements, i was thinking he could store all the table names in a column and use a cursor to fetch the table values. Considering you would create a table first such as:
CREATE TABLE tableName ( name varchar(20));
then run the following code once you inserted the right values in the table above.
Declare #table VARCHAR(255)
DECLARE #sql as varchar(max)
SET #SQL = 'SELECT * FROM' + 'dbo.' + #table + ' with (NOLOCK)'
DECLARE table_cursor CURSOR FOR
select distinct([name]) FROM DBname.dbo.tableName
Where [name] is not null
OPEN table_cursor
FETCH Next from table_cursor
INTO #table
WHILE ##FETCH_STATUS =0
BEGIN
EXEC #SQL
FETCH NEXT FROM table_cursor
INTO #table
END
CLOSE table_cursor
DEALLOCATE table_cursor
The cursor would return the table name for the select statement. I think you could use the same logic for insert statements.

Script -> Query for multiple databases

I have the following problem: I want to execute a query on multiple databases on my SQL Server. Every customer has a separate database. Those all have exactly the same table and their names are similar. So there is a database kde_01_Miller, then a kde_02_Mueller and so on ...
I want to execute a query in every one of those databases.
Here's what I have tried:
DECLARE #name VARCHAR(100) -- database name
DECLARE #dothis nvarchar(200)
DECLARE db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name like 'kde_0%'
order by name
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
set #dothis = 'use [' + #name + ']'
exec sp_executesql #dothis
/* Start query */
select description from dbo.basicdata
/* End query */
FETCH NEXT FROM db_cursor INTO #name
END
CLOSE db_cursor
DEALLOCATE db_cursor
The problem is that the query does not work properly. The use statement seems not to be working. I get a result for every database I have, but the result is always the same one, dependent on the database I'm currently doing a query for.
I've also tried the following and it worked: Instead of my while-loop I did this:
WHILE ##FETCH_STATUS = 0
BEGIN
set #dothis= 'select description from ' + QUOTENAME(#name) + '.dbo.basicdata'
exec sp_executesql #dothis
FETCH NEXT FROM db_cursor INTO #name
END
But I don't like this way, because you need the quotename(#name) for every table.
How do I make the first example work?
That's not possible, since sp_executesql is executed as its own self-contained batch, that mean you did actually "use" other databases, but only in those batchs i mentioned earlier
I'll try to be more clear, this code of you is a batch, since there's no "GO" command inside (read my sql comments) :
DECLARE #name VARCHAR(100) -- database name
DECLARE #dothis nvarchar(200)
DECLARE db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name like 'kde_0%'
order by name
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
set #dothis = 'use [' + #name + ']'
-- this will create another batch and execute the #dothis
-- it'll have nothing todo with your current executing batch,
-- which is calling the sp_executesql
exec sp_executesql #dothis
/* Start query */
select description from dbo.basicdata
/* End query */
FETCH NEXT FROM db_cursor INTO #name
END
CLOSE db_cursor
DEALLOCATE db_cursor
So, there's only one way left, write whatever you want to do with the database inside the #dothis :
declare #dothis nvarchar(max)
set #dothis = '
use [' + #name + ']
-- query start
Select description from dbo.basicdata
-- query end
'
exec sp_executesql #dothis
While this question has already been answered, I thought I'd provide a second answer I believe is better. Instead of using a Cursor you can generate dynamic SQL to query multiple databases.
DECLARE #sql NVARCHAR(Max);
SELECT #sql = COALESCE(#sql, '') + 'SELECT * FROM ' + [name] + '.sys.tables' + CHAR(13)
FROM sys.databases
PRINT #sql
EXEC sp_executesql #sql
The above SQL will Generate the following SQL.
SELECT * FROM master.sys.tables
SELECT * FROM tempdb.sys.tables
SELECT * FROM model.sys.tables
SELECT * FROM msdb.sys.tables
SELECT * FROM StackOverflow.sys.tables
SELECT * FROM AdventureWorks2012.sys.tables
SELECT * FROM AdventureWorksDW2012.sys.tables
As you see I was able to run a query against multiple databases. I could even UNION the data together if I'd like.
though already answered in finding a solution for the same issue I wrote this query.
it provides the data and it shows the source of the database which provides the answer.
note the order by is only to show double values but slows down the result
declare #results table (
name varchar(50),
clientnr numeric(20) ,
dbname_source varchar(20)
);
insert #results
exec sp_msforeachdb N'
use [?]
if left(''?'',3) = ''ons'' -- only execute the query against databases that match the naming pattern in this example starting with ons (use your own database names make sure to exclude systemdatabases
--and ''?'' <> ''MIS_MTA''
begin
--select script that to be executed over multiple databases
select distinct
c.name,
c.identificationNo as numeric,
d.table_catalog
from [?].dbo.clients as c , [?].INFORMATION_SCHEMA.COLUMNS as d
where 1=1
and isnumeric(c.identificationNo) = 1
end;
';
select * from #results
where
isnumeric(clientnr) = 1
order by 2
;
example result:
name clientnr dbname_source
TestclientA 9000 OnsDB
TestclientA 9000 OnsDB_Fixed
Storcken 9999 OnsDB_Fixed
Storcken 9999 OnsDB