探索SQL Server元数据(二)
背景上一篇中,我介绍了SQL Server 允许访问数据库的元数据,为什么有元数据,如何使用元数据。这一篇中我会介绍如何进一步找到各种有价值的信息。以触发器为例,因为它们往往一起很多问题。 那么如何找到触发器的数据?以sys.system_viewsis表开始。让我们查询出数据库中使用触发器的信息。可以告知你当前SQL Server版本中有什么触发器。 SELECT schema_name(schema_ID)++FROM sys.system_views WHERE name LIKE <span style="color: #800000">'<span style="color: #800000">%trigger%<span style="color: #800000">' sys.dm_exec_trigger_statssys.server_trigger_events sys.server_triggers sys.trigger_event_types sys.trigger_events sys.triggers (6 row(s) affected) 其中sys.triggers看起来信息很多,它又包含什么列?下面这个查询很容易查到: SELECT Thecol.name+ ++ CASE WHEN TheCol.is_nullable=<span style="color: #800080">1 THEN <span style="color: #800000">'<span style="color: #800000"> NULL<span style="color: #800000">' ELSE <span style="color: #800000">'<span style="color: #800000"> NOT NULL<span style="color: #800000">' END <span style="color: #0000ff">as<span style="color: #000000"> Column_InformationFROM sys.system_views AS TheView INNER JOIN sys.system_columns AS TheCol
WHERE TheView.name = <span style="color: #800000">'<span style="color: #800000">triggers<span style="color: #800000">'<span style="color: #000000"> ORDER BY column_ID; 结果如下: name nvarchar NOT NULL object_id int NOT NULL parent_class tinyint NOT NULL parent_class_desc nvarchar NULL parent_id int NOT NULL type char NOT NULL type_desc nvarchar NULL create_date datetime NOT NULL modify_date datetime NOT NULL is_ms_shipped bit NOT NULL is_disabled bit NOT NULL is_not_for_replication bit NOT NULL is_instead_of_trigger bit NOT NULL 因此我们多这个信息有了更好的理解,有了一个目录的目录。这个概念有点让人头晕,但是另一方面,它也是相当简单的。我们能够查出元数据,再找个查询中,需要做的就是改变这个单词‘triggers’来查找你想要的视图名称。. 在2012及其以后版本,可以使用一个新的表值函数极大地简化上述查询,并可以避免各种连接。在下面的查询中,我们将查找sys.triggers 视图 中的列。可以使用相同的查询通过更改字符串中的对象名称来获取任何视图的定义。 + ++ CASE WHEN is_nullable=<span style="color: #800080">1 THEN <span style="color: #800000">'<span style="color: #800000"> NULL<span style="color: #800000">' ELSE <span style="color: #800000">'<span style="color: #800000"> NOT NULL<span style="color: #800000">' END <span style="color: #0000ff">as<span style="color: #000000"> Column_InformationFROM sys.dm_exec_describe_first_result_set ( N<span style="color: #800000">'<span style="color: #800000">SELECT * FROM sys.triggers;<span style="color: #800000">',NULL,<span style="color: #800080">0<span style="color: #000000">) AS f ORDER BY column_ordinal; 查询结果如下: ----------------------------------------<span style="color: #000000">name nvarchar(<span style="color: #800080">128<span style="color: #000000">) NOT NULL object_id <span style="color: #0000ff">int<span style="color: #000000"> NOT NULL parent_class tinyint NOT NULL parent_class_desc nvarchar(<span style="color: #800080">60<span style="color: #000000">) NULL parent_id <span style="color: #0000ff">int<span style="color: #000000"> NOT NULL type <span style="color: #0000ff">char(<span style="color: #800080">2<span style="color: #000000">) NOT NULL type_desc nvarchar(<span style="color: #800080">60<span style="color: #000000">) NULL create_date datetime NOT NULL modify_date datetime NOT NULL is_ms_shipped bit NOT NULL is_disabled bit NOT NULL is_not_for_replication bit NOT NULL is_instead_of_trigger bit NOT NULL sys.dm_exec_describe_first_result_set函数的最大优势在于你能看到任何结果的列,不仅仅是表和视图、存储过程或者贬值函数。 为了查出任何列的信息,你可以使用稍微修改的版本,只需要改变代码中的字符串'sys.triggers'即可,如下: Declare @TheParamater nvarchar(Select @TheParamater = <span style="color: #800000">'<span style="color: #800000">sys.triggers<span style="color: #800000">'<span style="color: #000000">Select @TheParamater = <span style="color: #800000">'<span style="color: #800000">SELECT * FROM <span style="color: #800000">' +<span style="color: #000000"> @TheParamater SELECT name+ <span style="color: #800000">' <span style="color: #800000">'+<span style="color: #000000"> system_type_name + CASE WHEN is_nullable=<span style="color: #800080">1 THEN <span style="color: #800000">'<span style="color: #800000"> NULL<span style="color: #800000">' ELSE <span style="color: #800000">'<span style="color: #800000"> NOT NULL<span style="color: #800000">' END <span style="color: #0000ff">as<span style="color: #000000"> Column_Information FROM sys.dm_exec_describe_first_result_set ( @TheParamater,<span style="color: #800080">0<span style="color: #000000">) AS f ORDER BY column_ordinal; 但是当然一个触发器是首先是一个对象,因此一定在sys.objects?在我们使用sys.triggers的信息之前,需要来重复一遍,所有的数据库对象都存在于sys.objects中,在SQL Server 中的对象包括以下:聚合的CLR函数,check 约束,SQL标量函数,CLR标量函数,CLR表值函数,SQL内联表值函数,内部表,SQL存储过程,CLR存储过程,计划指南,主键约束,老式规则,复制过滤程序,系统基础表,同义词,序列对象,服务队列,CLR DML 触发器,SQL表值函数,表类型,用户自定义表,唯一约束,视图和扩展存储过程等。 触发器是对象所以基础信息一定保存在sys.objects。不走运的是,有时我们需要额外的信息,这些信息可以通过目录视图查询。这些额外数据有是什么呢? 修改我们使用过的查询,来查询sys.triggers的列,这次我们会看到额外信息。这些额外列是来自于sys.objects。 SELECT coalesce(trigger_column.name,FROM(SELECT Thecol.name FROM sys.system_views AS TheView
WHERE TheView.name = <span style="color: #800000">'<span style="color: #800000">triggers<span style="color: #800000">'<span style="color: #000000">) trigger_columnFULL OUTER JOIN (SELECT Thecol.name FROM sys.system_views AS TheView
WHERE TheView.name = <span style="color: #800000">'<span style="color: #800000">objects<span style="color: #800000">'<span style="color: #000000">) object_columnON trigger_column.name=<span style="color: #000000">object_column.name 查询结果: In_Sys_Triggers In_Sys_Objects ------------------------------ ----------------------<span style="color: #000000"> name name object_id object_id NOT INCLUDED principal_id NOT INCLUDED schema_id NOT INCLUDED parent_object_id type type type_desc type_desc create_date create_date modify_date modify_date is_ms_shipped is_ms_shipped NOT INCLUDED is_published NOT INCLUDED is_schema_published is_not_for_replication NOT INCLUDED is_instead_of_trigger NOT INCLUDED parent_id NOT INCLUDED is_disabled NOT INCLUDED parent_class NOT INCLUDED parent_class_desc NOT INCLUDED 以上这些让我们知道在sys.triggers的额外信息,但是因为它始终是表的子对象,所以有些不相关信息是不会展示在这些指定的视图或者sys.triggers中的。现在就要带大家去继续找找这些信息。 触发器的问题触发器是有用的,但是因为它们在SSMS对象资源管理器窗格中不是可见的,所以一般用来提醒错误。触发器有时候会有些微妙的地方让其出问题,比如,当导入过程中禁用了触发器,并且由于某些原因他们没有重启。 下面是一个关于触发器的简要提醒: 触发器可以在视图,表或者服务器上,任何这些对象上都可以有超过1个触发器。普通的DML触发器能被定义来执行替代一些数据修改(Insert,Update或者Delete)或者在数据修改之后执行。每一个触发器与只与一个对象管理。DDL触发器与数据库关联或者被定义在服务器级别,这类触发器一般在Create,Alter或者Drop这类SQL语句执行后触发。 像DML触发器一样,可以有多个DDL触发器被创建在同一个T-SQL语句上。一个DDL触发器和语句触发它的语句在同一个事务中运行,所以除了Alter DATABASE之外都可以被回滚。DDL触发器运行在T-SQL语句执行完毕后,也就是不能作为Instead OF触发器使用。 两种触发器都与事件相关,在DML触发器中,包含INSERT,UPDATE,和DELETE,然而很多事件都可以与DDL触发器关联,稍后我们将了解。 在数据库中列出触发器那么怎么获取触发器列表?下面我在AdventureWorks数据库中进行查询,注意该库的视图中没有触发器。 第一个查询所有信息都在sys.triggers 的目录视图中。 name AS TriggerName,coalesce(object_schema_name(parent_ID)+<span style="color: #800000">'<span style="color: #800000">.<span style="color: #800000">'
FROM sys.triggers; TriggerName TheParent ------------------------------ ----------------------------------------<span style="color: #000000"> ddlDatabaseTriggerLog Database (AdventureWorks2012) dEmployee HumanResources.Employee iuPerson Person.Person iPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail uPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail uPurchaSEOrderHeader Purchasing.PurchaSEOrderHeader iduSalesOrderDetail Sales.SalesOrderDetail uSalesOrderHeader Sales.SalesOrderHeader dVendor Purchasing.Vendor iWorkOrder Production.WorkOrder uWorkOrder Production.WorkOrder 我使用元数据函数db_name()使SQL保持简单。db_name()告诉我数据库的名称。object_schema_name()用来查询object_ID代表的对象的架构,以及object_name()查询对象名称。这些对对象的引用指向触发器的所有者,触发器可以是数据库本身,也可以是表:服务器触发器有自己的系统视图,稍后我会展示。 如果想要看到所有触发器,那么我们最好使用sys.objects 视图: SELECT name TriggerName,object_schema_name(parent_object_ID)+
注意,输出不包含数据库级别的触发器,因为所有的DML触发器都在sys.objects视图中,但是你会漏掉在sys.triggers视图中的触发器。 上面查询结果: ------------------------------ -------------------------------<span style="color: #000000">dEmployee HumanResources.Employee iuPerson Person.Person iPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail uPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail uPurchaSEOrderHeader Purchasing.PurchaSEOrderHeader iduSalesOrderDetail Sales.SalesOrderDetail uSalesOrderHeader Sales.SalesOrderHeader dVendor Purchasing.Vendor iWorkOrder Production.WorkOrder uWorkOrder Production.WorkOrder 我的表和视图有多少个触发器?我想知道每个表有多少个触发器,并且什么情况下触发它们。下面我们列出了具有触发器的表以及每个事件的触发器数量。每个表或者视图对于触发器行为都有一个INSTEAD OF 触发器,可能是UPDATE,DELETE,或者 INSERT 。但是一个表可以有多个AFTER触发器行为。这些将展示在下面的查询中(排除视图): convert(CHAR(<span style="color: #800080">32),coalesce(object_schema_name(parent_ID)+<span style="color: #800000">'<span style="color: #800000">.<span style="color: #800000">'
convert(SMALLINT,objectpropertyex(parent_ID,N<span style="color: #800000">'<span style="color: #800000">TABLEDeleteTriggerCount<span style="color: #800000">')) AS <span style="color: #800000">'<span style="color: #800000">Delete<span style="color: #800000">'<span style="color: #000000">,convert(SMALLINT,N<span style="color: #800000">'<span style="color: #800000">TABLEInsertTriggerCount<span style="color: #800000">')) AS <span style="color: #800000">'<span style="color: #800000">Insert<span style="color: #800000">'<span style="color: #000000">,N<span style="color: #800000">'<span style="color: #800000">TABLEUpdateTriggerCount<span style="color: #800000">')) AS <span style="color: #800000">'<span style="color: #800000">Update<span style="color: #800000">'<span style="color: #000000"> FROM (SELECT count(*<span style="color: #000000">) AS triggers,parent_ID FROM sys.triggers
--<span style="color: #000000">查询结果如下: Table triggers Delete Insert Update -------------------------------- ----------- ------ ------ ------<span style="color: #000000"> Purchasing.Vendor <span style="color: #800080">1 <span style="color: #800080">0 <span style="color: #800080">0 <span style="color: #800080">0<span style="color: #000000"> Production.WorkOrder <span style="color: #800080">2 <span style="color: #800080">0 <span style="color: #800080">1 <span style="color: #800080">1<span style="color: #000000"> Purchasing.PurchaSEOrderDetail <span style="color: #800080">2 <span style="color: #800080">0 <span style="color: #800080">1 <span style="color: #800080">1<span style="color: #000000"> Purchasing.PurchaSEOrderHeader <span style="color: #800080">1 <span style="color: #800080">0 <span style="color: #800080">0 <span style="color: #800080">1<span style="color: #000000"> Sales.SalesOrderDetail <span style="color: #800080">1 <span style="color: #800080">1 <span style="color: #800080">1 <span style="color: #800080">1<span style="color: #000000"> HumanResources.Employee <span style="color: #800080">1 <span style="color: #800080">0 <span style="color: #800080">0 <span style="color: #800080">0<span style="color: #000000"> Sales.SalesOrderHeader <span style="color: #800080">1 <span style="color: #800080">0 <span style="color: #800080">0 <span style="color: #800080">1<span style="color: #000000"> Person.Person <span style="color: #800080">1 <span style="color: #800080">0 <span style="color: #800080">1 <span style="color: #800080">1<span style="color: #000000"> (<span style="color: #800080">8 row(s) affected) 如果超过一个触发器被触发在一个表上,它们不保证顺序,当然也可以使用sp_settriggerorder来控制顺序。通过使用objectpropertyex()元数据函数,需要根据事件输入参数‘ExecIsLastDeleteTrigger’,‘ExecIsLastInsertTrigger’ 或者 ‘ExecIsLastUpdateTrigger’来确认谁是最后一个执行的触发器 。为了得到第一个触发器,酌情使用ObjectPropertyEx() 元数据函数,需要输入参数 ‘ExecIsFirstDeleteTrigger’,‘ExecIsFirstInsertTrigger’ 或者 ‘ExecIsFirstUpdateTrigger’。 因此我们现在知道了表有哪些触发器,哪些事件触发这些触发器。可以使用objectpropertyex()元数据函数,这个函数返回很多不同信息,根据指定的参数不同。通过查看MSDN中的文档,查看其中的一个文档是否有助于元数据查询,总是值得检查的。 触发器何时触发事件?让我们看一下这些触发器,DML触发器可以在所有其他时间发生后触发,但是可以在约束被处理前并且触发INSTEAD OF触发动作。下面我们就来看看所有的触发的到底是AFTER 还是INSTEAD OF 触发器,有事什么时间触发了触发器。 SELECTconvert(CHAR( <span style="color: #800080">25<span style="color: #000000">),name) AS triggerName,convert(CHAR(<span style="color: #800080">32),<span style="color: #800000">'<span style="color: #800000">Database (<span style="color: #800000">'+db_name()+<span style="color: #800000">'<span style="color: #800000">)<span style="color: #800000">'<span style="color: #000000">)) AS TheParent,is_disabled,CASE WHEN is_instead_of_trigger=<span style="color: #800080">1 THEN <span style="color: #800000">'<span style="color: #800000">INSTEAD OF <span style="color: #800000">' ELSE <span style="color: #800000">'<span style="color: #800000">AFTER <span style="color: #800000">'<span style="color: #000000"> END
FROM sys.triggers; 结果如下: ------------------------- -------------------------------- ----------- ---------<span style="color: #000000">ddlDatabaseTriggerLog Database (AdventureWorks2012) <span style="color: #800080">1<span style="color: #000000"> AFTER CREATE_TABLE,ALTER_TABLE,DROP_TABLE,CREATE_VIEW,ALTER_VIEW,DROP_VIEW,CREATE_INDEX,ALTER_INDEX,DROP_INDEX,CREATE_XML_INDEX,ALTER_FULLTEXT_INDEX,CREATE_FULLTEXT_INDEX,DROP_FULLTEXT_INDEX,CREATE_SPATIAL_INDEX,CREATE_STATISTICS,UPDATE_STAT t_AB dbo.AB <span style="color: #800080">0<span style="color: #000000"> INSTEAD OF INSERT dEmployee HumanResources.Employee <span style="color: #800080">0<span style="color: #000000"> INSTEAD OF DELETE iuPerson Person.Person <span style="color: #800080">0<span style="color: #000000"> AFTER INSERT,UPDATE iPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail <span style="color: #800080">0<span style="color: #000000"> AFTER INSERT uPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail <span style="color: #800080">0<span style="color: #000000"> AFTER UPDATE uPurchaSEOrderHeader Purchasing.PurchaSEOrderHeader <span style="color: #800080">0<span style="color: #000000"> AFTER UPDATE iduSalesOrderDetail Sales.SalesOrderDetail <span style="color: #800080">0<span style="color: #000000"> AFTER INSERT,DELETE uSalesOrderHeader Sales.SalesOrderHeader <span style="color: #800080">0<span style="color: #000000"> AFTER UPDATE dVendor Purchasing.Vendor <span style="color: #800080">0<span style="color: #000000"> INSTEAD OF DELETE iWorkOrder Production.WorkOrder <span style="color: #800080">0<span style="color: #000000"> AFTER INSERT uWorkOrder Production.WorkOrder <span style="color: #800080">0 AFTER UPDATE As you will notice,we used here to make a list of the events for each trigger to make it easier to read. These events were pulled from the sys.trigger_events view using a correlated subquery. 注意到我们使用了来列出事件的每一个触发器,更容易读取理解。sys.trigger_events使用相关子查询来查询这些事件。 触发器的多长?许多数据库人员不赞成冗长触发器的定义,但他们可能会发现,根据定义的长度排序的触发器列表是研究数据库的一种有用方法。 SELECT convert(CHAR(),coalesce(object_schema_name(t.object_ID)+,</span>+<span style="color: #000000">name) AS TheTrigger,<span style="color: #800000">'</span><span style="color: #800000">Database (</span><span style="color: #800000">'</span>+db_name()+<span style="color: #800000">'</span><span style="color: #800000">)</span><span style="color: #800000">'</span><span style="color: #000000">)) AS theParent,len(definition) AS length </span>--<span style="color: #000000">the length of the definition
FROM sys.SQL_modules m INNER JOIN sys.triggers t
ORDER BY length DESC; 访问sys.SQL_modules视图可以查看触发器定义的SQL DDL,并按大小顺序列出它们,最上面是最大的。 结果: -------------------------------- -------------------------------- --------<span style="color: #000000">Sales.iduSalesOrderDetail Sales.SalesOrderDetail <span style="color: #800080">3666<span style="color: #000000">Sales.uSalesOrderHeader Sales.SalesOrderHeader <span style="color: #800080">2907<span style="color: #000000">Purchasing.uPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail <span style="color: #800080">2657<span style="color: #000000">Purchasing.iPurchaSEOrderDetail Purchasing.PurchaSEOrderDetail <span style="color: #800080">1967<span style="color: #000000"> Person.iuPerson Person.Person <span style="color: #800080">1498<span style="color: #000000"> ddlDatabaseTriggerLog Database (AdventureWorks2012) <span style="color: #800080">1235<span style="color: #000000"> Purchasing.dVendor Purchasing.Vendor <span style="color: #800080">1103<span style="color: #000000"> Production.uWorkOrder Production.WorkOrder <span style="color: #800080">1103<span style="color: #000000"> Purchasing.uPurchaSEOrderHeader Purchasing.PurchaSEOrderHeader <span style="color: #800080">1085<span style="color: #000000"> Production.iWorkOrder Production.WorkOrder <span style="color: #800080">1011<span style="color: #000000"> HumanResources.dEmployee HumanResources.Employee <span style="color: #800080">604 好吧,我可能太挑剔了,不太喜欢太长的,但是逻辑有时候会很长。事实上,前三名在我看来是不可靠的,尽管我总是倾向于尽可能少地使用触发器。 这些触发器访问了多少对象在代码中,每个触发器要访问多少对象(比如表和函数)? 我们只需要检查表达式依赖项。这个查询使用一个视图来列出“软”依赖项(如触发器、视图和函数)。 </span>+<span style="color: #800000">'</span><span style="color: #800000">.</span><span style="color: #800000">'</span>,<span style="color: #800000">''</span>)+convert(CHAR(<span style="color: #800080">32</span><span style="color: #000000">),name) AS TheTrigger,count(</span>*<span style="color: #000000">) AS Dependencies
FROM sys.triggers INNER JOIN sys.SQL_Expression_dependencies ON [referencing_id] =<span style="color: #000000">object_IDGROUP BY name,parent_id ORDER BY count(*<span style="color: #000000">) DESC; TheTrigger Dependencies ---------------------------------------- ------------<span style="color: #000000"> Sales.iduSalesOrderDetail <span style="color: #800080">7<span style="color: #000000"> Sales.uSalesOrderHeader <span style="color: #800080">7<span style="color: #000000"> Purchasing.iPurchaSEOrderDetail <span style="color: #800080">5<span style="color: #000000"> Purchasing.uPurchaSEOrderDetail <span style="color: #800080">5<span style="color: #000000"> Purchasing.uPurchaSEOrderHeader <span style="color: #800080">3<span style="color: #000000"> Production.iWorkOrder <span style="color: #800080">3<span style="color: #000000"> Production.uWorkOrder <span style="color: #800080">3<span style="color: #000000"> dbo.t_AB <span style="color: #800080">2<span style="color: #000000"> Purchasing.dVendor <span style="color: #800080">2<span style="color: #000000"> Person.iuPerson <span style="color: #800080">2<span style="color: #000000"> ddlDatabaseTriggerLog <span style="color: #800080">1 居然有两个触发器有7个依赖!让我们就Sales.iduSalesOrderDetail来实际看一下,有哪些依赖。 特定触发器访问或者写入哪些对象?我们可以列出触发器在代码中引用的所有对象 convert(<span style="color: #0000ff">char(<span style="color: #800080">32),name) <span style="color: #0000ff">as<span style="color: #000000"> TheTrigger,convert(<span style="color: #0000ff">char(<span style="color: #800080">32),coalesce([referenced_server_name]+<span style="color: #800000">'<span style="color: #800000">.<span style="color: #800000">',<span style="color: #800000">''<span style="color: #000000">)
FROM sys.triggers INNER JOIN sys.SQL_Expression_dependencies ON [referencing_id]=<span style="color: #000000">object_ID WHERE name LIKE <span style="color: #800000">'<span style="color: #800000">iduSalesOrderDetail<span style="color: #800000">'<span style="color: #000000">; --<span style="color: #000000">查询结果: TheTrigger referencedObject -------------------------------- --------------------------------<span style="color: #000000"> iduSalesOrderDetail Sales.Customer iduSalesOrderDetail Person.Person iduSalesOrderDetail Sales.SalesOrderDetail iduSalesOrderDetail Sales.SalesOrderHeader iduSalesOrderDetail Production.TransactionHistory iduSalesOrderDetail dbo.uspLogError iduSalesOrderDetail dbo.uspPrintError 触发器里有什么代码?现在让我们通过检查触发器的源代码来确认这一点。. SELECT OBJECT_DEFINITION ( object_id() );我们之前的查询是正确的,扫描源码可知所有的依赖项。大量依赖项表名对于数据库的重构等需要非常小心,例如,修改一个基础表的列。 据需要做什么,您可能希望检查来自元数据视图的定义,而不是使用OBJECT_DEFINITION函数。 FROM sys.SQL_modules mINNER JOIN sys.triggers t
WHERE t.object_ID =object_id(<span style="color: #800000">'<span style="color: #800000">sales.iduSalesOrderDetail<span style="color: #800000">');搜索触发器的代码There are always plenty of ways of using the metadata views and functions. I wonder if all these triggers are executing that uspPrintError procedure? 有很多使用元数据视图和函数的方法。想知道是否所有这些触发器都执行uspPrintError存储过程? /*?在所有触发器中搜索字符串 */<div class="cnblogs_code"> SELECT convert(CHAR(),coalesce(object_schema_name(object_ID)+,
FROM (SELECT name,definition,t.object_ID,charindex(<span style="color: #800000">'<span style="color: #800000">EXECUTE [dbo].[uspPrintError]<span style="color: #800000">'<span style="color: #000000">,definition) AS hit FROM sys.SQL_modules m
WHERE hit><span style="color: #800080">0; 结果如图: 8个引用正在执行这个过程。我们在sys.SQL_modules中搜索了所有的定义可以找到一个特定的字符串,这种方式很慢很暴力,但是它是有效的! 在所有对象中搜索字符串我想知道除了触发器之外是否还有其他对象调用这个过程?我们稍微修改查询以搜索sys.objects视图,而不是sys.triggers,以搜索所有具有与之关联的代码的对象。我们还需要显示对象的类型 /*?在所有对象中搜索字符串 */ SELECT convert(CHAR(),</span>+object_name(object_ID)) AS TheObject,type_desc,<span style="color: #800080">120</span>)+<span style="color: #800000">'</span><span style="color: #800000">...</span><span style="color: #800000">'</span> <span style="color: #0000ff">as</span><span style="color: #000000"> TheExtract
FROM (SELECT type_desc,o.object_ID,charindex( <span style="color: #800000">'<span style="color: #800000">uspPrintError<span style="color: #800000">'<span style="color: #000000">,definition) AS hitFROM sys.SQL_modules m
WHERE hit><span style="color: #800080">0; 查询结果如下图: ?From this output we can see that,other than the procedure itself where it is defined,and the triggers,only dbo.uspLogError is executing the uspPrintError procedure. (see the first column,second line down) 从这个输出中我们可以看到,除了在定义它的过程本身之外,还有触发器,只有dbo.uspLogError正在执行uspPrintError过程。(见第一列,第二行往下) 列出服务器级触发器及其定义我们可以通过系统视图了解它们吗?嗯,是的。以下是列出服务器触发器及其定义的语句 FROM sys.server_SQL_modules mINNER JOIN sys.server_triggers t ON t.object_ID =m.object_ID;注意,只能看到有权限看的触发器 总结本文讨论过触发器,并且你能查出触发器,以及潜在的问题。这里并没有针对关于触发器的查询提供一个全面的工具箱,因为我只是使用触发器作为示例来展示在查询系统视图时可能使用的一些技术。在我们学习了索引、列和参数之后,我们将回到触发器,并了解了编写访问系统视图和information schema视图的查询的一些日常用途。表是元数据的许多方面的基础。它们是几种类型的对象的父类,其他元数据如索引是表的属性。我们正在慢慢地努力去发现所有关于表的信息。期待下期 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |