16

我目前的观点是不,更喜欢 Transact SQL 存储过程,因为它们重量更轻且(可能)性能更高的选项,而 CLR 过程允许开发人员进行各种恶作剧。

但是最近我需要调试一些写得很糟糕的 TSQL 存储过程。像往常一样,我发现许多问题是由于原始开发人员没有真正的 TSQL 经验,他们专注于 ASP.NET / C#。

因此,使用 CLR 程序首先会为这类开发人员提供更熟悉的工具集,其次,调试和测试工具更强大(即 Visual Studio 而非 SQL Management Studio)。

我很想听听您的经历,因为这似乎不是一个简单的选择。

4

12 回答 12

15

编写良好、经过深思熟虑的 T-SQL 和 CLR 都有位置。如果某些函数不经常调用并且如果它需要 SQL Server 2000 中的扩展过程,CLR 可能是一个选项。在数据旁边运行诸如计算之类的东西也可能很有吸引力。但是通过引入新技术来解决糟糕的程序员听起来是个坏主意。

于 2008-09-12T02:36:20.833 回答
12

CLR 存储过程并不意味着取代基于集合的查询。如果您需要查询数据库,您仍然需要将 SQL 放入您的 CLR 代码中,就像它嵌入在常规代码中一样。这将是白费力气。

CLR 存储过程有两个主要用途:1) 与操作系统交互,例如从文件读取或在 MSMQ 中删除消息,以及 2) 执行复杂的计算,尤其是当您已经用 .NET 语言编写代码时做计算。

于 2008-09-12T02:34:30.887 回答
7

在 SQL Server 中托管 CLR 旨在为数据库开发人员在他们寻求完成任务的方式上提供更灵活的选择。就像其他人提到的那样,SQL 非常适合对数据集进行操作和修改。任何使用复杂的业务/域规则进行过大型应用程序开发的人都可能会告诉您 - 尝试使用纯 SQL(有时在单个宏查询中)强制执行其中的一些规则可能会成为真正的噩梦。

只有某些任务可以以程序或 OO 方式更好地处理。通过选择使用 .NET 代码来分解逻辑序列,查询操作可以变得更易于阅读和调试。使用 CLR 存储过程后,我可以告诉您逐步使用调试器确实可以更轻松地跟踪数据库级别发生的事情。

仅举一个例子,我们在这里经常使用 CLR 存储过程作为动态搜索查询的“网关”。假设一个搜索请求最多可以有 30 个不同的搜索参数。用户显然不会使用全部 30 个,所以传入的数据结构会有 30 个参数,但大多是 DBNULL。出于明显的安全原因,客户端无法生成动态语句。生成的动态语句在内部生成,无需担心外部“额外”。

于 2008-09-12T03:57:10.483 回答
4

通常,如果您有一些不需要与数据库进行太多交互的东西,则可以使用 CLR。因此,假设您正在解析或解码一个值。这在 CLR 中更容易做到,然后返回值。

尝试在 CLR 中进行复杂查询并不是可行的方法。

顺便说一句,这在 2008 年也没有改变。

于 2008-09-12T02:31:56.430 回答
4

我相信这两者并不等同......适合相互对抗。
CLR 集成应该逐步淘汰过去的“扩展存储过程”。我们的工作场所中有一些这样的......本质上是对 SQL 数据的处理/逻辑块,这些块通过传统的 DB 存储过程/T SQL 太难/不可能完成。因此,他们将其编写为 C++ DLL 中的扩展存储过程,可以类似地调用。 现在它们已被淘汰,CLR 集成是替代品

  • DB存储过程:如果可以在T SQL Stored procs中完成,就去做。
  • CLR 存储过程:如果逻辑过于复杂或繁琐而无法通过 T SQL 执行...方法。
于 2008-09-12T05:45:00.083 回答
4

除了文件系统访问(CLR procs 具有非常明显的优势),我会使用 T-SQL procs。如果您有特别复杂的计算,您可以将该部分放入 CLR函数中并从您的 proc 中调用它(udf 是我发现 CLR 集成真正闪耀的地方)。然后,您可以为任务的特定部分获得 CLR 集成的好处,但尽可能多地将存储的过程逻辑保留在数据库中。

于 2008-09-12T16:31:16.880 回答
3

鉴于您所说,我宁愿您让开发人员在 t-SQl 和一般数据库方面接受适当的培训,也不愿允许他们通过允许他们在 CLR 中执行 t-sql 任务来对性能造成更大的损害。不了解数据库的开发人员以此为借口避免以最有利于数据库性能的方式做事,因为他们希望采用他们认为更容易的方式。

于 2009-01-13T17:40:15.360 回答
2

它总是归结为适合这项工作的正确工具,因此这实际上取决于您要完成的工作。

但是,作为一般规则,您是对的,CLR proc 具有更大的开销,并且永远不会在 T-SQL 之类的集合操作上执行。我的指导方针是全部在 T-SQL 中完成,除非你需要的东西在 T-SQL 中变得过于复杂。然后,更加努力地让 T-SQL 方法发挥作用。:-)

CLR proc 很棒并且确实有它们的位置,但它们的使用应该是例外,而不是规则。

于 2008-09-12T03:18:07.643 回答
2

SQL Server 联机丛书的主题页面列出了这些好处:

  • 更好的编程模型。.NET Framework 语言在许多方面都比 Transact-SQL 更丰富,提供了以前 SQL Server 开发人员无法使用的结构和功能。开发人员还可以利用 .NET Framework 库的强大功能,它提供了一组广泛的类,可用于快速有效地解决编程问题。

  • 提高了安全性和安保性。托管代码在由数据库引擎托管的公共语言运行时环境中运行。SQL Server 利用这一点为早期版本的 SQL Server 中可用的扩展存储过程提供更安全的替代方案。

  • 能够定义数据类型和聚合函数。用户定义类型和用户定义聚合是两个新的托管数据库对象,它们扩展了 SQL Server 的存储和查询能力。

  • 通过标准化环境简化开发。数据库开发集成到 Microsoft Visual Studio .NET 开发环境的未来版本中。开发人员使用与编写中间层或客户端层 .NET Framework 组件和服务相同的工具来开发和调试数据库对象和脚本。

  • 提高性能和可扩展性的潜力。在许多情况下,.NET Framework 语言编译和执行模型提供了优于 Transact-SQL 的性能。

于 2008-09-12T04:10:57.877 回答
2

我们遇到了一个 CLR 函数的情况,该函数在常规 SQL 过程中被调用了数千次。这是从另一个系统导入数据的过程。该函数验证了数据并很好地处理了空值。

如果我们在 TSQL 中进行操作,proc 大约在 15 秒内完成。如果我们使用 CLR 函数,proc 会在 20 - 40 分钟内完成。CLR 函数看起来更优雅,但据我们所知,每次使用 CLR 函数都会触发一次启动。因此,如果您使用一个 CLR 函数完成了一项大型操作,那很好,因为与操作时间相比,启动时间很短。或者,如果您调用 CLR 函数的次数不多,则该函数的所有调用的总启动时间会很短。但要小心循环。

此外,为了可维护性,最好不要使用比您真正需要的更多的语言。

于 2012-09-25T22:06:37.693 回答
0

我会添加几个可能没有提到的使用 CLR 的原因。

  • 替换和扩展基本查询、非查询和标量 sql 函数。
    A) 可以根据定义的要求集成错误报告和警报。B) 轻松定义调试级别。C) 以更简单的方式与外部 SQL 服务器交互
  • 将遗留代码移至托管环境。
于 2014-07-14T20:47:17.770 回答
0

我对类似问题发布了以下答案:SQL SERVER CLR 的优势。不过,我将在这里补充一点,C#/VB.net/etc 是一种比 T-SQL 更适合的语言,应该成为使用 SQLCLR 而不是 T-SQL 的理由。如果有人不知道如何在 T-SQL 中完成某事,请首先寻求帮助以找到 T-SQL 解决方案。如果不存在,走 CLR 路线。


SQL Server 中的 SQLCLR / CLR 集成只是帮助解决某些(不是全部)问题的另一种工具。有些事情它比纯 T-SQL 做得更好,有些事情只能通过 SQLCLR 完成。我为 SQL Server Central 写了一篇文章,Stairway to SQLCLR Level 1:什么是 SQLCLR?(需要免费注册才能阅读那里的文章),这解决了这个问题。基础知识是(有关详细信息,请参阅链接的文章):

  • 流表值函数 (sTVF)
  • 动态 SQL(在函数内)
  • 更好地访问外部资源/替换 xp_cmdshell
    • 传入数据更容易
    • 取回结果集的多列更容易
    • 没有外部依赖(例如 7zip.exe)
    • 通过模拟提高安全性
  • 多线程能力
  • 错误处理(函数内)
  • 自定义聚合
  • 自定义类型
  • 修改状态(在函数内且不带OPENQUERY/ OPENROWSET
  • 执行存储过程(只读;在函数内且不带OPENQUERY/ OPENROWSET
  • 性能(注意:并不是在所有情况下都有意义,但在某些情况下肯定取决于操作的类型和复杂性)
  • 可以捕获输出(即发送到 SSMS 中的“消息”选项卡的内容)(例如,PRINT严重性= 0 到 10)——我忘了​​在文章中提到这一点 ;-)。RAISERROR

要考虑的另一件事是,有时能够在应用程序和数据库之间共享代码是有益的,这样数据库就可以深入了解某些业务逻辑,而无需构建自定义的、仅限内部的屏幕来访问该应用程序代码。例如,我曾在一个系统上工作,该系统从客户那里导入数据文件,并使用大多数字段的自定义散列并将该值保存到数据库中的行中。这允许在再次导入数据时轻松跳过行,因为应用程序将从输入文件中散列值并与存储在行中的散列值进行比较。如果它们相同,那么我们立即知道所有字段都没有改变,所以我们进入下一行,这是一个简单的 INT 比较。但是用于进行哈希的算法仅在应用程序代码中,因此无论是用于调试客户案例还是通过标记至少有一个字段发生更改的行(来自我们的应用程序的更改)来寻找将某些处理卸载到后端服务的方法与在较新的导入文件中查找更改相反),我无能为力。这将是一个在数据库中拥有相当简单的业务逻辑的绝佳机会,即使不是用于正常处理;在数据库中拥有相当于编码值而无法理解其含义的内容使得解决问题变得非常困难。这将是一个在数据库中拥有相当简单的业务逻辑的绝佳机会,即使不是用于正常处理;在数据库中拥有相当于编码值而无法理解其含义的内容使得解决问题变得非常困难。这将是一个在数据库中拥有相当简单的业务逻辑的绝佳机会,即使不是用于正常处理;在数据库中拥有相当于编码值而无法理解其含义的内容使得解决问题变得非常困难。

如果有兴趣在不编写任何代码的情况下查看其中的一些功能,SQL#(我是其作者)的免费版本具有 RegEx 函数、自定义聚合 (UDA)、自定义类型 (UDT) 等。

于 2014-07-17T20:10:32.590 回答