Reputation: 1200
We have a piece of software that does not delete entries we no longer want. In order to get a feel for how much data is wasting away in our server and prepare for a big cleanup operation, I am trying to loop through all of the tables and pull the records that are marked for deletion. This is what I'm working with:
DECLARE @total INT
DECLARE @count INT
DECLARE @name NVARCHAR(25)
DECLARE @rn INT
SET @total = (SELECT COUNT(Name) FROM sys.tables)
SET @count = 1
SET @rn = (SELECT ROW_NUMBER() OVER(ORDER BY Name) FROM sys.tables)
WHILE @count <= @total AND @count < 2
BEGIN
SET @name = ( SELECT Name, ROW_NUMBER() OVER(ORDER BY Name)
FROM sys.tables
WHERE @rn = @count
)
EXEC('SELECT * FROM WS_Live.dbo.' + @name + ' WHERE GCRecord IS NOT NULL')
SET @count += 1
END
This is my error:
Msg 116, Level 16, State 1, Line 19 Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I realize that my error probably has to do with selecting two columns in the line
SET @name = ( SELECT Name, ROW_NUMBER() OVER(ORDER BY Name)
FROM sys.tables
WHERE @rn = @count
)
but, I'm not sure how else to ensure that I am selecting the next row.
P.S. AND @count <2
is just for script testing.
How can I loop through all of the tables?
Upvotes: 23
Views: 89295
Reputation: 1
To get all tables in the database:
CREATE TABLE #Results (TableName nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256)
SET @TableName = ''
WHILE @TableName IS NOT NULL
BEGIN
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)
insert #Results values (@TableName)
END
SELECT TableName
FROM #Results
drop table #Results;
Upvotes: 0
Reputation: 12959
You can generate the script as given below using Concatenation. Then execute the script.
DECLARE @sqlStmt NVARCHAR(MAX) = ''
SELECT @sqlStmt= CONCAT('SELECT COUNT(*) AS CountOfRows,''',name,''' AS TableName FROM ',name,';',CHAR(13), CHAR(10)) FROM sys.tables
--SELECT @sqlstmt
EXEC(@sqlStmt)
Upvotes: 0
Reputation: 2481
Use this system stored procedure
sp_MSforeachtable @command1="select count(*) from ?"
Note:
sp_MSforeachtable
is an undocumented stored procedure. Upvotes: 41
Reputation: 1619
Some times using Cursor in the SQL is Risk. Below SQL query will traverse through all the tables in a selected data base without using CURSOR.
USE TEST
Declare @TableName nvarchar(256)
SET @TableName = ''
WHILE @TableName IS NOT NULL
BEGIN
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
)
print @TableName -- Your logic will come here
END
GO
Above sql statements will print all the tables in side the TEST database. So instead of print table statement you can give your own sql logic like what you want to do with looping each table and @TableName will contain the table name in the present loop.
Upvotes: 6
Reputation: 93694
Maybe this is what you are looking for
DECLARE @NAME VARCHAR(100)
DECLARE @SQL NVARCHAR(300)
DECLARE CUR CURSOR FOR
SELECT NAME
FROM SYS.TABLES
WHERE TYPE = 'U'
AND SCHEMA_ID = 1
OPEN CUR
FETCH NEXT FROM CUR INTO @NAME
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = 'SELECT * FROM WS_LIVE.DBO.'+@NAME+' WHERE GCRECORD IS NOT NULL'
PRINT @SQL
EXEC Sp_executesql
@SQL
FETCH NEXT FROM CUR INTO @NAME
END
CLOSE CUR
DEALLOCATE CUR
Upvotes: 25