在 SQL 服务器上存储 运行(~10 分钟)长的过程有多危险(performance/resources)?
How dangerous (performance/resources) is it to have long running (~10 minute) stored procedures on SQL Server?
我正在研究在 SQL 服务器上部署一些非资源密集型但已知会长期 运行ning 存储过程的想法。到long 运行ning,我想在10分钟范围内。
它们很长 运行ning 但不是资源密集型的原因是它们通过 C# SQLCLR 代码访问外部系统,这是这些外部系统的性能导致性能问题,SQL 服务器大部分时间都在等待来自外部系统的结果。
我 100% 意识到做这种事情可能是 "not recommended" 在 SQL 服务器上,像 PowerShell 这样的东西会更合适,但我希望将问题限制在是否这样做 实际上对整个 SQL 服务器 performance/resources 造成物理伤害,如果是这样,危害有多大。
在我的场景中,总体服务器负载不会很高,最多可能有 20 个其他查询 运行ning,其中大部分是针对 SQL 表的正常查询 - 最多有可能是 3 个用户 运行ning 这些慢速查询之一。
所以我的问题是:在 SQL 服务器上提供此类查询是否存在任何真正的风险,是否有任何我应该注意的与阻塞、连接等相关的问题?
编辑:
为了便于讨论,假设这是 运行ning 在 4 CPU、8GB RAM 的机器上。
这样做的动机(从业务角度来看)是它有助于使用 SQL 作为访问多个异构外部系统的通用抽象层,从而消除对众多最终用户拥有各种本地专有系统的依赖安装客户端软件,或了解所涉及的各种系统的模糊调用语法。
我真的希望人们不要因为对一个人 "should" 是否这样做的哲学观点而投票结束这个问题。能够使用 SQL 服务器完成此操作具有经济价值。但如果它实际上在技术上是危险的,那么难道就不能描述危险的一些细节吗?
编辑 2
应版主的要求,我将提供一些额外的细节,以缩小我要问的范围。
场景:
我的公司环境中有 20 个不同的系统。这些系统中的每一个都有一个专门的 API,需要安装软件才能访问系统,以及正确语法的专业知识,以便在系统内查询数据。每个系统还有一个可以通过 C# 访问的 API。
由于公司内的每个人都非常熟悉 SQL 服务器,因此为所有这些系统提供行业标准 API 可以在经济上取得优势,从而无需安装特殊软件在每个客户端桌面上,以及最终用户学习复杂语法以查询每个不同系统的要求。在这种情况下,常见的 API 是 SQL 服务器存储过程(作为 C# SQL CLR 存储过程实现,但对调用者来说是完全透明的)。这些过程的接口(参数)简单且有据可查,完全将用户与底层系统调用实现和语法的复杂性隔离开来。
实际调用任何给定底层系统的执行时间从不到 1 秒到长达 10 分钟不等,具体取决于被调用的具体过程和系统。在此 SQL 过程中没有进行额外的昂贵处理,较长的 运行 时间只是等待远程系统完成查询和 return 结果的过程。
典型的结果集大小为 1 到 50,000 行,平均值可能在 1000 行左右。 非常 大的结果集大小为 5 MB。
在任何给定时间,此服务器上最多可能有 25 个并发执行的查询处于活动状态,其中至少有 20 个查询将执行 "regular" TSQL 存储过程读取正常SQL 服务器表驻留在本地数据库中,而其中最多 5 个可能是这些 "special" C# SQL 访问外部系统的 CLR 查询。
所有查询都是读取的,没有写入的,并且没有正在执行的事务性多命令查询。
25 个最大并发查询 x 5 MB 最大结果集大小 = 在任何给定时间内存中最多 125 MB "pure data",加上任何伴随的 SQL 服务器 "overhead".
运行 的典型服务器将是 4 CPU、8GB 内存盒 运行宁 SQL Server 2012。我有极大的余地来大量增加如果我这样选择,这个盒子的力量 - 在这种情况下没有预算限制。
那么,考虑到这个场景,有没有人知道任何具体技术原因为什么这个实现不起作用,或者合理的推测某些技术限制可能出现在哪里?
顺便说一句......我不知道是否有人听过 Jeff 和 Joel 在 SO 首次开发时所做的 Whosebug 播客,但这个问题有点让人想起 Joel 告诉哪里的轶事他问的是在 SQL 服务器中做一些不寻常的事情(出于非常具体但有效的原因),所有答案基本上都是 "you shouldn't be doing that!" :)
可能感兴趣的人参考:
https://blog.stackexchange.com/2009/01/podcast-38/
https://Whosebug.fogbugz.com/default.asp?pg=pgWiki&command=view&ixWikiPage=29025
SQL Server "AFTER INSERT" trigger doesn't see the just-inserted row
同样,我当然知道这个问题很不寻常,但如果从纯技术角度考虑,我认为它不应该有争议。
Mods:如果这个额外的细节足以减少误解,请告诉我。我真的希望这个问题可以保持开放,因为它是善意的、合法的,并且涉及我认为是 SQL 服务器平台功能的一个非常有趣的边缘案例。
为正确的工作使用正确的工具。在您的测试环境中,一切都会正常运行,但是一旦您离开该环境并转移到生产环境中,您就会被炸死。
作为您的主要数据存储的数据库应该具有高可用性,那些非资源密集型任务将始终快速增加,具体取决于所建立的并发连接数。在设计系统时,请牢记最终用户。
这本身不是问题。根据您的描述,执行将是可靠的。 "Reliable" 从某种意义上说,虽然这不是最佳实践,但它会起作用并且不会随机引起问题。
想到一些问题:
- 如果 SQL 服务器实例出现故障(故障转移、崩溃、重启等),程序将中途终止。你必须同意这一点。 10分钟是很长的时间window所以机会很大。
- 您可以同时 运行 执行多少次此类操作可能存在限制。我不知道具体的限制。如果 N = 3,则它们不适用。
- Long-运行ning 事务会导致日志增长,并可能导致严重的阻塞。
None 这些问题仅仅因为它们的存在就破坏了实例的稳定。这些都是完全正常的事情,只是被 10 分钟的持续时间放大了。
不知道为什么有些评论这么激动。 10 分钟的查询在数据仓库中很常见,这些查询使服务器处于 100% 的负载之下,这比等待 10 分钟还要糟糕。这里没问题。
如果您不同意,请发表评论说明原因。当您从 SQL 服务器发出 Web 服务调用时,请说明 究竟是什么 导致了问题。
鉴于在所有情况下:
- 只能访问外部系统
- 访问权限为只读
那么,从概念上讲,SQL服务器的稳定性应该没有特定的内在危险。但是,有几件事需要考虑 and/or 注意:
A C# API 表示您添加作为对项目的引用的 DLL,对吗?这个第 3 方 DLL 需要与您的 DLL 一起加载到 SQL 服务器中。这就是事情变得棘手的地方。可以安全地假设 DLL 将通过网络与其他服务器进行通信,因此至少需要将其标记为 WITH PERMISSION_SET = EXTERNAL_ACCESS
。
- 理想情况下,您将使用您(希望)用于程序集的相同
.pfx
文件对第 3 方 DLL 进行签名。如果 3rd 方 DLL 已经签名,我想你可以重新签名。
- 这个第 3 方 DLL 是否正确清理了它的外部资源?打开外部资源而不正确处理它们可能会导致问题。 GC 可能会清理孤立的外部文件和网络句柄,但我相信当 class 没有更多引用时会发生这种情况,而且我不确定包含SQLCLR 方法将保持活动状态,直到应用程序域被卸载。
- 如果 API DLL 正在建立 HTTP 连接,它将限制可以与特定 URI 建立多少连接。虽然这对于 Windows 应用程序或控制台应用程序可能不是问题(因为它们都有自己的应用程序域),但在 SQLCLR 中这是一个问题,因为只有一个应用程序域(对于在所有会话(即 SPID)之间共享的特定程序集)。默认限制是 2 个到给定 URI 的连接。如果您有 3 个会话同时点击同一个 API 调用,则第 3 个将被阻止或获得异常。幸运的是,这可以通过 ServicePointManager.DefaultConnectionLimit 属性.
配置
- API DLL 是否使用任何标有主机保护属性 (HPA) 的方法?当您通过 CREATE ASSEMBLY 加载 DLL 时,或者您的代码调用 API 方法时,您会发现它正在使用标有 HPA 的东西。如果是这样,您需要将 API DLL 和程序集标记为
UNSAFE
。这里的风险取决于特定的 HPA。例如,通过 TimeZoneInfo
进行时区转换有潜在的内存泄漏,因此它被标记为 MayLeakOnAbort
.
- API DLL 是否将值存储在静态 class 变量中? SQL 当您发出
CREATE ASSEMBLY
而未将程序集设置为 UNSAFE
时,服务器会通知您 DLL 是否执行此操作。虽然将程序集设置为 UNSAFE
将允许它工作,但您现在有可能访问静态变量的多个会话 运行ning 代码将遇到 "odd" 行为并可能得到不正确的结果。同样,问题是所有会话共享一个应用程序域,因此为什么需要 UNSAFE
才能使用静态变量。唯一可以缓解此问题的方法是在任何使用静态变量的 API 调用周围放置一个 lock
。但是,这不是绝对的解决方法,因为静态变量可能会在不同的 API 调用中使用。存储值对于一个特定会话继续使用可能有意义,但在会话之间不正确。
- API DLL 是否引用了任何不在 Supported .NET Framework Libraries 列表中的库?如果是这样,您还需要将它们加载到 SQL 服务器中。但是,请记住,您不能保证能够将任何不受支持的 .NET Framework DLL 加载到 SQL 服务器中。 SQL 服务器仅允许纯程序集(即仅托管代码)。无法加载混合的 DLL(托管和非托管 C++ 代码)。即使不受支持的 Framework DLL 是纯的并且现在可以加载,在未来的 .NET 版本中也可能会发生变化。事实上,这以前发生过。风险范围是任何使用 CLR 4.0 版的框架更新(这是 SQL Server 2012、2014 和 2016 所绑定的)。
- API DLL 是纯的(仅限托管代码)还是混合的(托管和非托管 C++)?如果混入了3rd party DLL,那么无论如何都加载不出来
但是,如果您处理的是 Web 服务 API,那么顾虑就会大大减少。
- 您需要使用
EXTERNAL_ACCESS
- 您需要确保正确
Dispose()
可以处理的所有对象。
- 您需要设置ServicePointManager.DefaultConnectionLimit属性。同样,对于任何特定方法,都有一个在所有会话之间共享的应用程序域。
DefaultConnectionLimit
的默认值为 2,这可能不够,因为相同的 URI(对于给定的 API 调用)将在多个会话中访问。
关于 SQL 服务器运行状况的一个问题是 SQLCLR 代码可能会锁定调度程序,以便在该进程完成之前它无法执行任何其他操作。这是由于 SQL 服务器使用抢占式多任务处理,这需要线程放弃自己以暂停。如果您的 SQL 服务器代码执行查询,那么这不是问题,但如果它只是在等待来自外部资源的响应,则存在这种可能性。我个人还没有看到调度程序被 SQLCLR 进程锁定,但它仍然是可能的,所以尝试 "play nice" 与 SQL 服务器是个好主意。如果可以对 API 代码进行 async
调用,则可以使用 Timer 每 10 或 100 毫秒(或类似时间)调用 Thread.Sleep(0);
,直到外部进程returns。调用 Thread.Sleep(0);
是 SQLCLR 代码让 SQLOS 知道它(即 SQLCLR 进程)可以暂停的方式。
在 SQLCLR 中执行任何类型的异步工作需要将程序集标记为 UNSAFE
。由于已经提到的各种其他原因,您的程序集很可能已经被标记为 UNSAFE
。但即使不是,如果这是将它们标记为 UNSAFE
的唯一原因,那么它仍然是值得的,尤其是这是一个内部项目。
可以帮助缓解与 UNSAFE
SQLCLR 代码相关的稳定性问题的一个选项(至少对于主 SQL 服务器进程)是隔离它在单独的 SQL 服务器实例中。例如,您可以 运行 一个单独的 SQL Server express 实例,它除了处理这些 API 调用外什么都不做。只要您指定允许 SQL Server Express 实例使用的最大服务器内存,内存泄漏就不会影响主 SQL 服务器实例,只会影响 Express 实例。如果调度程序被长期 运行 外部进程锁定,那么它只会影响 Express 实例。
然后你只需设置一个从主实例到 Express 实例的链接服务器,这样用户就可以在主实例上工作并连接到那里的任何 tables,等等
最后,从可用性的角度来看,考虑制作这些 SQLCLR 对象 Table-Valued Functions 而不是 Stored Procedures。整合他们的结果会容易得多。您不仅可以加入,而且如果有人不想要整个结果集,添加 WHERE
子句比将所有内容转储到临时 table (通过 INSERT...EXEC
) 仅删除不需要的行。
我正在研究在 SQL 服务器上部署一些非资源密集型但已知会长期 运行ning 存储过程的想法。到long 运行ning,我想在10分钟范围内。
它们很长 运行ning 但不是资源密集型的原因是它们通过 C# SQLCLR 代码访问外部系统,这是这些外部系统的性能导致性能问题,SQL 服务器大部分时间都在等待来自外部系统的结果。
我 100% 意识到做这种事情可能是 "not recommended" 在 SQL 服务器上,像 PowerShell 这样的东西会更合适,但我希望将问题限制在是否这样做 实际上对整个 SQL 服务器 performance/resources 造成物理伤害,如果是这样,危害有多大。
在我的场景中,总体服务器负载不会很高,最多可能有 20 个其他查询 运行ning,其中大部分是针对 SQL 表的正常查询 - 最多有可能是 3 个用户 运行ning 这些慢速查询之一。
所以我的问题是:在 SQL 服务器上提供此类查询是否存在任何真正的风险,是否有任何我应该注意的与阻塞、连接等相关的问题?
编辑:
为了便于讨论,假设这是 运行ning 在 4 CPU、8GB RAM 的机器上。
这样做的动机(从业务角度来看)是它有助于使用 SQL 作为访问多个异构外部系统的通用抽象层,从而消除对众多最终用户拥有各种本地专有系统的依赖安装客户端软件,或了解所涉及的各种系统的模糊调用语法。
我真的希望人们不要因为对一个人 "should" 是否这样做的哲学观点而投票结束这个问题。能够使用 SQL 服务器完成此操作具有经济价值。但如果它实际上在技术上是危险的,那么难道就不能描述危险的一些细节吗?
编辑 2 应版主的要求,我将提供一些额外的细节,以缩小我要问的范围。
场景:
我的公司环境中有 20 个不同的系统。这些系统中的每一个都有一个专门的 API,需要安装软件才能访问系统,以及正确语法的专业知识,以便在系统内查询数据。每个系统还有一个可以通过 C# 访问的 API。
由于公司内的每个人都非常熟悉 SQL 服务器,因此为所有这些系统提供行业标准 API 可以在经济上取得优势,从而无需安装特殊软件在每个客户端桌面上,以及最终用户学习复杂语法以查询每个不同系统的要求。在这种情况下,常见的 API 是 SQL 服务器存储过程(作为 C# SQL CLR 存储过程实现,但对调用者来说是完全透明的)。这些过程的接口(参数)简单且有据可查,完全将用户与底层系统调用实现和语法的复杂性隔离开来。
实际调用任何给定底层系统的执行时间从不到 1 秒到长达 10 分钟不等,具体取决于被调用的具体过程和系统。在此 SQL 过程中没有进行额外的昂贵处理,较长的 运行 时间只是等待远程系统完成查询和 return 结果的过程。
典型的结果集大小为 1 到 50,000 行,平均值可能在 1000 行左右。 非常 大的结果集大小为 5 MB。
在任何给定时间,此服务器上最多可能有 25 个并发执行的查询处于活动状态,其中至少有 20 个查询将执行 "regular" TSQL 存储过程读取正常SQL 服务器表驻留在本地数据库中,而其中最多 5 个可能是这些 "special" C# SQL 访问外部系统的 CLR 查询。
所有查询都是读取的,没有写入的,并且没有正在执行的事务性多命令查询。
25 个最大并发查询 x 5 MB 最大结果集大小 = 在任何给定时间内存中最多 125 MB "pure data",加上任何伴随的 SQL 服务器 "overhead".
运行 的典型服务器将是 4 CPU、8GB 内存盒 运行宁 SQL Server 2012。我有极大的余地来大量增加如果我这样选择,这个盒子的力量 - 在这种情况下没有预算限制。
那么,考虑到这个场景,有没有人知道任何具体技术原因为什么这个实现不起作用,或者合理的推测某些技术限制可能出现在哪里?
顺便说一句......我不知道是否有人听过 Jeff 和 Joel 在 SO 首次开发时所做的 Whosebug 播客,但这个问题有点让人想起 Joel 告诉哪里的轶事他问的是在 SQL 服务器中做一些不寻常的事情(出于非常具体但有效的原因),所有答案基本上都是 "you shouldn't be doing that!" :)
可能感兴趣的人参考:
https://blog.stackexchange.com/2009/01/podcast-38/
https://Whosebug.fogbugz.com/default.asp?pg=pgWiki&command=view&ixWikiPage=29025
SQL Server "AFTER INSERT" trigger doesn't see the just-inserted row
同样,我当然知道这个问题很不寻常,但如果从纯技术角度考虑,我认为它不应该有争议。
Mods:如果这个额外的细节足以减少误解,请告诉我。我真的希望这个问题可以保持开放,因为它是善意的、合法的,并且涉及我认为是 SQL 服务器平台功能的一个非常有趣的边缘案例。
为正确的工作使用正确的工具。在您的测试环境中,一切都会正常运行,但是一旦您离开该环境并转移到生产环境中,您就会被炸死。
作为您的主要数据存储的数据库应该具有高可用性,那些非资源密集型任务将始终快速增加,具体取决于所建立的并发连接数。在设计系统时,请牢记最终用户。
这本身不是问题。根据您的描述,执行将是可靠的。 "Reliable" 从某种意义上说,虽然这不是最佳实践,但它会起作用并且不会随机引起问题。
想到一些问题:
- 如果 SQL 服务器实例出现故障(故障转移、崩溃、重启等),程序将中途终止。你必须同意这一点。 10分钟是很长的时间window所以机会很大。
- 您可以同时 运行 执行多少次此类操作可能存在限制。我不知道具体的限制。如果 N = 3,则它们不适用。
- Long-运行ning 事务会导致日志增长,并可能导致严重的阻塞。
None 这些问题仅仅因为它们的存在就破坏了实例的稳定。这些都是完全正常的事情,只是被 10 分钟的持续时间放大了。
不知道为什么有些评论这么激动。 10 分钟的查询在数据仓库中很常见,这些查询使服务器处于 100% 的负载之下,这比等待 10 分钟还要糟糕。这里没问题。
如果您不同意,请发表评论说明原因。当您从 SQL 服务器发出 Web 服务调用时,请说明 究竟是什么 导致了问题。
鉴于在所有情况下:
- 只能访问外部系统
- 访问权限为只读
那么,从概念上讲,SQL服务器的稳定性应该没有特定的内在危险。但是,有几件事需要考虑 and/or 注意:
A C# API 表示您添加作为对项目的引用的 DLL,对吗?这个第 3 方 DLL 需要与您的 DLL 一起加载到 SQL 服务器中。这就是事情变得棘手的地方。可以安全地假设 DLL 将通过网络与其他服务器进行通信,因此至少需要将其标记为
WITH PERMISSION_SET = EXTERNAL_ACCESS
。- 理想情况下,您将使用您(希望)用于程序集的相同
.pfx
文件对第 3 方 DLL 进行签名。如果 3rd 方 DLL 已经签名,我想你可以重新签名。 - 这个第 3 方 DLL 是否正确清理了它的外部资源?打开外部资源而不正确处理它们可能会导致问题。 GC 可能会清理孤立的外部文件和网络句柄,但我相信当 class 没有更多引用时会发生这种情况,而且我不确定包含SQLCLR 方法将保持活动状态,直到应用程序域被卸载。
- 如果 API DLL 正在建立 HTTP 连接,它将限制可以与特定 URI 建立多少连接。虽然这对于 Windows 应用程序或控制台应用程序可能不是问题(因为它们都有自己的应用程序域),但在 SQLCLR 中这是一个问题,因为只有一个应用程序域(对于在所有会话(即 SPID)之间共享的特定程序集)。默认限制是 2 个到给定 URI 的连接。如果您有 3 个会话同时点击同一个 API 调用,则第 3 个将被阻止或获得异常。幸运的是,这可以通过 ServicePointManager.DefaultConnectionLimit 属性. 配置
- API DLL 是否使用任何标有主机保护属性 (HPA) 的方法?当您通过 CREATE ASSEMBLY 加载 DLL 时,或者您的代码调用 API 方法时,您会发现它正在使用标有 HPA 的东西。如果是这样,您需要将 API DLL 和程序集标记为
UNSAFE
。这里的风险取决于特定的 HPA。例如,通过TimeZoneInfo
进行时区转换有潜在的内存泄漏,因此它被标记为MayLeakOnAbort
. - API DLL 是否将值存储在静态 class 变量中? SQL 当您发出
CREATE ASSEMBLY
而未将程序集设置为UNSAFE
时,服务器会通知您 DLL 是否执行此操作。虽然将程序集设置为UNSAFE
将允许它工作,但您现在有可能访问静态变量的多个会话 运行ning 代码将遇到 "odd" 行为并可能得到不正确的结果。同样,问题是所有会话共享一个应用程序域,因此为什么需要UNSAFE
才能使用静态变量。唯一可以缓解此问题的方法是在任何使用静态变量的 API 调用周围放置一个lock
。但是,这不是绝对的解决方法,因为静态变量可能会在不同的 API 调用中使用。存储值对于一个特定会话继续使用可能有意义,但在会话之间不正确。 - API DLL 是否引用了任何不在 Supported .NET Framework Libraries 列表中的库?如果是这样,您还需要将它们加载到 SQL 服务器中。但是,请记住,您不能保证能够将任何不受支持的 .NET Framework DLL 加载到 SQL 服务器中。 SQL 服务器仅允许纯程序集(即仅托管代码)。无法加载混合的 DLL(托管和非托管 C++ 代码)。即使不受支持的 Framework DLL 是纯的并且现在可以加载,在未来的 .NET 版本中也可能会发生变化。事实上,这以前发生过。风险范围是任何使用 CLR 4.0 版的框架更新(这是 SQL Server 2012、2014 和 2016 所绑定的)。
- API DLL 是纯的(仅限托管代码)还是混合的(托管和非托管 C++)?如果混入了3rd party DLL,那么无论如何都加载不出来
- 理想情况下,您将使用您(希望)用于程序集的相同
但是,如果您处理的是 Web 服务 API,那么顾虑就会大大减少。
- 您需要使用
EXTERNAL_ACCESS
- 您需要确保正确
Dispose()
可以处理的所有对象。 - 您需要设置ServicePointManager.DefaultConnectionLimit属性。同样,对于任何特定方法,都有一个在所有会话之间共享的应用程序域。
DefaultConnectionLimit
的默认值为 2,这可能不够,因为相同的 URI(对于给定的 API 调用)将在多个会话中访问。
- 您需要使用
关于 SQL 服务器运行状况的一个问题是 SQLCLR 代码可能会锁定调度程序,以便在该进程完成之前它无法执行任何其他操作。这是由于 SQL 服务器使用抢占式多任务处理,这需要线程放弃自己以暂停。如果您的 SQL 服务器代码执行查询,那么这不是问题,但如果它只是在等待来自外部资源的响应,则存在这种可能性。我个人还没有看到调度程序被 SQLCLR 进程锁定,但它仍然是可能的,所以尝试 "play nice" 与 SQL 服务器是个好主意。如果可以对 API 代码进行
async
调用,则可以使用 Timer 每 10 或 100 毫秒(或类似时间)调用Thread.Sleep(0);
,直到外部进程returns。调用Thread.Sleep(0);
是 SQLCLR 代码让 SQLOS 知道它(即 SQLCLR 进程)可以暂停的方式。在 SQLCLR 中执行任何类型的异步工作需要将程序集标记为
UNSAFE
。由于已经提到的各种其他原因,您的程序集很可能已经被标记为UNSAFE
。但即使不是,如果这是将它们标记为UNSAFE
的唯一原因,那么它仍然是值得的,尤其是这是一个内部项目。可以帮助缓解与
UNSAFE
SQLCLR 代码相关的稳定性问题的一个选项(至少对于主 SQL 服务器进程)是隔离它在单独的 SQL 服务器实例中。例如,您可以 运行 一个单独的 SQL Server express 实例,它除了处理这些 API 调用外什么都不做。只要您指定允许 SQL Server Express 实例使用的最大服务器内存,内存泄漏就不会影响主 SQL 服务器实例,只会影响 Express 实例。如果调度程序被长期 运行 外部进程锁定,那么它只会影响 Express 实例。然后你只需设置一个从主实例到 Express 实例的链接服务器,这样用户就可以在主实例上工作并连接到那里的任何 tables,等等
最后,从可用性的角度来看,考虑制作这些 SQLCLR 对象 Table-Valued Functions 而不是 Stored Procedures。整合他们的结果会容易得多。您不仅可以加入,而且如果有人不想要整个结果集,添加
WHERE
子句比将所有内容转储到临时 table (通过INSERT...EXEC
) 仅删除不需要的行。