在SQL编码中,很多编程人员常会使用嵌套view或者存储过程(sproc)完成代码,虽然出于性能和可维护性的考虑并不推荐使用多层嵌套,但现实中仍然是较为常见的编码习惯(方便呗~~)。那么针对多层嵌套的情况需要找出所有用户自定义表(或其它类型对象)往往就显得不是那么的容易了,当然可以通过一层一层统计获得,那么有没有精确并快速的方法找出所有的表呢。
首先,得从系统表sys.sql_expression_dependencies说起,该系统表主要用于查询SQL Server对象间的依赖关系,例如,在视图定义中引用表时,作为引用实体的视图将依赖于表这个被引用的实体,用户定义实体的每个按名称依赖项在此表中均占一行。
以下SQL 用于查询所有给定对象依赖的所有对象。如给定的对象为视图,则返回当前视图所有依赖的对象(table,view,fun,etc),因此可以查询出视图中所用的实体对象。
SELECT OBJECT_NAME(referencing_id) AS referencing_entity_name,
o.type_desc AS referencing_desciption,
COALESCE(COL_NAME(referencing_id, referencing_minor_id), '(n/a)') AS referencing_minor_id,
referencing_class_desc,
referenced_entity_name,
o2.type_desc AS referenced_desciption,
referenced_server_name,
referenced_database_name,
referenced_schema_name,
COALESCE(COL_NAME(referenced_id, referenced_minor_id), '(n/a)') AS referenced_column_name,
o.type AS referencing_type,
is_caller_dependent,
is_ambiguous
FROM sys.sql_expression_dependencies AS sed
JOIN sys.objects AS o ON sed.referencing_id = o.object_id
JOIN sys.objects AS o2 ON sed.referenced_entity_name = o2.name
WHERE referencing_id = OBJECT_ID(N'Object_Name')
查询所有依赖于给定对象的所有实体对象,如给定一个表,将会返回所有使用该表的view,sp,fun等
SELECT OBJECT_SCHEMA_NAME ( referencing_id ) AS referencing_schema_name,
OBJECT_NAME(referencing_id) AS referencing_entity_name,
o.type_desc AS referencing_desciption,
COALESCE(COL_NAME(referencing_id, referencing_minor_id), '(n/a)') AS referencing_minor_id,
referencing_class_desc,
referenced_entity_name,
referenced_class_desc,
referenced_server_name,
referenced_database_name,
referenced_schema_name,
COALESCE(COL_NAME(referenced_id, referenced_minor_id), '(n/a)') AS referenced_column_name,
o.type AS referencing_type,
is_caller_dependent,
is_ambiguous
FROM sys.sql_expression_dependencies AS sed
JOIN sys.objects AS o
ON sed.referencing_id = o.object_id
WHERE referenced_id = OBJECT_ID(N'Object_Name')
下面的语句将返回所有跨数据库的依赖关系
SELECT OBJECT_NAME (referencing_id) AS referencing_entity_name,
referenced_database_name,
referenced_schema_name,
referenced_entity_name,
referencing_class_desc
FROM sys.sql_expression_dependencies
WHERE referenced_database_name IS NOT NULL;
这里再提一下另外一个系统视图sys.sql_modules,该视图能够实现相同的功能,但是并不要求是实体对象,可以找出所有包含所给关键词的所有对象,甚至关键词出现在注释中也会被查询出来,因此查询返回的结果更多。同样还可以使用sys.syscomments,但不推荐,后续的SQL Server版本可能会删除该视图。
SELECT b.name,
b.type_desc
FROM sys.sql_modules a
JOIN sys.objects b
ON a.object_id = b.object_id
WHERE b.type = 'P'
AND a.definition LIKE '%Object_Name%'
以上的代码只适用于查询当前对象的依赖关系,对于嵌套对象的情况并不支持,例如,查询视图中使用到的所有表,如果视图中还包含其它视图,则返回的对象将包括视图和表,并不会返回内嵌视图中使用的表。针对这样的情况,可以使用以下递归CTE,递归的查找出所有的用户表。设置type可以选择返回的对象,如查询所有的视图等。
WITH RECUR_CTE(referencing_id, referenced_id, referenced_entity_name, referenced_database_name)
SELECT referencing_id, referenced_id, referenced_entity_name, referenced_database_name
FROM sys.sql_expression_dependencies AS sed
WHERE sed.referencing_id = OBJECT_ID(N'Object_Name')
UNION ALL
SELECT sed2.referencing_id, sed2.referenced_id, sed2.referenced_entity_name, sed2.referenced_database_name
FROM sys.sql_expression_dependencies AS sed2
INNER JOIN RECUR_CTE rc
ON rc.referenced_id = sed2.referencing_id
SELECT DISTINCT
schema_name(o.schema_id) AS schema_name,
o.name AS referencing_entity_name,
o.type_desc AS referencing_object_type,
rc.referenced_entity_name,
o2.type_desc AS referenced_object_type,
ISNULL(rc.referenced_database_name, db_name()) AS referenced_database_name
FROM RECUR_CTE rc
JOIN sys.objects o
ON rc.referencing_id = o.object_id
JOIN sys.objects o2
ON rc.referenced_id = o2.object_id
WHERE o2.type = 'U'
OPTION(MAXRECURSION 10)
referenced_schema_name,
referenced_entity_name,
'UPDATE STATISTICS ['+referenced_schema_name+'].'+'['+referenced_entity_name+']' as update_stats_sql
FROM #table_list
其中临时表table_list为递归CTE返回的所有用户表。
对于如何获取索引信息,想必大家对sp_helpindex并不陌生,这也是常用方法,但是它并不能提供包含列以及filter信息,于是乎尝试着写了如下SQL code,当然和大神们写的查询的sp不能相提并论,但是凑合着使用应该没有问题。
SELECT index_name,
index_description,
(LEFT(ind_col, LEN(ind_col)-1)
sqlserver父子递归查询指的是在一张表中,通过某一列的父子关系建立递归查询,以获取某一节点的所有子孙节点或所有祖先节点的一种查询方式。一般情况下,父子递归查询需要使用到sqlserver中的CTE(通用表达式)功能。
在进行父子递归查询时,需要先确定递归关系所依赖的列名,并对其进行命名。然后,通过WITH关键字,定义一个CTE来连接包含父子关系的表,并给其取一个别名。接着,在该CTE中使用递归查询语句,以获取所需的结果。
递归查询语句需要包含以下几个部分:首先是递归结束条件,用来终止递归的过程;其次是递归体,用来确定递归下一步所需要获取的数据;最后是查询语句,用来获取最终需要的结果。
在递归查询中,为了能够判断某一节点是否为叶子节点或根节点,可以使用CASE语句进行判断。如果在查询中需要对结果进行排序,可以使用ORDER BY关键字,指定排序规则。
需要注意的是,在进行父子递归查询时,需要考虑性能问题。如果表中记录非常多,递归的过程也会比较复杂,可能会导致查询时间变得非常长。因此,在实际应用中,需要根据具体情况进行优化,例如在表中添加索引等。