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

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

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

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

有帮助吗?

解决方案

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

其他提示

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

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

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

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

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

一般来说,如果您的东西不需要与数据库进行太多交互,则可以使用 CLR。假设您正在解析或解码一个值。这在 CLR 中更容易完成,然后返回值。

尝试在 CLR 中执行 compelx 查询并不是正确的方法。

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

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

  • 数据库存储过程:如果它可以在 T SQL 存储过程中完成,那就这样做。
  • CLR 存储过程:如果逻辑太复杂或繁琐而无法通过 T SQL 完成...如果需要更少的 CLR 代码行来处理它(字符串操作、复杂/自定义排序或过滤等),请使用此方法。

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

鉴于您所说的,我宁愿您对开发人员进行 t-SQl 和数据库方面的适当培训,也不愿允许他们在 CLR 中执行 t-sql 任务,从而对性能造成更大的损害。不了解数据库的开发人员以此为借口,避免以最有利于数据库性能的方式做事,因为他们想采取他们认为更简单的方法。

这始终取决于适合工作的正确工具,因此这实际上取决于您想要完成的任务。

然而,作为一般规则,您是对的,CLR 过程具有更大的开销,并且永远不会像 T-SQL 那样执行集合操作。我的指导方针是在 T-SQL 中完成所有操作,除非您需要的内容在 T-SQL 中变得过于复杂。然后,更加努力地让 T-SQL 方法发挥作用。:-)

CLR 过程很棒并且确实有其用武之地,但它们的使用应该是例外,而不是规则。

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 更高的性能。

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

如果我们在 TSQL 中执行操作,则过程大约需要 15 秒即可完成。如果我们使用 CLR 函数,该过程将在 20 - 40 分钟内完成。CLR 函数看起来更优雅,但据我们所知,每次使用 CLR 函数都会出现启动问题。因此,如果您使用一个 CLR 函数完成一项大型操作,那也没关系,因为与操作时间相比,启动时间很短。或者,如果您调用 CLR 函数的次数适中,则该函数的所有调用的总启动时间将会很小。但要小心循环。

另外,为了可维护性,最好不要使用超出实际需要的语言。

我想补充几个可能没有提到的使用 CLR 的原因。

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

我针对类似问题发布了以下答案: SQL SERVER CLR 的优点。不过,我要在这里补充一点,C# / VB.net / 等是一种比 T-SQL 更适合人们使用的语言 不是 这是使用 SQLCLR 而不是 T-SQL 的一个原因。如果有人不知道如何在 T-SQL 中完成某些任务,请首先寻求帮助以找到 T-SQL 解决方案。如果一个不存在, 然后 走CLR路线。


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

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

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

如果有兴趣在无需编写任何代码的情况下查看其中一些功能的实际应用,可以使用免费版本 SQL# (我是作者)有正则表达式函数、自定义聚合(UDA)、自定义类型(UDT)等。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top