如何在不从SQL Server删除程序集的情况下更新CLR程序集


18

如何在不删除并在SQL Server(2008 R2)中重新创建程序集的情况下更新CLR函数(或过程)程序集dll?

就目前而言,如果我更新程序集(例如添加新功能),则在我删除程序集之前,SQL Server将不接受更新的dll:

DROP ASSEMBLY CLRFunctions

Msg 6590, Level 16, State 1, Line 1
DROP ASSEMBLY failed because 'CLRFunctions' is referenced by object 'NormalizeString'.

但是在删除程序集之前,必须先删除所有引用该程序集的函数

DROP FUNCTION NormalizeString
DROP FUNCTION RemoveDiacritics
DROP FUNCTION RemoveCombiningDiacritics
DROP FUNCTION CombineLigatures
....
DROP FUNCTION PseudolocalizeArabic

并且然后我可以删除这个组件:

DROP ASSEMBLY CLRFunctions

现在我必须“ 创建 ”程序集:

CREATE ASSEMBLY CLRFunctions FROM 'c:\foos\CLRFunctions.dll';

现在我必须寻找的所有UDF的声明之前,我删除了他们注册。

我宁愿更新程序集,并让SQL Server开始使用它。


更新:我随机尝试DBCC FREEPROCCACHE强制执行“重新编译”,但SQL Server仍使用旧代码。

更新:我删除了程序集dll CLRFunctions.dll,并且SQL Server仍然能够运行代码(没有应该是不可能的代码)。

Answers:


16

我认为您正在寻找alter assembly。从BOL:

如果指定了FROM子句,则ALTER ASSEMBLY会根据提供的模块的最新副本来更新程序集。因为在SQL Server实例中可能已经针对程序集定义了CLR函数,存储过程,触发器,数据类型和用户定义的聚合函数,所以ALTER ASSEMBLY语句将它们重新绑定到程序集的最新实现。为了完成此重新绑定,映射到CLR函数,存储过程和触发器的方法必须仍然存在于具有相同签名的修改后的程序集中。实现CLR用户定义类型和用户定义聚合函数的类仍必须满足作为用户定义类型或聚合的要求。

同一页面上的示例之一似乎可以解决问题:

ALTER ASSEMBLY ComplexNumber 
FROM 'C:\Program Files\Microsoft SQL Server\90\Tools\Samples\1033\Engine\Programmability\CLR\UserDefinedDataType\CS\ComplexNumber\obj\Debug\ComplexNumber.dll' 

1
当更新的程序集位于SSMS客户端计算机而不是SQL Server主机上时,可以这样做吗?我在服务器上没有足够的特权来直接访问其文件系统,但是我有足够的权限来添加和删除CLR程序集。
扎里菲斯2014年

不,好吧,基本上没有。您可以指定UNC路径(即\\ server \ path \ to \ file),并且只要运行SQL引擎的服务帐户对文件具有读取权限,它就可以正常工作。另一个选项是为程序集指定二进制值。如果您已经将其部署在另一台服务器上,那么从那里编写脚本脚本将获得blob值。
本图尔2014年

是的,这就是我的想法。:(也许SSMS的较新版本将允许从远程计算机上更新组件在此期间,我想我下降,通过SSMS GUI创建组件-并执行删除并创建操作的所有相关功能。
Zarepheth

我不会屏住呼吸。至于必须删除并重新创建,为什么您不能使用上面概述的任何一种方法?
Ben Thul 2014年

1
“添加和更改程序集需要文件系统参考。” - 这不是真的。两者CREATE ASSEMBLYALTER ASSEMBLY都会采用代表程序集的Blob。通过转到在2008+上创建的任何数据库并转到Programmability->程序集并对Microsoft.SqlServer.Types程序集的创建进行脚本编写,可以自己证明这一点。那巨大的varbinary 是装配体。由于这适用于您的情况,因此将程序集部署到本地实例,对其进行脚本编写,然后使其成为ALTER ASSEMBLY脚本。
Ben Thul 2014年

7

要补充本图尔的答案,可以通过SQL Server Management Studio的GUI相当轻松地远程完成此操作。

  1. 在数据库的对象资源管理器下->可编程性,右键单击程序集,然后选择“新建程序集...”。

  2. 浏览到更新的DLL。

  3. 单击“新建装配”窗口顶部的“脚本”,而不是单击“确定”(这将失败,因为已经存在相同名称的装配)。
     
    您将进入一个包含“ CREATE ASSEMBLY”行的SQL查询,后跟一个巨大的Blob(即您刚刚选择的DLL)。

  4. 将“创建”更改为“更改”,然后执行!

脚本还为我创建了“ AUTHORIZATION”行,我必须在执行前将其删除;您的里程可能会有所不同。

我希望这可以帮助其他没有文件系统访问其服务器的人。

希望微软有朝一日将其作为SSMS中的一流操作,但这是一个相当容易的解决方法,直到他们这样做为止。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.