最直接的方式是查询 sys.tables 并加 where type = 'u' and is_ms_shipped = 0;它返回用户表名(不含 schema),需拼接 schema_name(schema_id) 获取完整限定名,且不包含临时表、内存优化表及外部表。

查 sys.tables 是最直接的方式
SQL Server 的系统视图 sys.tables 专用于列出当前数据库中所有用户定义的表(不含视图、系统表)。它比旧式 sysobjects 更清晰、更可靠,且默认过滤掉系统对象。
-
SELECT name FROM sys.tables就能拿到所有表名,但注意:结果不含 schema 前缀,比如只返回Orders,而不是dbo.Orders - 如果需要完整限定名,必须显式拼接 schema:
SELECT SCHEMA_NAME(schema_id) + '.' + name FROM sys.tables - 该视图不包含临时表(
#temp或##global),也不返回内存优化表以外的外部表(如 PolyBase 外部源)
用 INFORMATION_SCHEMA.TABLES 要小心权限和范围
INFORMATION_SCHEMA.TABLES 是 SQL 标准兼容视图,看起来“更通用”,但在 SQL Server 中实际受限较多:
- 它只返回当前用户有权限查看的表,哪怕你有
db_owner角色,若某表被显式DENY SELECT,也可能不出现 - 它把视图和表混在一起,需额外过滤:
WHERE TABLE_TYPE = 'BASE TABLE' - 不支持内存优化表、临时表、分区表元数据的完整呈现;某些企业版功能(如 Stretch Database)也不在此视图中反映
- 性能略低于
sys.tables,尤其在大库中,因为它是基于多个系统基表的封装视图
排除系统表和内部对象的关键条件
即使查 sys.tables,默认也会包含一些以 sys 开头的内部对象(如 sysallocunits),它们不是用户可操作的表。真正要“所有用户表”,得加过滤:
- 推荐条件:
WHERE type = 'U' AND is_ms_shipped = 0——type = 'U'表示用户表,is_ms_shipped = 0排除 SQL Server 自带的对象 - 不要只依赖
name NOT LIKE 'sys%',因为有些用户建的表也叫sys_config,会被误杀 - 如果跨多个数据库查,需动态切换上下文或用
sys.databases配合sys.dm_exec_describe_first_result_set等方式,不能简单UNION ALL所有sys.tables
查询结果为空?先确认当前数据库上下文
这是最常见的“查不到表”的原因:你连着 master 或 tempdb,却在查当前库的 sys.tables,自然返回空。
- 执行前务必检查:
SELECT DB_NAME(),确保在目标数据库下 - 不想切库?可用三段式名称:
MyDB.sys.tables,但注意:SQL Server 不允许跨库直接查另一个库的sys.视图(会报错“无法解析对象名”),必须USE MyDB或用EXEC MyDB..sp_executesql - 如果用 SSMS,右上角数据库下拉框是否手动选错了?这个坑每天都在发生
sys.tables 加 is_ms_shipped = 0 这个组合,覆盖了绝大多数真实场景;但别忘了——schema 名、数据库上下文、权限这三点,才是让查询“看似失效”的高频盲区。










