获取返回错误的存储过程的模式

问题描述 投票:0回答:2

我有几个相同名称但程序不同的程序。当这些过程引发错误时,父进程(调用这些嵌套的存储过程)可能会获得引发错误的过程的模式吗?例如,我可以从ERROR_PROCEDURE()获得名称,但是还有一些选项可以获得SCHEMA吗?因为否则我不确定如果有许多具有相同名称的错误,那么确切的过程会引发错误。

我想这个功能仍然缺少https://connect.microsoft.com/SQLServer/feedback/details/124627/schema-not-reported-in-the-error-procedure-function

但是有一些解决方法吗?

sql-server-2008 tsql error-handling database-schema
2个回答
0
投票

我能想到的一些可能的解决方案:

  • 重命名每个存储过程,以便它们在不同的模式中具有不同的名称。
  • 将一些调试输出添加到存储过程,以便在执行它们时,您可以在发生错误时查看哪个正在进行中。
  • 运行SQL事件探查器以查看错误发生时正在调用的内容。

但是,这些更多来自于尝试解决您现在遇到的问题,而不是构建一些错误处理,以便将来进行故障排除。您总是可以使用这些存储过程将某些日志文件写入磁盘,以便在遇到错误时可以查询这些日志。


1
投票

遗憾的是,SQL-Server中没有针对此限制的100%解决方法。 对MSSQL开发团队感到羞耻,因为没有对此进行纠正,以后会在十年内完成。 它应该像添加像ERROR_ProcedureSchema()ERROR_PROCID()这样的新函数一样简单。 这是从2005年5月开始请求此功能的复活帖子: https://feedback.azure.com/forums/908035-sql-server/suggestions/32894584-schema-not-reported-in-the-error-procedure-functio

我更喜欢尽可能详细地记录我在自定义错误处理逻辑中捕获的异常。 这是我能找到的最好的Schema名称:

DECLARE @Error_ProcSchemaName nVarChar(128)--Leave as Null if found in more than 1 Schema.
--Only Populate the @Error_ProcSchemaName if it Belongs to 1 Schema. - 04/08/2019 - MCR.
SELECT @Error_ProcSchemaName = S.name
  FROM sys.objects as O
  JOIN sys.schemas as S
    ON S.schema_id = O.schema_id
  JOIN
  (
    SELECT O.name[ObjectName], COUNT(*)[Occurrences]
      FROM sys.objects as O
     GROUP BY O.name
  ) AS Total
    ON Total.ObjectName = O.name
 WHERE O.name = ERROR_PROCEDURE()
   AND Total.Occurrences = 1

避免使用像OBJECT_SCHEMA_NAME(OBJECT_ID(ERROR_PROCEDURE()))这样的字符串,因为传入OBJECT_ID()的字符串应该已经包含了Schema(ERROR_PROCEDURE()没有)。 否则它将默认为您的默认架构,在大多数情况下,它是dbo

运行此查询以查看在架构中重用的所有对象名称:

--View Object Names that Exist in Multiple Schemas: - 04/08/2019 - MCR.
SELECT S.name[SchemaName], O.name[ObjectName], Total.Occurrences,
       O.type[Type], O.type_desc[TypeDesc],
       O.object_id[ObjectID], O.principal_id[PrincipalID], O.parent_object_id[ParentID],
       O.is_ms_shipped[MS], O.create_date[Created], O.modify_date[Modified]
  FROM sys.objects as O
  JOIN sys.schemas as S
    ON S.schema_id = O.schema_id
  JOIN
  (
    SELECT O.name[ObjectName], COUNT(*)[Occurrences]
      FROM sys.objects as O
     GROUP BY O.name
  ) AS Total
    ON Total.ObjectName = O.name
 WHERE Total.Occurrences > 1
 ORDER BY [ObjectName], [SchemaName]

如果你只有几个重叠的对象(Sprocs和Triggers),那么你可能不知道Schema,因为它可能是显而易见的。 但是,如果不是这种情况,那么您可能需要:

  1. 更改Sproc / Trigger的名称以使其成为唯一。 这个选项违背了我的存在。
  2. 如果您使用的是高级错误处理,则在记录错误时,在Catch-Block中手动添加带有OBJECT_SCHEMA_NAME(@@PROCID)的Sproc / Trigger的Schema。

注意:由于使用了不允许编辑的第三方Sproc,可能无法使用这些选项。 使用共享相同名称的多个Sprocs / Triggers进行故障排除时,您可以编写一个Custom Wrapper-Sproc来调用您的第三方Sproc,然后记录Wrapper中抛出的任何异常,以确切知道哪个Schema / Sproc引起了它。

守则气味: 如果您有多个Sprocs / Triggers具有相同的名称,分布在不同的Schema中 然后我会称之为“代码嗅觉”。 意思是,您的架构存在缺陷。 您可能无法正确封装逻辑以供重用。 有时名称会与Schemas重叠,但这应该是罕见的,而且只是巧合。

挪用模式处理多租户/用户组访问: 如果您正在尝试多租户(在同一数据库中存储来自不同组织/用户组的数据并阻止他们查看彼此的信息)并在每个共享对象名称的模式中运行几乎相同的逻辑,那么这就是设计问题。 如果用户将直接访问它,您应该将数据放在不同的数据库中 或者有一个TenantIDUserGroupID,当用户从自定义应用程序访问时,你总是传入并过滤到任何地方。

© www.soinside.com 2019 - 2024. All rights reserved.