Object & help system procedures

Status: Reviewed
Stack: PowerShell → SQL / stored procs → Blazor
Depends on: SQL-CLI-09 (overview), SQL-CLI-01 (calling), SQL-CLI-07 (pipeline shapes)
Goal: Know when to use sp_help* / sp_spaceused / sp_helptext / sp_rename vs catalog views/DMVs for inventory and ops scripts feeding Blazor.

Sources: Microsoft Learn (sql-server-ver17 / 2026). Expands SQL-CLI-09 §3.2 (database/objects) only — do not treat this as a rewrite of the overview. Calling: SQL-CLI-01. Staging → Blazor: SQL-CLI-07.


1. Scope map

In this doc (09b) Out → sibling
sp_help, sp_helpdb, sp_helpfile, sp_helpfilegroup Config / sp_configure / who → 09a
sp_helpindex, ODBC catalog procs (sp_columns, sp_tables, …) Security / principals / orphans → 09c
sp_helptext, encrypted-module caveat Agent (msdb help/start/history) → 09d
sp_spaceused (+ @updateusage / @oneresultset) Surface area / xp_*09e
sp_rename (table/column/index OK; never modules) Full call patterns / decision table → CLI-09
Deprecated deps: sp_depends / sp_MSdependencies → catalog/DMFs Pipeline shapes → CLI-07

Write path that stays a proc: sp_rename (and only for the object classes called out below).
Read path for Blazor: always catalog views / DMVs — never scrape multi-result-set sp_help* into a grid.


2. Decision: interactive help procs vs catalog for Blazor staging

Need Prefer Why
One-off peek in SSMS / sqlcmd sp_help / sp_helpindex / sp_spaceused Zero join typing; human-readable
Inventory → staging table → Blazor Catalog / DMVs One result set, typed columns, WHERE/JOIN, stable shape
Module definition into a string column sys.sql_modules / OBJECT_DEFINITION() Single nvarchar(max) — not 255-char chunks
Fleet space / row counts sys.dm_db_partition_stats (+ files via sys.master_files) Filterable; no @updateusage side effects
Rename table / column / index / constraint sp_rename Official API — then fix dependents yourself
Rename proc / view / fn / trigger DROP + CREATE (or SSDT publish) See §3.8 — definition text does not follow rename
Dependency graph for refactor sys.sql_expression_dependencies + sys.dm_sql_*_entities sp_depends deprecated; incomplete

Multi-result-set problem (why Blazor hates sp_help*)

Caller Behavior with multi-set procs
sqlcmd / go-sqlcmd Prints all sets to stdout — fine for eyeballs; ugly for -o CSV / parsers
Invoke-Sqlcmd Typically surfaces the last result set as objects — earlier sets silently dropped
ADO.NET / SqlCommand Can walk NextResult() — doable, not worth it for inventory

Rule for this stack: Collect with a single-select catalog query into dbo.*Staging (CLI-07). Use help procs only for interactive triage or rare control-plane renames.


3. Deep catalog — high-value object / help procs

Columns per proc: purpose · args · result-set quirks · permissions · prefer-instead.

3.1 sp_help

Purpose Object metadata dump: name/owner/type; for tables also columns, identity, RowGuid, filegroup, indexes, constraints, references, etc.
Args @objname = N'schema.object' or omit (list all objects in current DB)
Result quirks Many result sets — shape depends on object type. Current DB only. Exposes only orderable index columns (no XML/spatial detail).
Perms public + object visibility; constraint/detail often needs VIEW DEFINITION / ownership
Prefer instead sys.objects + sys.columns + sys.indexes + sys.index_columns + sys.key_constraints / sys.foreign_keys / sys.check_constraints + sys.types
-- Interactive only
EXEC sp_help N'dbo.MyTable';

3.2 sp_helpdb

Purpose DB size / owner / created / status string / compat; with @dbname, second set = file layout
Args @dbname or omit (all DBs)
Result quirks 1 set (all) or 2 sets (named DB). status is a comma soup — incomplete vs sys.databases. db_size is a display string. Applies to: SQL Server (on-prem / MI-class file layout); thin/absent on Azure SQL DB.
Perms public in target DB (named) or master (all)
Prefer instead sys.databases + sys.master_files (size = size * 8.0 / 1024 MB)

3.3 sp_helpfile / sp_helpfilegroup

Proc Purpose Args Quirks Prefer instead
sp_helpfile Logical/physical file attrs for current DB @filename or all Size/growth as strings; log → filegroup NULL. SQL Server–centric. sys.database_files (current) / sys.master_files (instance)
sp_helpfilegroup Filegroup list + optional file members @filegroupname or all Multi-set when named; includes FILESTREAM/memory-optimized notes in modern builds sys.filegroups + sys.database_files

Ops tip: For attach/detach planning, sp_helpfile is a fast interactive peek. For Blazor disk inventory, query sys.master_files once per instance.

3.4 sp_helpindex — and sp_helptable?

sp_helpindex

Purpose Index name / description (incl. filegroup, uniqueness, clustered) / key list for a table or view
Args @objname (required)
Result quirks One set. Descending keys marked with -. Does not expose XML/spatial indexes. Description is a free-text blob — hard to parse.
Perms public
Prefer instead sys.indexes + sys.index_columns + sys.columns (+ sys.partitions for row counts per index)

sp_helptable

Not relevant on modern SQL Server. There is no documented sp_helptable in Learn sql-server-ver17. Sybase heritage / folklore — use sp_help interactively or catalog views for scripts. Do not put it in runbooks.

3.5 ODBC-style catalog procs (brief)

These implement ODBC dictionary functions. Still present; not first-choice for Blazor staging (ODBC column names, wildcards, limited richness).

Proc ODBC cousin Typical args Prefer instead
sp_tables SQLTables @table_name, @table_owner, @table_type, @fUsePattern sys.tables / sys.views / sys.objects
sp_columns SQLColumns @table_name, @table_owner, @column_name, @ODBCVer sys.columns + sys.types
sp_pkeys SQLPrimaryKeys @table_name, @table_owner sys.key_constraints + sys.index_columns where is_primary_key = 1
sp_stored_procedures SQLProcedures @sp_name, @sp_owner, @fUsePattern sys.procedures / sys.objects (type IN ('P','PC'))
sp_fkeys, sp_statistics, … FK / index stats (see Learn Catalog stored procedures) sys.foreign_keys / sys.indexes

Worth knowing when debugging ODBC/JDBC metadata; skip for inventory scripts.

3.6 sp_helptext

Purpose Print definition of unencrypted module / rule / default / computed column / CHECK as text rows
Args @objname (required); optional @columnname for computed column on a table
Result quirks One column Text nvarchar(255) — definition chunked across rows. Must concatenate in order. Synapse: not supported → use OBJECT_DEFINITION / sys.sql_modules.
Perms public for system objects; user objects need owner or ALTER / CONTROL / TAKE OWNERSHIP / VIEW DEFINITION
Prefer instead SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID(N'schema.obj'); or OBJECT_DEFINITION(OBJECT_ID(…))

Encrypted modules caveat

Situation What you get
WITH ENCRYPTION proc/view/fn/trigger sp_helptext → message that it is encrypted; sys.sql_modules.definition = NULL; OBJECT_DEFINITION = NULL
CLR modules No T-SQL text in sql_modules the same way — assembly lives elsewhere
System procs Definitions often visible via sp_helptext / modules (implementation detail; don’t rely on editing them)

Ops rule: Inventory “do we have the source?” with definition IS NULL on sys.sql_modules joined to sys.objects — not by scraping sp_helptext errors.

3.7 sp_spaceused

Purpose Rows + reserved/data/index/unused for a table/indexed view/queue, or whole-DB space summary
Args @objname; @updateusage (true/false); @mode (Stretch — deprecated feature); @oneresultset (bit); @include_total_xtp_storage (In-Mem, when single set)
Result quirks DB mode default = two result sets. @oneresultset = 1 → one set (PS-friendly). Space columns are varchar with units (KB), not pure numbers. Object mode: schema name not returned. Deferred drop after big truncate/index drop → numbers lag.
Perms Execute: public. @updateusage = true: db_owner (runs DBCC UPDATEUSAGE)
Prefer instead sys.dm_db_partition_stats + sys.allocation_units / sys.partitions; files via sys.master_files

@updateusage caveat

-- Acceptable one-shot from PowerShell (single set)
EXEC sp_spaceused @oneresultset = 1;

-- Prefer for fleets (numeric, joinable) — see §4

3.8 sp_rename

Purpose Rename user object in current DB: table, column, index, constraint, statistics, alias/CLR type, database (@objtype = 'DATABASE')
Args @objname, @newname, optional @objtype (COLUMN | INDEX | OBJECT | STATISTICS | USERDATATYPE | DATABASE)
Result quirks Returns informational messages (e.g. caution about breaking scripts). New name is one-part only. Synapse/Fabric: narrower @objtype support (often COLUMN / OBJECT only — check platform).
Perms ALTER on object; type → CONTROL; database rename → sysadmin / dbcreator; ledger table → ALTER LEDGER

OK vs NEVER

Target OK? Why
Table, column, index, constraint, stats, type Yes (with dependency work) Metadata name updates; PK/UQ rename can cascade to related index/constraint
Stored proc, view, function, trigger NEVER for production renames sys.sql_modules.definition / OBJECT_DEFINITION still contain the old name — object name and body diverge. Scripts, sp_helptext, and redeploys lie. DROP + CREATE (or dacpac) instead.
Any object with dependents Only after inventory Refs do not auto-update. Check sys.sql_expression_dependencies first; fix views/procs/jobs manually. SELECT * views may need sp_refreshsqlmodule / sp_refreshview after column rename.
-- Table
EXEC sys.sp_rename N'dbo.OldTable', N'NewTable';           -- @objtype optional for objects
-- Column
EXEC sys.sp_rename N'dbo.T.OldCol', N'NewCol', N'COLUMN';
-- Index
EXEC sys.sp_rename N'dbo.T.IX_Old', N'IX_New', N'INDEX';

-- Modules: do NOT sp_rename — drop/create or publish

3.9 Dependencies — deprecated procs → modern catalog

Old Status Replacement
sp_depends Deprecated (Learn ver17: will be removed) sys.dm_sql_referencing_entities / sys.dm_sql_referenced_entities
sp_MSdependencies Undocumented / unsupported Same DMFs + sys.sql_expression_dependencies
SSMS “View Dependencies” UI only Fine interactively; scripts use catalog/DMFs
-- What references this object?
SELECT referencing_schema_name, referencing_entity_name, referencing_class_desc
FROM sys.dm_sql_referencing_entities(N'dbo.MyTable', N'OBJECT');

-- What does this module reference?
SELECT referenced_schema_name, referenced_entity_name, referenced_class_desc,
       is_caller_dependent, is_ambiguous
FROM sys.dm_sql_referenced_entities(N'dbo.usp_MyProc', N'OBJECT');

-- Database-wide soft dependency edges
SELECT OBJECT_SCHEMA_NAME(referencing_id) AS src_schema,
       OBJECT_NAME(referencing_id) AS src_object,
       referenced_schema_name, referenced_entity_name, referenced_server_name
FROM sys.sql_expression_dependencies;

Limits: No dependency rows for temp tables, rules/defaults (legacy), many dynamic-SQL names, or cross-DB unless recorded. Always treat as necessary but not sufficient before a rename/drop.

3.10 Other object-help procs still worth knowing (thin)

Proc When Prefer instead for Blazor
sp_helptrigger Interactive triggers on a table sys.triggers + sys.trigger_events
sp_helpconstraint Interactive constraints on a table sys.check_constraints / defaults / FKs / keys
sp_refreshview / sp_refreshsqlmodule After column rename / SELECT * drift Keep — fix tools, not inventory
ODBC set (§3.5) Driver debugging Catalog views

4. Inventory patterns — catalog queries that replace sp_help*

Stable shapes for dbo.*Staging → merge → Blazor (CLI-07). Always SET NOCOUNT ON.

4.1 Objects (replaces bare sp_help)

SET NOCOUNT ON;
SELECT
  @@SERVERNAME AS instance_name,
  DB_NAME() AS database_name,
  SCHEMA_NAME(o.schema_id) AS schema_name,
  o.name AS object_name,
  o.object_id,
  o.type AS type_code,
  o.type_desc,
  o.create_date,
  o.modify_date,
  o.is_ms_shipped,
  SYSUTCDATETIME() AS collected_utc
FROM sys.objects AS o
WHERE o.is_ms_shipped = 0
ORDER BY schema_name, o.type, object_name;

4.2 Columns (replaces sp_help column set / sp_columns)

SET NOCOUNT ON;
SELECT
  SCHEMA_NAME(t.schema_id) AS schema_name,
  t.name AS table_name,
  c.column_id,
  c.name AS column_name,
  ty.name AS type_name,
  c.max_length, c.precision, c.scale,
  c.is_nullable, c.is_identity, c.is_computed,
  c.is_rowguidcol
FROM sys.tables AS t
JOIN sys.columns AS c ON c.object_id = t.object_id
JOIN sys.types AS ty ON ty.user_type_id = c.user_type_id
ORDER BY schema_name, table_name, c.column_id;

4.3 Indexes (replaces sp_helpindex)

SET NOCOUNT ON;
SELECT
  SCHEMA_NAME(t.schema_id) AS schema_name,
  t.name AS table_name,
  i.name AS index_name,
  i.index_id, i.type_desc,
  i.is_unique, i.is_primary_key, i.is_unique_constraint,
  i.filter_definition,
  STRING_AGG(
    CASE WHEN ic.is_included_column = 0
         THEN c.name + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE '' END
    END, ', ') WITHIN GROUP (ORDER BY ic.key_ordinal) AS key_columns
FROM sys.tables AS t
JOIN sys.indexes AS i ON i.object_id = t.object_id AND i.index_id > 0
JOIN sys.index_columns AS ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.columns AS c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
GROUP BY t.schema_id, t.name, i.name, i.index_id, i.type_desc,
         i.is_unique, i.is_primary_key, i.is_unique_constraint, i.filter_definition;

4.4 Module definitions (replaces sp_helptext)

SET NOCOUNT ON;
SELECT
  SCHEMA_NAME(o.schema_id) AS schema_name,
  o.name AS module_name,
  o.type_desc,
  CASE WHEN m.definition IS NULL THEN 1 ELSE 0 END AS is_encrypted_or_unavailable,
  m.definition,          -- nvarchar(max); Invoke-Sqlcmd: raise -MaxCharLength
  m.uses_ansi_nulls, m.uses_quoted_identifier
FROM sys.sql_modules AS m
JOIN sys.objects AS o ON o.object_id = m.object_id
WHERE o.is_ms_shipped = 0;

4.5 Space / rows (replaces sp_spaceused fleets)

SET NOCOUNT ON;
SELECT
  SCHEMA_NAME(o.schema_id) AS schema_name,
  o.name AS object_name,
  SUM(ps.row_count) AS row_count,
  SUM(ps.reserved_page_count) * 8 AS reserved_kb,
  SUM(ps.used_page_count) * 8 AS used_kb,
  (SUM(ps.reserved_page_count) - SUM(ps.used_page_count)) * 8 AS unused_kb
FROM sys.dm_db_partition_stats AS ps
JOIN sys.objects AS o ON o.object_id = ps.object_id
WHERE o.type IN ('U', 'V')   -- tables; indexed views appear as V with indexes
  AND ps.index_id IN (0, 1)  -- heap or clustered only for row_count
GROUP BY o.schema_id, o.name
ORDER BY reserved_kb DESC;

4.6 Files / DBs (replaces sp_helpdb / sp_helpfile)

SET NOCOUNT ON;
SELECT
  d.name AS database_name,
  d.database_id, d.state_desc, d.recovery_model_desc,
  d.compatibility_level, d.collation_name,
  SUSER_SNAME(d.owner_sid) AS owner_name,
  mf.name AS logical_name, mf.type_desc,
  mf.physical_name,
  mf.size * 8.0 / 1024 AS size_mb,
  CASE WHEN mf.max_size = -1 THEN NULL ELSE mf.max_size * 8.0 / 1024 END AS max_size_mb,
  mf.growth, mf.is_percent_growth
FROM sys.databases AS d
JOIN sys.master_files AS mf ON mf.database_id = d.database_id
ORDER BY database_name, mf.type, mf.file_id;

5. Gotchas

Gotcha Impact Mitigation
Multi-result sets + Invoke-Sqlcmd You keep the last set only; Blazor staging silently incomplete Don’t stage from sp_help / sp_helpdb (named). Use §4 queries or @oneresultset = 1 for sp_spaceused
sp_helptext 255-char rows Naive ConvertTo-Json on rows ≠ full module sys.sql_modules.definition; set -MaxCharLength high enough (CLI-03)
Collation Join name across DBs / temp / catalog can fail with collation conflict COLLATE DATABASE_DEFAULT on join keys; inventary columns as nvarchar
Temp tables sp_help on #t works in-session; catalog queries need that session; deps DMFs ignore temps Don’t inventory temps for Blazor; session-scoped only
Deferred space release sp_spaceused right after huge truncate/index drop looks “full” Wait for background cleanup, or trust DMVs later; avoid panicking capacity alerts
@updateusage Heavy; needs db_owner Never on a 5-minute collector; maintenance window only
sp_rename modules Name ≠ definition text Ban in CI; allow only table/column/index/constraint
Azure SQL DB No full instance sys.master_files story like on-prem; sp_helpdb/sp_helpfile thin or N/A; no Agent Use sys.database_files, Azure metrics / CLI-05; skip Agent siblings
Azure Synapse sp_helptext unsupported; sp_rename limited (often column-focused) OBJECT_DEFINITION / sys.sql_modules; check platform docs before rename scripts
Cross-db sp_help* Looks in current DB only USE / -d per DB loop (CLI-01)

6. Recipes (sqlcmd + Invoke-Sqlcmd + catalog equivalents)

R1 — Interactive object peek (sqlcmd)

sqlcmd -S "$SQL_SERVER" -E -d "$SQL_DB" -Q "EXEC sp_help N'dbo.MyTable';"

R2 — Indexes interactive (catalog: §4.3)

sqlcmd -S "$SQL_SERVER" -E -d "$SQL_DB" -Q "EXEC sp_helpindex N'dbo.MyTable';"

R3 — sp_spaceused single set (acceptable PS) vs DMV

Invoke-Sqlcmd -ServerInstance $env:SQL_SERVER -Database $env:SQL_DB -TrustServerCertificate `
  -Query "EXEC sp_spaceused @oneresultset = 1;"
# Preferred fleet shape
$q = Get-Content -Raw .\space-by-table.sql   # §4.5
Invoke-Sqlcmd -ServerInstance $env:SQL_SERVER -Database $env:SQL_DB -TrustServerCertificate -Query $q |
  Export-Csv ".\space-$($env:SQL_SERVER)-$($env:SQL_DB).csv" -NoTypeInformation

R4 — Module text: never chunk-scrape

$q = @"
SET NOCOUNT ON;
SELECT OBJECT_SCHEMA_NAME(object_id) AS schema_name, OBJECT_NAME(object_id) AS module_name,
       definition
FROM sys.sql_modules
WHERE object_id = OBJECT_ID(N'dbo.usp_MyProc');
"@
Invoke-Sqlcmd -ServerInstance $env:SQL_SERVER -Database $env:SQL_DB -TrustServerCertificate `
  -MaxCharLength 1000000 -Query $q

R5 — Encrypted / missing definition audit

SET NOCOUNT ON;
SELECT SCHEMA_NAME(o.schema_id) AS schema_name, o.name, o.type_desc
FROM sys.objects AS o
JOIN sys.sql_modules AS m ON m.object_id = o.object_id
WHERE m.definition IS NULL AND o.is_ms_shipped = 0
ORDER BY 1, 2;

R6 — Rename column (with dependency check first)

-- 1) Who references this table?
SELECT referencing_schema_name, referencing_entity_name
FROM sys.dm_sql_referencing_entities(N'dbo.MyTable', N'OBJECT');

-- 2) Rename
EXEC sys.sp_rename N'dbo.MyTable.OldCol', N'NewCol', N'COLUMN';

-- 3) Refresh any SELECT * modules if needed
-- EXEC sys.sp_refreshsqlmodule N'dbo.vw_Something';

R7 — sqlcmd CSV: object inventory (catalog)

sqlcmd -S "$SQL_SERVER" -E -d "$SQL_DB" -b -s"," -W \
  -Q "SET NOCOUNT ON;
SELECT SCHEMA_NAME(schema_id) AS schema_name, name, type, type_desc, create_date, modify_date
FROM sys.objects WHERE is_ms_shipped = 0 ORDER BY 1, 2;" \
  -o "./objects_${SQL_SERVER}_${SQL_DB}.csv"

R8 — Invoke-Sqlcmd → JSON for Blazor cache / API

$q = @"
SET NOCOUNT ON;
SELECT @@SERVERNAME AS InstanceName, DB_NAME() AS DatabaseName,
  SCHEMA_NAME(o.schema_id) AS SchemaName, o.name AS ObjectName,
  o.type AS TypeCode, o.type_desc AS TypeDesc,
  o.create_date AS CreateDate, o.modify_date AS ModifyDate,
  SYSUTCDATETIME() AS CollectedUtc
FROM sys.objects AS o WHERE o.is_ms_shipped = 0;
"@
$rows = Invoke-Sqlcmd -ServerInstance $env:SQL_SERVER -Database $env:SQL_DB `
  -TrustServerCertificate -Query $q
$rows | ConvertTo-Json -Depth 3 | Set-Content ".\objects-$($env:SQL_SERVER).json" -Encoding UTF8

R9 — Dependency gate before drop/rename

sqlcmd -S "$SQL_SERVER" -E -d "$SQL_DB" -b -Q "
SET NOCOUNT ON;
SELECT referencing_schema_name, referencing_entity_name, referencing_class_desc
FROM sys.dm_sql_referencing_entities(N'dbo.MyTable', N'OBJECT');
"

R10 — DB file layout catalog (replaces sp_helpdb/sp_helpfile for staging)

sqlcmd -S "$SQL_SERVER" -E -d master -b -s"," -W -i ./files-inventory.sql -o "./files_${SQL_SERVER}.csv"
# files-inventory.sql body = §4.6

7. Pointers to 09a / 09c / 09d / 09e

Doc Covers
SQL-CLI-09 Overview: call patterns, procs vs DMVs, curated catalog
SQL-CLI-09a sp_configure / RECONFIGURE / sys.configurations; sp_who* honesty
09b (this) Object help, space, text, rename, dependency replacements
09c Security / logins / users / roles; deprecated sp_change_users_login; modern DDL
09d Agent: sp_help_job / sp_start_job / history vs msdb tables
09e Surface area / xp_cmdshell / Ole Automation — policy & safer alternatives

Related stack: SQL-CLI-01 (calling / -b / -d), SQL-CLI-07 (Collect→Stage→Blazor), SQL-CLI-03 (-MaxCharLength).

Learn anchors (ver17): sp_help, sp_helpdb, sp_helpfile, sp_helpfilegroup, sp_helpindex, sp_helptext, sp_spaceused, sp_rename, sp_depends (deprecated), Catalog stored procedures, sys.sql_modules, sys.sql_expression_dependencies, sys.dm_sql_referencing_entities, sys.dm_sql_referenced_entities, sys.dm_db_partition_stats.