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

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

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'

Fetch data without using union all every month

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

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;

INSERT INTO command doesn't work

I have one outer cursor and one inner cursor also have two tables to work with. Now with the outer cursor i'm making new columns in the table 1 and naming them by the values from the table two, and that works just fine. Problem is with the inner cursor witch i used to insert the values into those new columns from one specific column from another table. This seams not to work, but what confusing me is that i do not get any error messages. Now i hope you understand what i'm trying to do, here is the code so comment for more description about the problem :
DECLARE #rbr_param nvarchar(255)
DECLARE #vrednost nvarchar(255)
DECLARE #cName nvarchar(255)
DECLARE #sql nvarchar (255)
DECLARE curs CURSOR FOR SELECT DISTINCT rbr_param FROM dbo.parametri_pomocna ORDER BY rbr_param
OPEN curs
FETCH NEXT FROM curs
INTO #rbr_param
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cName = 'P_'+#rbr_param+'_P'
EXEC('ALTER TABLE dbo.Parametri ADD ' + #cName + ' nvarchar(255)')
DECLARE vrd CURSOR FOR SELECT DISTINCT vrednost FROM dbo.parametri_pomocna
OPEN vrd
FETCH NEXT FROM vrd
INTO #vrednost
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'INSERT INTO dbo.Parametri'+(#cName)+ ' SELECT vrednost FROM dbo.parametri_pomocna WHERE vrednost = '+#vrednost+ ' AND rbr_param = '+#rbr_param
if exists (select * from INFORMATION_SCHEMA.COLUMNS where table_name = 'dbo.Parametri' and column_name = '#cName')
begin
exec(#sql)
end
FETCH NEXT FROM vrd
INTO #vrednost
END --end vrd
CLOSE vrd
DEALLOCATE vrd
FETCH NEXT FROM curs
INTO #rbr_param
END
CLOSE curs
DEALLOCATE curs
You have two problems here:
if exists ( select * from INFORMATION_SCHEMA.COLUMNS
where table_name = 'dbo.Parametri'
and column_name = '#cName'
)
(1) This view will never have table_name = schema name and table name.
(2) You have enclosed your variable name in single quotes for some reason.
For both of these reasons, your IF condition will never return true.
Try:
IF EXISTS
(
SELECT 1 FROM sys.columns
WHERE [object_id] = OBJECT_ID('dbo.Parametri')
AND name = #cName
)
(And here is why I prefer catalog views over INFORMATION_SCHEMA.)
Also this double-nested cursor thing seems quite inefficient and a lot more code than necessary to achieve what I think you're trying to do. How about something like this instead:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'ALTER TABLE dbo.Parametri ADD '
+ QUOTENAME('P_' + rbr_param + '_P') + ' NVARCHAR(255);'
FROM dbo.parametri_pomocna GROUP BY rbr_param;
EXEC sp_executesql #sql;
SET #sql = N'';
SELECT #sql = #sql + N'INSERT dbo.Parametri('+QUOTENAME('P_' + rbr_param + '_P')+ ')
SELECT vrednost
FROM dbo.parametri_pomocna WHERE rbr_param = ''' + rbr_param + '''
GROUP BY vrednost;'
FROM dbo.parametri_pomocna
GROUP BY rbr_param;
EXEC sp_executesql #sql;

How to execute a stored procedure inside a select query

SELECT col1,
col2,
col3,
EXEC GetAIntFromStoredProc(T.col1) AS col4
FROM Tbl AS T
WHERE (col2 = #parm)
How to write this SQL query in SQL Server 2008?
Thanks #twoleggedhorse.
Here is the solution.
First we created a function
CREATE FUNCTION GetAIntFromStoredProc(#parm Nvarchar(50)) RETURNS INTEGER
AS
BEGIN
DECLARE #id INTEGER
set #id= (select TOP(1) id From tbl where col=#parm)
RETURN #id
END
then we do the select query
Select col1, col2, col3,
GetAIntFromStoredProc(T.col1) As col4
From Tbl as T
Where col2=#parm
Functions are easy to call inside a select loop, but they don't let you run inserts, updates, deletes, etc. They are only useful for query operations. You need a stored procedure to manipulate the data.
So, the real answer to this question is that you must iterate through the results of a select statement via a "cursor" and call the procedure from within that loop. Here's an example:
DECLARE #myId int;
DECLARE #myName nvarchar(60);
DECLARE myCursor CURSOR FORWARD_ONLY FOR
SELECT Id, Name FROM SomeTable;
OPEN myCursor;
FETCH NEXT FROM myCursor INTO #myId, #myName;
WHILE ##FETCH_STATUS = 0 BEGIN
EXECUTE dbo.myCustomProcedure #myId, #myName;
FETCH NEXT FROM myCursor INTO #myId, #myName;
END;
CLOSE myCursor;
DEALLOCATE myCursor;
Note that ##FETCH_STATUS is a standard variable which gets updated for you. The rest of the object names here are custom.
You can create a temp table matching your proc output and insert into it.
CREATE TABLE #Temp (
Col1 INT
)
INSERT INTO #Temp
EXEC MyProc
As long as you're not doing any INSERT or UPDATE statements in your stored procedure, you will probably want to make it a function.
Stored procedures are for executing by an outside program, or on a timed interval.
The answers here will explain it better than I can:
Function vs. Stored Procedure in SQL Server
"Not Possible".
You can use a function instead of the stored procedure.
"Not Possible". You can do this using this query.
Initialize here
declare #sql nvarchar(4000)=''
Set Value & exec command of your sp with parameters
SET #sql += ' Exec spName #param'
EXECUTE sp_executesql #sql, N'#param type', #param = #param
Don't forget, if you just want to use the SP as a one-off query real quick to check something, all you have to do is pull the innards of the SP out and paste it in a new query window and do whatever you like at that point because it is no longer a SP.
Create a dynamic view and get result from it.......
CREATE PROCEDURE dbo.usp_userwise_columns_value
(
#userid BIGINT
)
AS
BEGIN
DECLARE #maincmd NVARCHAR(max);
DECLARE #columnlist NVARCHAR(max);
DECLARE #columnname VARCHAR(150);
DECLARE #nickname VARCHAR(50);
SET #maincmd = '';
SET #columnname = '';
SET #columnlist = '';
SET #nickname = '';
DECLARE CUR_COLUMNLIST CURSOR FAST_FORWARD
FOR
SELECT columnname , nickname
FROM dbo.v_userwise_columns
WHERE userid = #userid
OPEN CUR_COLUMNLIST
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #columnlist = #columnlist + #columnname + ','
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
END
CLOSE CUR_COLUMNLIST
DEALLOCATE CUR_COLUMNLIST
IF NOT EXISTS (SELECT * FROM sys.views WHERE name = 'v_userwise_columns_value')
BEGIN
SET #maincmd = 'CREATE VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
ELSE
BEGIN
SET #maincmd = 'ALTER VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
EXECUTE sp_executesql #maincmd
END
-----------------------------------------------
SELECT * FROM dbo.v_userwise_columns_value