An introduction to sp MSforeachtable run commands iteratively through all tables in a database

An introduction to sp MSforeachtable run commands iteratively through all tables in a database

An introduction to sp_MSforeachtable run commands iteratively through all tables in a database

SQLShack

SQL Server training Español

An introduction to sp_MSforeachtable run commands iteratively through all tables in a database

August 18, 2017 by Vitor Montalvão

Introduction

There have always been some undocumented objects in SQL Server that are used internally by Microsoft, but they can be used by anybody that have access to it. One of those objects is a stored procedure called sp_MSforeachtable. sp_MSforeachtable is a stored procedure that is mostly used to apply a T-SQL command to every table, iteratively, that exists in the current database. Because official documentation from Microsoft doesn’t exist, the majority of people do not know about the existence of all of these parameters and how this stored procedure can be used to perform more than a simple operation over all the database tables. This is main purpose of this article. To provide as much information as possible for this undocumented SQL Server stored procedure so everybody can take the maximum advantage when use it.

Typical usages

From my experience, I have found in the majority of use cases, people using this stored procedure to: perform an unconditional reindex over all tables in the database: 123 EXEC sp_MSforeachtable 'DBCC DBREINDEX(''?'')' truncate all tables in the database: 123 EXEC sp_MSforeachtable 'TRUNCATE TABLE ?' get the information about the number of records from all tables in the database: 123 EXEC sp_MSforeachtable 'SELECT ''?'' TableName, Count(1) NumRecords FROM ?' I think by now you should get the idea on how to use this undocumented stored procedure and also realized that the question mark (?) it is used as the replacement of the table and during the execution it will be replaced by the appropriate table name. But the above are only the examples for the typical usage of the sp_MSforeachtable stored procedure. This stored procedure allows more parameters. If only one is passed (as the above examples) it will use by default the @command1 parameter.

sp_MSforeachtable parameters

So how to know the rest of the parameters if this is an undocumented stored procedure? We can easily find out the parameters for the sp_MSforeachtable stored procedure by searching for it in the SQL Server Management Studio (SSMS). In SSMS, drill down to “Databases / System Databases / master / Programmability / Stored Procedures / System Stored Procedures” and look for sys.sp_MSforeachtable’s parameters: @command1, @command2, @command3
sp_MSforeachtable stored procedure requires at least one command to be executed (@command1) but it allows up to 3 commands to be executed. Note that it will start to execute first the @command1 and then @command2 and @command3 by the last and this for each table. @precommand
Use this parameter to provide a command to be executed before the @command1. It is useful to set variable environments or perform any kind of initialization. @postcommand
Use this parameter to provide a command to be executed after all the commands being executed successfully. It is useful for control and cleanup processes. @replacechar
By default, a table is represented by the question mark (?) character. This parameter allows you to change this character. @whereand
By default, sp_MSforeachtable is applied to all user tables in the database. Use this parameter to filter the tables that you want to work with. On the next section, I will explain how you can filter the tables.

sp_MSforeachtable definition

For a better understanding of the sp_MSforeachtable stored procedure let see it’s code. To get this stored procedure code, in SSMS right-click on the stored procedure name and choose the Modify option. This will create a new query window with the respective stored procedure code: 12345678910111213141516171819202122232425262728293031323334353637383940414243 USE [master]GO/****** Object: StoredProcedure [sys].[sp_MSforeachtable] Script Date: 8/18/2017 8:47:44 AM ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER OFFGO ALTER proc [sys].[sp_MSforeachtable] @command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null, @command3 nvarchar(2000) = null, @whereand nvarchar(2000) = null, @precommand nvarchar(2000) = null, @postcommand nvarchar(2000) = nullas /* This proc returns one or more rows for each table (optionally, matching @where), with each table defaulting to its own result set */ /* @precommand and @postcommand may be used to force a single result set via a temp table. */ /* Preprocessor won't replace within quotes so have to use str(). */ declare @mscat nvarchar(12) select @mscat = ltrim(str(convert(int, 0x0002))) if (@precommand is not null) exec(@precommand) /* Create the select */ exec(N'declare hCForEachTable cursor global for select ''['' + REPLACE(schema_name(syso.schema_id), N'']'', N'']]'') + '']'' + ''.'' + ''['' + REPLACE(object_name(o.id), N'']'', N'']]'') + '']'' from dbo.sysobjects o join sys.all_objects syso on o.id = syso.object_id ' + N' where OBJECTPROPERTY(o.id, N''IsUserTable'') = 1 ' + N' and o.category & ' + @mscat + N' = 0 ' + @whereand) declare @retval int select @retval = @@error if (@retval = 0) exec @retval = sys.sp_MSforeach_worker @command1, @replacechar, @command2, @command3, 0 if (@retval = 0 and @postcommand is not null) exec(@postcommand) return @retval You can see now the full code of this undocumented stored procedure. In the header, you can confirm the existence of the parameters referred in the previous section. You can also see that this procedure uses a Cursor (N’declare hCForEachTable cursor global) to go through all user tables (where OBJECTPROPERTY(o.id, N”IsUserTable”) = 1) in the current database. Plus, at the end it concatenates the select statement with whatever we pass in the @whereand parameter. Looking at the code, it joins dbo.sysobjects with sys.all_objects (from dbo.sysobjects o join sys.all_objects syso) so we just need to work from here.

Full example

Now that we have the sp_MSforeachtable stored procedure definition let’s practice with an example so we can try to cover all parameters. The AdventureWorks database has a HumanResources schema so I am using this database for this example. Imagine that our Human Resources department requested us to check the database growth because they are facing some kind of disk free space issue and want to determine which table or tables are growing more than expected. As can be seen in the solution I am presenting below, the @whereand parameter is used to filter only the tables that belong to HumanResources schema. As explained before, the code that is passed in this parameter is concatenated to the SELECT query that will be used by the cursor definition in the sp_MSforeachtable stored procedure so we are using it to filter the HumanResources schema. I am using the @precommand parameter to create a global temporary table called ##Statistics to store the information that will be need to be shown at the end. This global temporary table will be dropped at the end as it can be seen in the @postcommand parameter after returning the required data (the SELECT statement just before the DROP statement). So, for each table in that belongs to HumanResources schema it will be applied the code in @command1 and @command2 parameters. As explained before, these parameters are used sequentially, i.e. it will first execute @command1 and after this one finish it will execute @command2. If @command3 parameter exists, it will be executed after @command2 finish. And this is why I have an INSERT statement in @command1 parameter and an UPDATE statement in @command2 parameter, since it is expected that the row already exists when @command2 is executed so we will not insert again the row but update it instead. Follow is the code that you can test. Feel free to change it to perform other kind of tests that can be useful for you: 1234567891011121314151617181920212223242526 USE AdventureworksGO exec sp_MSforeachtable @precommand = 'CREATE TABLE ##Statistics (TableName varchar(128) NOT NULL, NumOfRows int, SpaceUsed float)',@command1='INSERT INTO ##Statistics (TableName, NumOfRows) SELECT ''?'' TableName, COUNT(1) NumOfRows FROM ?',@command2='UPDATE S SET s.SpaceUsed = g.SizeKB FROM ##Statistics s INNER JOIN (SELECT p.object_id TableID, sum(a.total_pages) * 8192 / 1024.0 SizeKB FROM sys.partitions p INNER JOIN sys.allocation_units a on p.partition_id = a.container_id GROUP BY p.object_id) g ON OBJECT_ID(s.TableName) = g.TableID WHERE s.TableName = ''?''',@postcommand = 'SELECT TableName, NumOfRows, SpaceUsed FROM ##Statistics ORDER BY SpaceUsed DESC, NumOfRows DESC; DROP TABLE ##Statistics',@whereand='AND schema_name(schema_id) = ''HumanResources''' For the example above you will get a similar output as below: NOTE: The solution could be simpler by using the sp_spaceused but I preferred the above solution to better show how to work with more than a command parameter.

Disclaimer

Microsoft does not recommend the usage of the undocumented objects because they do not offer any support for these kinds of objects as they may be changed or dropped in future SQL Server releases without any previous warning. From my own experience, these undocumented objects have been not experienced any changes in the past so if you want to use them, remember to perform tests with those objects in any new SQL Server version that will be released in the future to assure the correct operation of your code. Author Recent Posts Vitor MontalvãoVitor Montalvão is a senior SQL Server Engineer with more than 20 years of experience working with SQL Server.

He participates in some SQL Server forums, helping other professionals solving SQL Server issues and acting as their mentor whenever is possible.

Vitor also has a website with some useful information about SQL Server: https://f1-sqlserver.wixsite.com/f1-sqlserver

View all posts by Vitor Montalvão Latest posts by Vitor Montalvão (see all) An introduction to sp_MSforeachtable run commands iteratively through all tables in a database - August 18, 2017 SQL Server system databases – the model database - August 9, 2017 SQL Server system databases – the msdb database - July 14, 2017

Related posts

Using Memory-Optimized Tables to Replace SQL Temp Tables and Table Variables The tempdb database, introduction and recommendations Dynamic SQL in SQL Server The SQL Server system views/tables/functions. Common questions and solutions to real life problems DBATools PowerShell SQL Server Database Backups commands 77,054 Views

Follow us

Popular

SQL Convert Date functions and formats SQL Variables: Basics and usage SQL PARTITION BY Clause overview Different ways to SQL delete duplicate rows from a SQL Table How to UPDATE from a SELECT statement in SQL Server SQL Server functions for converting a String to a Date SELECT INTO TEMP TABLE statement in SQL Server SQL WHILE loop with simple examples How to backup and restore MySQL databases using the mysqldump command CASE statement in SQL Overview of SQL RANK functions Understanding the SQL MERGE statement INSERT INTO SELECT statement overview and examples SQL multiple joins for beginners with examples Understanding the SQL Decimal data type DELETE CASCADE and UPDATE CASCADE in SQL Server foreign key SQL Not Equal Operator introduction and examples SQL CROSS JOIN with examples The Table Variable in SQL Server SQL Server table hints – WITH (NOLOCK) best practices

Trending

SQL Server Transaction Log Backup, Truncate and Shrink Operations Six different methods to copy tables between databases in SQL Server How to implement error handling in SQL Server Working with the SQL Server command line (sqlcmd) Methods to avoid the SQL divide by zero error Query optimization techniques in SQL Server: tips and tricks How to create and configure a linked server in SQL Server Management Studio SQL replace: How to replace ASCII special characters in SQL Server How to identify slow running queries in SQL Server SQL varchar data type deep dive How to implement array-like functionality in SQL Server All about locking in SQL Server SQL Server stored procedures for beginners Database table partitioning in SQL Server How to drop temp tables in SQL Server How to determine free space and file size for SQL Server databases Using PowerShell to split a string into an array KILL SPID command in SQL Server How to install SQL Server Express edition SQL Union overview, usage and examples

Solutions

Read a SQL Server transaction logSQL Server database auditing techniquesHow to recover SQL Server data from accidental UPDATE and DELETE operationsHow to quickly search for SQL database data and objectsSynchronize SQL Server databases in different remote sourcesRecover SQL data from a dropped table without backupsHow to restore specific table(s) from a SQL Server database backupRecover deleted SQL data from transaction logsHow to recover SQL Server data from accidental updates without backupsAutomatically compare and synchronize SQL Server dataOpen LDF file and view LDF file contentQuickly convert SQL code to language-specific client codeHow to recover a single table from a SQL Server database backupRecover data lost due to a TRUNCATE operation without backupsHow to recover SQL Server data from accidental DELETE, TRUNCATE and DROP operationsReverting your SQL Server database back to a specific point in timeHow to create SSIS package documentationMigrate a SQL Server database to a newer version of SQL ServerHow to restore a SQL Server database backup to an older version of SQL Server

Categories and tips

►Auditing and compliance (50) Auditing (40) Data classification (1) Data masking (9) Azure (295) Azure Data Studio (46) Backup and restore (108) ►Business Intelligence (482) Analysis Services (SSAS) (47) Biml (10) Data Mining (14) Data Quality Services (4) Data Tools (SSDT) (13) Data Warehouse (16) Excel (20) General (39) Integration Services (SSIS) (125) Master Data Services (6) OLAP cube (15) PowerBI (95) Reporting Services (SSRS) (67) Data science (21) ►Database design (233) Clustering (16) Common Table Expressions (CTE) (11) Concurrency (1) Constraints (8) Data types (11) FILESTREAM (22) General database design (104) Partitioning (13) Relationships and dependencies (12) Temporal tables (12) Views (16) ►Database development (418) Comparison (4) Continuous delivery (CD) (5) Continuous integration (CI) (11) Development (146) Functions (106) Hyper-V (1) Search (10) Source Control (15) SQL unit testing (23) Stored procedures (34) String Concatenation (2) Synonyms (1) Team Explorer (2) Testing (35) Visual Studio (14) DBAtools (35) DevOps (23) DevSecOps (2) Documentation (22) ETL (76) ►Features (213) Adaptive query processing (11) Bulk insert (16) Database mail (10) DBCC (7) Experimentation Assistant (DEA) (3) High Availability (36) Query store (10) Replication (40) Transaction log (59) Transparent Data Encryption (TDE) (21) Importing, exporting (51) Installation, setup and configuration (121) Jobs (42) ▼Languages and coding (686) Cursors (9) DDL (9) DML (6) JSON (17) PowerShell (77) Python (37) R (16) SQL commands (196) SQLCMD (7) String functions (21) T-SQL (275) XML (15) Lists (12) Machine learning (37) Maintenance (99) Migration (50) Miscellaneous (1) ►Performance tuning (869) Alerting (8) Always On Availability Groups (82) Buffer Pool Extension (BPE) (9) Columnstore index (9) Deadlocks (16) Execution plans (125) In-Memory OLTP (22) Indexes (79) Latches (5) Locking (10) Monitoring (100) Performance (196) Performance counters (28) Performance Testing (9) Query analysis (121) Reports (20) SSAS monitoring (3) SSIS monitoring (10) SSRS monitoring (4) Wait types (11) ►Professional development (68) Professional development (27) Project management (9) SQL interview questions (32) Recovery (33) Security (84) Server management (24) SQL Azure (271) SQL Server Management Studio (SSMS) (90) SQL Server on Linux (21) ►SQL Server versions (177) SQL Server 2012 (6) SQL Server 2016 (63) SQL Server 2017 (49) SQL Server 2019 (57) SQL Server 2022 (2) ►Technologies (334) AWS (45) AWS RDS (56) Azure Cosmos DB (28) Containers (12) Docker (9) Graph database (13) Kerberos (2) Kubernetes (1) Linux (44) LocalDB (2) MySQL (49) Oracle (10) PolyBase (10) PostgreSQL (36) SharePoint (4) Ubuntu (13) Uncategorized (4) Utilities (21) Helpers and best practices BI performance counters SQL code smells rules SQL Server wait types © 2022 Quest Software Inc. ALL RIGHTS RESERVED. GDPR Terms of Use Privacy
Share:
0 comments

Comments (0)

Leave a Comment

Minimum 10 characters required

* All fields are required. Comments are moderated before appearing.

No comments yet. Be the first to comment!

An introduction to sp MSforeachtable run commands iteratively through all tables in a database | Trend Now