Fetch data without using union all every month - sql

Select * from [dbo].[TRNS0119]
union all
Select * from [dbo].[TRNS0219]
union all
Select * from [dbo].[TRNS0319]
union all
Select * from [dbo].[TRNS0419]
In my attendance SQL Server database, every month a new table gets created with in/out records. I have to use union all to fetch data from all 12 month's data. I want to my query to fetch data automatically when new table gets created with a particular name. I am not SA user so can not make any changes / triggers / procedures.
So far I am doing this for every month but I want to know how I can resolve this without any intervention every month

for this solution, you must have same fields in your dynamic tables.
Tablename can be anything in your database, this will works for all tablenames.
Try this if you get your results.
declare #table table([Name] varchar(200))
declare #query VARCHAR(max)
declare #strQuery varchar(max) = '';
set #query='SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES';
insert into #table exec (#query)
--select * from #table (You will get all your table names)
declare #tablename varchar(100)
declare #i int=0
DECLARE curFetchData CURSOR FOR SELECT [Name] from #table
OPEN curFetchData
FETCH NEXT FROM curFetchData INTO #tablename
WHILE ##Fetch_status = 0
BEGIN
IF(#i>0)
set #strQuery = #strQuery + (' UNION ALL ')
set #strQuery = #strQuery + (' SELECT * from '+#tablename+' ')
set #i=#i+1;
FETCH NEXT FROM curFetchData INTO #tablename
END
CLOSE curFetchData
DEALLOCATE curFetchData
PRINT (#strQuery)
EXEC (#strQuery)

Try this query. Please ensure the input parameter.
DECLARE #inputYear INT,#tablename VARCHAR(20)=''
SET #inputYear =2019---- year(getdate())
DECLARE #v nvarchar(30)='TRNS%'+right(convert(varchar(4),#inputyear),2)
DECLARE #query nvarchar(max)=''
SELECT #query=#query+' UNION ALL SELECT * FROM ' + NAME from sys.tables where name like #v
SELECT #query= STUFF(#query,1,10,'')
EXECUTE sp_executesql #query

Related

How to retrieve a column name from a table that is stored as a value in another table

I'm pretty new to sql so any help will be much appreciated
I have a table containing a list of table names in a column of a table and I need to retrieve a column called [Last Refreshed] from all the tables listed. The tables all have different structures but they all have the [Last Refreshed] Column. I have managed to insert the tablenames into a sql variable but up to this point I am kind of stuck.
I hope I managed to explain what I need but I have attached my code as well.
Declare #tables nvarchar(max)
Declare #sql nvarchar(max)
Declare #cnt int
DECLARE #Counter int
SET #Counter = 1
DECLARE #RowCount INT
SET #RowCount = (SELECT COUNT(*)
FROM (
SELECT * FROM TABLE_LIST1
UNION
SELECT * FROM TABLE_LIST2) data )
DROP TABLE #DB_DUMMY
CREATE TABLE #DB_DUMMY (
[TABLENAME] VARCHAR(512),
[LAST_REFRESHED] VARCHAR(533)
);
WHILE ( #Counter <= #RowCount)
BEGIN
SELECT #tables = FinalTable, #cnt = Row_num from (
SELECT FinalTable , ROW_NUMBER() OVER(ORDER BY FinalTable DESC) AS Row_num
FROM (
SELECT FinalTable FROM TABLE_LIST1
UNION
SELECT FinalTable FROM ABLE_LIST2) data
group by FinalTable) a
where Row_num = #Counter
--This part doesnt work
INSERT INTO #DB_DUMMY(TABLENAME,LAST_REFRESHED)
SELECT #tables , [Last Refreshed] from #tables
SET #Counter = #Counter + 1
END
exec(#sql)
I expect to see a list of tablenames as well as the last refresh in the temporary table #DB_DUMMY
i add the [Last Refreshed] column to my tables and write this query and give me the correct answer
DROP TABLE IF EXISTS #DB_DUMMY
CREATE TABLE #DB_DUMMY (
[TABLENAME] VARCHAR(512),
[LAST_REFRESHED] VARCHAR(533)
);
DECLARE #COMMAND NVARCHAR(MAX)
SELECT #COMMAND = STRING_AGG(' INSERT INTO #DB_DUMMY SELECT DISTINCT '+CHAR(39)+T.name+CHAR(39)+',['+C.name+'] FROM '+S.name+'.'+T.name + ' GO', CHAR(13)+CHAR(10))
FROM sys.all_columns C
INNER JOIN sys.tables T ON C.object_id = T.object_id
INNER JOIN sys.schemas S ON T.schema_id = S.schema_id
WHERE C.name = 'Last Refreshed'
PRINT(#COMMAND)
EXEC(#COMMAND)
SELECT * FROM #DB_DUMMY
two first line with IF EXISTS is new syntax in sql server 2017
Just a suggestion You could use a INSERT SELECT
INSERT INTO #DB_DUMMY(TABLENAME,LAST_REFRESHED)
SELECT 'TABLE_LIST1', LAST_REFRESHED
FROM TABLE_LIST1
UNION ALL
SELECT 'TABLE_LIST2', LAST_REFRESHED
FROM TABLE_LIST2
UNION ALL
.....
SELECT 'TABLE_LISTN', LAST_REFRESHED
FROM TABLE_LISTN
Try something like this:
declare cur cursor for Select TableName From TABLE_LIST
declare #tablename nvarchar(max)
declare #sqlstring nvarchar(max)
open cur
fetch next from cur into #tablename
while ##fetch_status=0
begin
set #sqlstring = 'SELECT ''' + #tablename + ''' AS ''TABLE'', [LAST_REFRESHED] FROM ' + #tablename
exec sp_executesql #sqlstring
fetch next from cur into #tablename
end
close cur
deallocate cur
;
It is the weekend and I don't have access to a database to test on, so it may need some adjusting. Here is a fiddle with the sample code, but it only returns the first table http://sqlfiddle.com/#!18/a5b55b/2 (I think the fiddle execution mechanism interferes with the cursor.)
This answer is based upon the code here: I have the same column in multiple tables, and want to update that column in all tables to a specific value. How can I do this?
Note that there is no need to maintain a list of tables with the column. You can generate it dynamically from INFORMATION_SCHEMA.COLUMNS
Another possible approach is to generate and execute a dynamic statement (it's not possible to use a variable for the name of a column or a table):
Table:
CREATE TABLE #TableNames (
[TableName] nvarchar(128)
)
INSERT INTO #TableNames
([TableName])
VALUES
(N'Table1'),
(N'Table2'),
(N'Table3'),
(N'Table4'),
(N'Table5')
Statement:
-- Generate statement
DECLARE #stm nvarchar(max) = N''
SELECT #stm = CONCAT(
#stm,
N'INSERT INTO #DB_DUMMY (TABLENAME, LAST_REFRESHED) ',
N'SELECT ''',
[TableName],
N''' AS [TableName], [LastRefreshed] FROM ',
QUOTENAME([TableName]),
N'; '
)
FROM #TableNames
-- Execute statement
PRINT #stm
EXEC sp_executesql #stm

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.

How to store a dynamic SQL result in a variable in T-SQL?

I have a stored procedure which takes 'table name' as parameter. I want to store my 'exec' results to a variable and display using that variable.
Here is my T-SQL stored procedure..
create procedure DisplayTable( #tab varchar(30))
as
begin
Declare #Query VARCHAR(30)
set #Query='select * from ' +#tab
EXEC (#Query)
END
I want to do something like this..
SET #QueryResult = EXEC (#Query)
select #QueryResult
How do i achieve this.. Please help.. I am a beginner..
You can use XML for that. Just add e.g. "FOR XML AUTO" at the end of your SELECT. It's not tabular format, but at least it fulfills your requirement, and allows you to query and even update the result. XML support in SQL Server is very strong, just make yourself acquainted with the topic. You can start here: http://technet.microsoft.com/en-us/library/ms178107.aspx
alter procedure DisplayTable(
#tab varchar(30)
,#query varchar(max) output
)
as
BEGIN
Declare #execution varchar(max) = 'select * from ' +#tab
declare #tempStructure as table (
pk_id int identity
,ColumnName varchar(max)
,ColumnDataType varchar(max)
)
insert into
#tempStructure
select
COLUMN_NAME
,DATA_TYPE
from
INFORMATION_SCHEMA.columns
where TABLE_NAME= #tab
EXEC(#execution)
declare #ColumnCount int = (SELECT count(*) from #tempStructure)
declare #counter int = 1
while #counter <= #ColumnCount
BEGIN
IF #counter = 1
BEGIN
set #query = (SELECT ColumnName + ' ' + ColumnDataType FROM #tempStructure where pk_id= #counter)
END
IF #counter <> 1
BEGIN
set #query = #query + (SELECT ',' + ColumnName + ' ' + ColumnDataType FROM #tempStructure where #counter = pk_id)
END
set #counter = #counter + 1
END
END
When you execute the SP, you'll now get a return of the structure of the table you want.
This should hopefully get you moving.
If you want the table CONTENTS included, create yourself a loop for the entries, and append them to the #query parameter.
Remember to delimit the #query, else when you read it later on, you will not be able to restructure your table.
First of all you have to understand that you can't just store the value of a SELECTon a table in simple variable. It has to be TABLE variable which can store the value of a SELECTquery.
Try the below:
select 'name1' name, 12 age
into MyTable
union select 'name2', 15 union
select 'name3', 19
--declaring the table variable and selecting out of it..
declare #QueryResult table(name varchar(30), age int)
insert #QueryResult exec DisplayTable 'MyTable'
select * from #QueryResult
Hope this helps!

Why isn't the table being created from within the stored procedure?

I am creating stored procedure in which I need to build a temporary table dynamically. I tried the following code but its not creating table. When I execute the generated Query in Query window it works fine there.
--declare query variable
DECLARE #Query nvarchar(MAX)
SET #Query = 'CREATE TABLE #final (DATE int,'
--DECLARE #COLUMNNAME VARIABLE
DECLARE #ColName nvarchar(10)
OPEN #taCur
FETCH NEXT FROM #taCur INTO #ColName
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #Query = #Query + 'T_' + #ColName +' int,'
FETCH NEXT FROM #taCur INTO #ColName
END
SET #Query = #Query + 'TOTAL int,CUMM_TOTAL int)'
print #Query
EXEC sp_executesql #Query
--SET #Query = 'INSERT INTO #final (DATE) VALUES (1)'
SET #Query = 'SELECT * FROM #final'
print #Query
EXEC(#Query)
Final generated create table Query is as follow
CREATE TABLE #final (DATE int,T_211E int,T_211G int,T_211H int,T_211J int,T_211L int,T_221F int,TOTAL int,CUMM_TOTAL int)
Object #final used in CREATE and SELECT statements is not in the same scope.
Here is one way to structure the query.
Try to terminate SQL statements with semicolon. Even though it is not mandatory, it will help you differentiate the statements for readability. Note that I have included semicolon at the end of CREATE, INSERT and SELECT statements.
You can notice that CREATE, INSERT and SELECT are executed in the same transaction. Thereby, you don't lose the scope of the temporary table.
Script:
CREATE TABLE dbo.ColumnSchema
(
ColName NVARCHAR(10)
);
INSERT INTO dbo.ColumnSchema (ColName) VALUES
('211E'),
('211G'),
('211H'),
('211J'),
('211L'),
('211F');
DECLARE #Query NVARCHAR(MAX);
DECLARE #ColName NVARCHAR(10);
SET #Query = 'CREATE TABLE #final (DATE int,';
DECLARE taCursor CURSOR FOR
SELECT ColName
FROM dbo.ColumnSchema;
OPEN taCursor
FETCH NEXT FROM taCursor
INTO #ColName
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #Query = #Query + 'T_' + #ColName + ' int, '
FETCH NEXT FROM taCursor
INTO #ColName
END
CLOSE taCursor;
DEALLOCATE taCursor;
SET #Query = #Query + 'TOTAL int,CUMM_TOTAL int); '
SET #Query = #Query + 'INSERT INTO #final (DATE) VALUES (1); '
SET #Query = #Query + 'SELECT * FROM #final; '
EXEC (#Query);
Output:
DATE T_211E T_211G T_211H T_211J T_211L T_211F TOTAL CUMM_TOTAL
---- ------ ------ ------ ------ ------ ------ ----- ----------
1 NULL NULL NULL NULL NULL NULL NULL NULL
Your problem is that your temp table only exists within the scope that it is created... which is within the scope of your first sp_executesql. When you call your select statement, your temp table is no longer in scope.
To fix this, you would have to build up a single string that contains everything you need to do with your temp table: your create, insert, and select all within the a single sp_executesql call.
However, you should be aware that your current approach is likely vulnerable to SQL injection if you don't have complete control over all the values that are used to build up your commands.

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