数据库模式探索与分析
立即解锁
发布时间: 2025-08-30 01:40:30 阅读量: 5 订阅数: 9 AIGC 

### 数据库模式探索与分析
#### 1. 利用系统视图和函数进行数据库查询
在数据库操作中,我们可以借助系统视图和`OBJECTPROPERTY()`函数来节省大量代码。以下是一些常见的查询场景及对应的 SQL 代码:
##### 1.1 查找无主键的表
```sql
SELECT DB_NAME() + '.' + object_schema_name(t.object_ID) + '.' + t.name
AS [tables without primary keys]
FROM sys.tables t
WHERE OBJECTPROPERTY(object_id, 'TableHasPrimaryKey') = 0
AND OBJECTPROPERTY(object_id, 'IsUserTable') = 1
ORDER BY [tables without primary keys]
```
此查询通过`sys.tables`系统视图和`OBJECTPROPERTY()`函数,筛选出没有主键且为用户表的表,并将结果按表名排序。
##### 1.2 查找无引用约束的表
```sql
SELECT
DB_NAME() + '.' + object_schema_name(t.object_ID)
+ '.' + t.name AS [Waif Tables]
FROM sys.tables t
WHERE OBJECTPROPERTY(object_id, 'TableHasForeignKey') = 0
AND OBJECTPROPERTY(object_id, 'TableHasForeignRef') = 0
AND OBJECTPROPERTY(object_id, 'IsUserTable') = 1
ORDER BY [Waif tables]
```
该查询找出既没有外键约束,也没有被其他表引用的用户表。
##### 1.3 查找无聚集索引的表
```sql
SELECT DB_NAME() + '.' + Object_Schema_name(t.object_ID) + '.' + t.name
AS [Tables without Clustered index]
FROM sys.tables t
WHERE OBJECTPROPERTY(object_id, 'TableHasClustIndex') = 0
AND OBJECTPROPERTY(object_id, 'IsUserTable') = 1
ORDER BY [Tables without Clustered index]
```
此查询用于找出没有聚集索引的用户表。
##### 1.4 查找无任何索引的表
```sql
SELECT DB_NAME() + '.' + Object_Schema_name(t.object_ID) + '.' + t.name
AS [Tables without any index]
FROM sys.tables t
WHERE OBJECTPROPERTY(object_id, 'TableHasIndex') = 0
AND OBJECTPROPERTY(object_id, 'IsUserTable') = 1
ORDER BY [Tables without any index]
```
该查询可找出没有任何索引的用户表。
#### 2. 全面查看表结构
我们可以通过一个针对`sys.tables`系统视图的查询,一次性了解数据库中表的各种对象(如索引、约束等)是否存在。以下是具体的查询代码:
```sql
SELECT DB_NAME() + '.' + Object_Schema_name(t.object_ID) + '.' + t.name
AS [Qualified Name] ,
CASE WHEN
--Table has an active full-text index.
OBJECTPROPERTY(object_id, 'TableHasActiveFulltextIndex') = 0
THEN 'no'
ELSE 'yes'
END AS [FT index] ,
CASE WHEN
--Table has a CHECK constraint.
OBJECTPROPERTY(object_id, 'TableHasCheckCnst') = 0 THEN 'no'
ELSE 'yes'
END AS [Check Cnt] ,
CASE WHEN
--Table has a clustered index.
OBJECTPROPERTY(object_id, 'TableHasClustIndex') = 0
THEN 'no'
ELSE 'yes'
END AS [Clustered ix] ,
CASE WHEN
--Table has a DEFAULT constraint.
OBJECTPROPERTY(object_id, 'TableHasDefaultCnst') = 0
THEN 'no'
ELSE 'yes'
END AS [Default Cnt] ,
CASE WHEN
--Table has a DELETE trigger.
OBJECTPROPERTY(object_id, 'TableHasDeleteTrigger') = 0
THEN 'no'
ELSE 'yes'
END AS [Delete Tgr] ,
CASE WHEN
--Table has a FOREIGN KEY constraint.
OBJECTPROPERTY(object_id, 'TableHasForeignKey') = 0
THEN 'no'
ELSE 'yes'
END AS [FK Cnt] ,
CASE WHEN
--referenced by a FOREIGN KEY constraint.
OBJECTPROPERTY(object_id, 'TableHasForeignRef') = 0
THEN 'no'
ELSE 'yes'
END AS [FK Ref] ,
--Table has an identity column.
CASE WHEN OBJECTPROPERTY(object_id, 'TableHasIdentity') = 0 THEN 'no'
ELSE 'yes'
END AS [Identity Col] ,
--Table has an index of any type.
CASE WHEN OBJECTPROPERTY(object_id, 'TableHasIndex') = 0 THEN 'no'
ELSE 'yes'
END AS [Any index] ,
CASE WHEN
--Object has an INSERT trigger.
OBJECTPROPERTY(object_id, 'TableHasInsertTrigger') = 0
THEN 'no'
ELSE 'yes'
END AS [Insert Tgr] ,
CASE WHEN
--Table has a nonclustered index.
OBJECTPROPERTY(object_id, 'TableHasNonclustIndex') = 0
THEN 'no'
ELSE 'yes'
END AS [nonCl Index] ,
CASE WHEN
--Table has a primary key
OBJECTPROPERTY(object_id, 'TableHasPrimaryKey') = 0
THEN 'no'
ELSE 'yes'
END AS [Primary Key] ,
CASE WHEN
--ROWGUIDCOL for uniqueidentifier col
OBJECTPROPERTY(object_id, 'TableHasRowGuidCol') = 0
THEN 'no'
ELSE 'yes'
END AS [ROWGUIDCOL] ,
CASE WHEN
--Table has text, ntext, or image column
OBJECTPROPERTY(object_id, 'TableHasTextImage') = 0 THEN 'no'
ELSE 'yes'
END AS [Has Blob] ,
CASE WHEN
--Table has a timestamp column.
OBJECTPROPERTY(object_id, 'TableHasTimestamp') = 0 THEN 'no'
ELSE 'yes'
END AS [Timestamp] ,
CASE WHEN
--Table has a UNIQUE constraint.
OBJECTPROPERTY(object_id, 'TableHasUniqueCnst') = 0
THEN 'no'
ELSE 'yes'
END AS [Unique Cnt] ,
CASE WHEN
--Table has an Update trigger.
OBJECTPROPERTY(object_id, 'TableHasUpdateTrigger') = 0
THEN 'no'
ELSE 'yes'
END AS [Update Tgr]
FROM sys.tables t
WHERE OBJECTPROPERTY(object_id, 'IsUserTable') = 1
ORDER BY [Qualified Name]
```
这个查询会返回一个表格,展示每个用户表的各种属性,如是否有全文索引、检查约束、聚集索引等。
#### 3. 统计对象数量
`OBJECTPROPERTY`函数通常返回 1 或 0,我们可以利用这一特性来统计每个表上的约束、默认值、规则或触发器的数量。
```sql
SELECT DB_NAME() + '.' + Object_Schema_name(s.[object_ID]) + '.' + p.name
AS [Qualified_Name] ,
COUNT(*) ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsPrimaryKey')) AS [Pk] ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsCheckCnst')) AS [ChkCns] ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsDefaultCnst')) AS [DefCns] ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsForeignKey')) AS [Fk] ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsConstraint')) AS [Cnstrnt] ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsDefault')) AS [Default] ,
SUM(OBJECTPROPERTY(s.object_ID, 'IsTrigger')) AS [Trigger]
FROM sys.objects S
INNER JOIN sys.objects p
ON s.parent_Object_ID = p.[object_ID]
WHERE OBJECTPROPERTY(p.object_ID, 'IsTable') <> 0
GROUP BY DB_NAME() + '.' + Object_Schema_name(s.[object_ID]) + '.' + p.name
```
此查询会统计每个表上各种对象的数量,如主键、检查约束、默认约束等。
#### 4. 查找索引过多的表
我们可以通过以下查询找出索引最多的表,以检查是否存在索引重复的情况。
```sql
SELECT TOP 10
COUNT(*) AS [Indexes] ,
DB_NAME() + '.' + Object_Schema_name(t.object_ID) + '.' + t.name
AS [table]
FROM sys.indexes i
INNER JOIN sys.objects t ON i.object_ID = t.object_ID
WHERE USER_NAME(OBJECTPROPERTY(i.object_id, 'OwnerId')) NOT LIKE 'sys%'
GROUP BY DB_NAME() + '.' + Object_Schema_name(t.object_ID) + '.' + t.name
ORDER BY COUNT(*) DESC
```
该查询会返回索引数量最多的前 10 个表,并按索引数量降序排列。
#### 5. 查找含触发器的表
触发器有时会给开发带来困扰,我们可以通过以下查询找出哪些表上有触发器以及触发器的数量。
```sql
SELECT
DB_NAME() + '.' + Object_Schema_name(s.[object_ID]) + p.name
AS [Qualified_Name] ,
COUNT(*) AS [how many]
FROM sys.objects S
INNER JOIN sys.objects p
ON s.parent_Object_ID = p.[object_ID]
WHERE OBJECTPROPERTY(s.object_ID, 'IsTrigger') <> 0
AND OBJECTPROPERTY(p.object_ID, 'IsTable') <> 0
GROUP BY DB_NAME() + '.' + Object_Schema_name(s.[object_ID]) + p.name
```
此查询会统计每个表上触发器的数量。
我们还可以进一步查看每个表上触发器的类型:
```sql
SELECT DB_NAME() + '.' + Object_Schema_name(t.[object_ID]) + '.' + t.name
AS [Qualified_Name] ,
CASE WHEN OBJECTPROPERTY(t.object_ID, 'HasAfterTrigger') <> 0
THEN 'yes'
```
0
0
复制全文
相关推荐










