Using SELECT INTO for a multi-table query - sql

I've been using a script that a coworker showed me to query against all of our databases. It starts with CREATE TABLE #tempTable and then I need to define all the columns. I was wondering if it was possible to not define the table and use SELECT * INTO instead.
Current Query:
CREATE TABLE #tempTable(category nvarchar(50), eventType nvarchar(50), occurtime datetime);
DECLARE #fixedname nvarchar(150);
DECLARE dbCursor CURSOR FOR
SELECT REPLACE(QUOTENAME(name),'''','''''')
FROM master.sys.databases
WHERE state_desc = 'ONLINE'
AND HAS_DBACCESS(name) = 1
AND name NOT IN ('master', 'msdb','model','tempdb');
OPEN dbCursor
FETCH NEXT FROM dbCursor INTO #fixedname;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('USE ' + #fixedname + ';' +
'INSERT INTO #tempTable
SELECT
DISTINCT UserChangeEvent.category [Category],
UserChangeEvent.eventType [EventType],
UserChangeEvent.occurTime[DateTime]
FROM
UserChangeEvent
WHERE
/* User Conditions */
(
(eventType LIKE ''Alarm'')
)
AND UserChangeEvent.occurtime >= ''2021-01-01''
;');
FETCH NEXT FROM dbCursor INTO #fixedname;
END;
CLOSE dbCURSOR
DEALLOCATE dbCursor
SELECT * FROM #tempTable
--The following line can be commented out if you plan to do multiple queries within the
DROP TABLE #tempTable`
What I'm hoping might work:
DECLARE #fixedname nvarchar(150);
DECLARE dbCursor CURSOR FOR
SELECT REPLACE(QUOTENAME(name),'''','''''')
FROM master.sys.databases
WHERE state_desc = 'ONLINE'
AND HAS_DBACCESS(name) = 1
AND name NOT IN ('master', 'msdb','model','tempdb');
OPEN dbCursor
FETCH NEXT FROM dbCursor INTO #fixedname;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('USE ' + #fixedname + ';' +
'SELECT * INTO #tempTable
;');
FETCH NEXT FROM dbCursor INTO #fixedname;
END;
CLOSE dbCURSOR
DEALLOCATE dbCursor
SELECT * FROM #tempTable
WHERE
/* User Conditions */
(
(eventType LIKE ''Alarm'')
)
AND UserChangeEvent.occurtime >= ''2021-01-01''
--The following line can be commented out if you plan to do multiple queries within the
DROP TABLE #tempTable
I also read something that suggests I might not have to drop the table at the end since it's a temp table.

Related

Create an ms sql query to get data from tables belonging to different schemas

I have a table named 'tbl_user' and this table exists under many schemas for example :
schema1.tbl_user
schema2.tbl_user
and so on. I would like to union all the data in these tables and get a single result and I cannot use any programming language because the environment I need to run it doesn't allow for it. Is there a way to accomplish this on sql server 2008 using stored procedures?
Edit : There are over a thousand schemas and schemas can be added and deleted as time goes.
using cursor, create the query dynamic and execute at when completed.
You can add additional filter if you want to filter out the schema.
DECLARE #NAME VARCHAR(100)
DECLARE #SQL NVARCHAR(300)
DECLARE #TABLE_NAME NVARCHAR(300)='userMaster'
DECLARE CUR CURSOR FOR
SELECT S.name
from sys.schemas s
inner join sys.sysusers u
on u.uid = s.principal_id
order by s.name
OPEN CUR
FETCH NEXT FROM CUR INTO #NAME
WHILE ##FETCH_STATUS = 0
BEGIN
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA =#NAME
AND TABLE_NAME =#TABLE_NAME))
BEGIN
IF(LEN(#SQL)>0)
begin
SET #SQL =#SQL+' UNION ALL SELECT * FROM ['+#NAME+'].['+#TABLE_NAME+']'
end
ELSE
begin
SET #SQL ='SELECT * FROM ['+#NAME+'].['+#TABLE_NAME+']'
end
--PRINT #SQL
END
FETCH NEXT FROM CUR INTO #NAME
END
CLOSE CUR
DEALLOCATE CUR
PRINT #SQL
exec(#SQL)
Try this and remember Tables should have the same structure.
SELECT *
FROM schema1.tbl_user
UNION
SELECT *
FROM schema2.tbl_user
And for large number of schemas you can use the following stored procedure. This will generate the UNION query dynamically and you can add the conditions to filter out the schema and table names.
DECLARE #table_name NVARCHAR(100)
DECLARE #schema_name NVARCHAR(100)
DECLARE #gettable CURSOR
DECLARE #query NVARCHAR(100)
SET #query=''
SET #gettable = CURSOR FOR
SELECT name,
schema_name(schema_id)
FROM sys.tables
OPEN #gettable
FETCH NEXT
FROM #gettable INTO #table_name, #schema_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = #query + 'SELECT * FROM ' + #schema_name + '.'+ #table_name + ' UNION ';
FETCH NEXT
FROM #gettable INTO #table_name, #schema_name
END
CLOSE #gettable
DEALLOCATE #gettable
print #query;

Execute saved queries in table SQL Server

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;

Find all database tables where a common column is set to a value

All database tables have a UserId field of [uniqueidentifier] type.
I need to query the entire database and get the list of tables that have UserId set to a specific value.
Right now I achieved this by using cursor and the results are horrible and are difficult to read. How can I improve this query to retrieve back a clear list with tables and count of record that have UserId set to a specific value, instead of using this:
DECLARE #TableName VARCHAR(127);
DECLARE #Value VARCHAR(512);
DECLARE #SqlCommand varchar(1000)
--Use cursor to loop through database tables that contain UserId column
DECLARE db_cursor CURSOR FOR
SELECT t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'UserId';
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #TableName;
WHILE ##FETCH_STATUS = 0
BEGIN
--Check if the next table has any UserId matching the where clause
EXEC('SELECT COUNT(UserId) , ''' + #TableName + ''' FROM ' + #TableName + ' WHERE UserId = ''FF13ACCA-022C-4296-AB3D-A35700E35BB3''');
FETCH NEXT FROM db_cursor INTO #TableName;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
You made all the difficult part, just put the value in a temp table and select them once you've finished.
DECLARE #TableName VARCHAR(127);
DECLARE #Value VARCHAR(512);
DECLARE #SqlCommand varchar(1000)
--Creta temp table
CREATE TABLE #Results (Number int, Tablename sysname)
--Use cursor to loop through database tables that contain UserId column
DECLARE db_cursor CURSOR FOR
SELECT t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'UserId';
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #TableName;
WHILE ##FETCH_STATUS = 0
BEGIN
--Check if the next table has any UserId matching the where clause
EXEC('INSERT INTO #Results (Number, ''' + #TableName + ''') SELECT COUNT(UserId) , ''' + #TableName + ''' FROM ' + #TableName + ' WHERE UserId = ''FF13ACCA-022C-4296-AB3D-A35700E35BB3''');
FETCH NEXT FROM db_cursor INTO #TableName;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
SELECT * FROM #Results
DROP TABLE #Results
I cannot test it but this should be the way

how to check same Object Name across databases on the same server

I was trying to find duplicate object name across all databases on one server. Is there away to find all duplicate? I am using cursor to loop through the databases and I want to check if an object shows more than one and column called duplicates will be populated with Yes or No.
use the msforeachdb builtin function/proc, then insert those results into a temp table. Then query the temp table and do a groupby having count(1) > 1
create table #tables (db varchar(100) not null, name varchar(100) not null)
exec sp_msforeachdb 'use [?] insert into #tables select distinct db_name(), [name] from sys.objects where [type] = ''U'''
select name, count(1) from #tables group by name having count(1) > 1 order by 2 desc
drop table #tables
This isn't exact, but you get the idea. I'll keep tweaking until I know it's right.
Here's the cursor version:
set nocount on
SELECT name
into #dbs
FROM sys.databases
declare dbCursor cursor local forward_only for
select name from #dbs
declare #db varchar(100)
create table #tables (db varchar(100) not null, name varchar(100) not null)
open dbCursor
fetch next from dbCursor into #db
while (##fetch_status = 0) begin
begin try
exec ('use ' + #db + ' insert into #tables select distinct db_name(), [name] from sys.objects where [type] = ''U''')
print 'got ' + ##rowcount + ' from db ' + #db
end try
begin catch
print 'couldn''t retrieve data from database ' + #db
end catch
fetch next from dbCursor into #db
end
close dbCursor
deallocate dbCursor
select name, count(1) from #tables group by name having count(1) > 1 order by 2 desc
drop table #tables
drop table #dbs

How to get the row count for views from a database?

I'm trying to make a customized view that gets me the row count for all the views and tables of a database.
Getting the count of table is damn in SQL Server
SELECT TABLE_SCHEMA,
TABLE_NAME = TABLES.TABLE_NAME,
RECORD_COUNT = MAX(SYSINDEXES.ROWS)
FROM SYS.SYSINDEXES "SYSINDEXES",
INFORMATION_SCHEMA.TABLES "TABLES"
WHERE TABLES.TABLE_NAME = OBJECT_NAME(SYSINDEXES.ID)
AND TABLES.TABLE_TYPE = 'BASE TABLE'
GROUP BY TABLES.TABLE_SCHEMA,
TABLES.TABLE_NAME
Now, I need to get the rowcount for VIEWS
I feel the only way is to count the number of rows from the views
i.e. count(*) from view_name
But, I could not find a way to have the rowcount for view along with view_name, table_schema and so on.
Any advance on this would be helpful.
Well, it isn't very pretty, but this should do the trick.
This applies to a single database because I'm using the system view 'all_views' to get the data. I'm sure it could be adapted if you wanted something else.
I've also limited the views I'm returning counts for, via the 'schema_id'. You can look at this and determine what would be best for you.
Lastly, I've just spit the results out so that you can view them if you run this in Management Studio. You would probably want to insert the results into a table or something instead. If so, it's simply a matter of changing the dynamic query from a select to an insert.
So without further adieu:
SET NOCOUNT ON
DECLARE #ViewName AS nVarChar(128)
, #Query AS nVarChar(500)
/* Declare Cursor */
DECLARE Cur_Views CURSOR
FOR
SELECT name
FROM [sys].[all_views] x
WHERE x.schema_id = 1
-- Loop through the views.
OPEN Cur_Views
-- Fetch the first view
FETCH NEXT FROM Cur_Views
INTO #ViewName
WHILE ##Fetch_Status = 0 BEGIN
-- Set up our dynamic sql
SELECT #Query = 'SELECT COUNT(*) AS [Count] FROM ' + #ViewName
-- Print the query we're executing for debugging purposes
-- PRINT #Query
-- Execute the dynamic query
EXECUTE(#Query)
-- Fetch subsequent views
FETCH NEXT FROM Cur_Views
INTO #ViewName
-- Loop back to the beginning
END -- WHILE ##Fetch_Status = 0 BEGIN
-- Close the cursor
CLOSE Cur_Views
-- Dispose of the cursor
DEALLOCATE Cur_Views
GO
Here , is the final solution:
SET NOCOUNT ON
DECLARE #ViewName AS nVarChar(128)
, #TmpQuery AS nVarChar(500)
, #Out3 as int
DECLARE Cur_Views CURSOR FOR
SELECT schema_name(schema_id)+'.'+name as "Table_Name" FROM [sys].[all_views]
OPEN Cur_Views
FETCH NEXT FROM Cur_Views INTO #ViewName
WHILE ##Fetch_Status = 0 BEGIN
--SELECT #Query = 'SELECT COUNT(*) AS [Count] FROM ' + #ViewName
--EXECUTE(#Query)
CREATE TABLE #Data (var int)
SELECT #TmpQuery = 'SELECT COUNT(*) AS [Count] FROM ' + #ViewName
INSERT #Data exec (#TmpQuery)
SELECT #Out3 = var from #Data
--PRINT #ViewName
--PRINT #Out3
insert into Person.ViewCountTracker values(#ViewName,#Out3)
DROP TABLE #Data
FETCH NEXT FROM Cur_Views INTO #ViewName
END
CLOSE Cur_Views
DEALLOCATE Cur_Views
GO
--create table Person.ViewCountTracker
--(
-- ViewName varchar(255),
-- RowValue int
--)
--select * from Person.ViewCountTracker
I know this is an old post and I do not intend to take credit from the marked answer but wanted to add to it.
SELECT #Query = 'SELECT ''' + #ViewName + ''' AS Name, COUNT(*) AS [Count] FROM ' + #ViewName
I added the View name to help distinguish the numbers more.
SET NOCOUNT ON
DECLARE #ViewName AS nVarChar(128), #TmpQuery AS nVarChar(384)
CREATE TABLE #Results (Name nVarChar(128), Cnt BigInt)
DECLARE Cur_Views CURSOR FOR SELECT schema_name(schema_id) + '.' + name AS Name FROM [sys].[all_views] WHERE is_ms_shipped = 0
OPEN Cur_Views
WHILE (1=1)
BEGIN
FETCH NEXT FROM Cur_Views INTO #ViewName
If ##Fetch_Status != 0 BREAK
SELECT #TmpQuery = 'SELECT ''' + #ViewName + ''' AS Name, COUNT_BIG(*) AS Cnt FROM ' + #ViewName + ' (NoLock)'
PRINT #TmpQuery
INSERT #Results EXEC (#TmpQuery)
END
CLOSE Cur_Views
DEALLOCATE Cur_Views
SET NOCOUNT OFF
SELECT * FROM #Results
DROP TABLE #Results
GO