SQL Server ->> 重新创建Assembly和自动重建相关的数据库编程对象(存储过程,函数和触发器)
在SQL Server中,一旦一个Assembly被其他的数据库编程对象(存储过程,函数和触发器)引用了,这个Assembly就不能被删除。但是问题是,在SQL Server要更新一个Assembly的方法是先删除这个Assembly再用心的DLL地址或者编译后的二进制代码重新创建。这样就造成了,每次我们都要根据它的错误提示把那些引用到该Assembly的数据库编程对象的创建脚本导出后再删除这些编程对象,然后才可能删除Assembly。导出脚本的方法需要手动去利用SSMS这个IDE里面的GENERATE SCRIPT的功能来做。挺麻烦的。下面这个存储过程就是为了来解决这个问题。它会自动来干这个事情。
但是,它只是个半成品。为什么这么说呢?因为这个存储过程到目前为止还没办法支持Trigger的脚本导出。因为工作需要,而项目中只是用到CLR存储过程和函数,就没有继续完善Trigger的部分。今后再完善吧。
IF EXISTS(SELECT * FROM sys.procedures WHERE name = 'usp_RecreateAssemblyAndInvolvedSQLObjects' AND [schema_id] = SCHEMA_ID('dbo'))
DROP PROCEDURE [dbo].[usp_RecreateAssemblyAndInvolvedSQLObjects]
GO
CREATE PROCEDURE [dbo].[usp_RecreateAssemblyAndInvolvedSQLObjects]
@assembly_name SYSNAME,
@new_binary_string NVARCHAR(MAX),
@permission_set NVARCHAR(50) = NULL,
@not_exists_create BIT = 0,
@only_output_command BIT = 0
AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
CREATE TABLE #t(id INT IDENTITY(1,1), drop_sqlobject_cmd NVARCHAR(MAX), create_sqlobject_cmd NVARCHAR(MAX))
IF OBJECT_ID('tempdb..#cmd') IS NOT NULL
DROP TABLE #cmd
CREATE TABLE #cmd(id INT IDENTITY(1,1), cmd NVARCHAR(MAX))
DECLARE @cmd AS NVARCHAR(MAX)
DECLARE @msg NVARCHAR(4000)
IF NOT EXISTS(SELECT * FROM sys.assemblies WHERE name = @assembly_name)
BEGIN
IF @not_exists_create = 1
BEGIN
IF @permission_set NOT IN ('SAFE','EXTERNAL_ACCESS','UNSAFE')
BEGIN
RAISERROR('PERMISSION_SET in "CREATE ASSEMBLY" command should only be one of values: SAFE, EXTERNAL_ACCESS, UNSAFE.',16,1)
RETURN
END
SET @cmd = '/**************************** recreate assembly ' + QUOTENAME(@assembly_name) + ' with the new binary string ****************************/' + REPLICATE(CHAR(13) + CHAR(10),2)
INSERT #cmd VALUES(@cmd)
SET @cmd = 'CREATE ASSEMBLY ' + QUOTENAME(@assembly_name) + CHAR(13) + CHAR(10) +
'FROM ' + CAST(@new_binary_string AS NVARCHAR(MAX)) + CHAR(13) + CHAR(10) +
'WITH PERMISSION_SET = ' + @permission_set + CHAR(13) + CHAR(10) + ';' + CHAR(13) + CHAR(10)
INSERT #cmd VALUES(@cmd)
GOTO CombineCmdString
END
ELSE
BEGIN
SET @msg = 'Assembly "' + @assembly_name + '" doesn''t exist in the database'
RAISERROR(@msg,16,1)
RETURN
END
END
INSERT #t(drop_sqlobject_cmd, create_sqlobject_cmd)
SELECT 'DROP ' + CASE obj.type_desc WHEN 'CLR_STORED_PROCEDURE' THEN ' PROCEDURE '
WHEN 'CLR_SCALAR_FUNCTION' THEN ' FUNCTION '
WHEN 'CLR_TABLE_VALUED_FUNCTION' THEN ' FUNCTION '
WHEN 'CLR_TRIGGER' THEN 'TRIGGER'
ELSE '' END + QUOTENAME(sch.name) + '.' + QUOTENAME(obj.name)
+ CASE obj.type_desc WHEN 'CLR_TRIGGER' THEN ' ON ' + QUOTENAME(prn_sch.name) + '.' + QUOTENAME(prn_obj.name)
ELSE '' END
+ ';' + CHAR(13) + CHAR(10) AS drop_sqlobject_cmd,
'CREATE' + CASE obj.type_desc WHEN 'CLR_STORED_PROCEDURE' THEN ' PROCEDURE '
WHEN 'CLR_SCALAR_FUNCTION' THEN ' FUNCTION '
WHEN 'CLR_TABLE_VALUED_FUNCTION' THEN ' FUNCTION '
WHEN 'CLR_TRIGGER' THEN 'TRIGGER'
ELSE '' END + QUOTENAME(sch.name) + '.' + QUOTENAME(obj.name)
+ par.param_list
+ CHAR(13) + CHAR(10) + CASE WHEN ass_mod.execute_as_principal_id IS NULL THEN 'WITH EXECUTE AS CALLER '
WHEN ass_mod.execute_as_principal_id = -2 THEN 'WITH EXECUTE AS OWNER '
ELSE 'WITH EXECUTE AS ''' + dp.name + '''' END
+ CHAR(13) + CHAR(10) + 'AS EXTERNAL NAME '
+ QUOTENAME(ass.name) + '.' + QUOTENAME(ass_mod.assembly_class) + '.' + QUOTENAME(ass_mod.assembly_method)
+ ';' + CHAR(13) + CHAR(10) AS create_sqlobject_cmd
FROM sys.assembly_modules ass_mod JOIN
sys.objects obj ON ass_mod.object_id = obj.object_id JOIN
sys.schemas sch ON sch.schema_id = obj.schema_id JOIN
sys.assembly_files ass_f ON ass_f.assembly_id = ass_mod.assembly_id JOIN
sys.assemblies ass ON ass.assembly_id = ass_f.assembly_id LEFT JOIN
sys.objects prn_obj ON prn_obj.object_id = obj.parent_object_id LEFT JOIN
sys.schemas prn_sch ON prn_sch.schema_id = prn_obj.schema_id LEFT JOIN
sys.database_principals dp ON dp.principal_id = ass_mod.execute_as_principal_id CROSS APPLY
( SELECT IIF(obj.type_desc IN ('CLR_SCALAR_FUNCTION'),CHAR(13) + CHAR(10) + '(','') + STUFF((
SELECT CASE
WHEN obj.type_desc IN ('CLR_STORED_PROCEDURE','CLR_TRIGGER') THEN
',' + CHAR(13) + CHAR(10) + par.name + SPACE(1) + UPPER(tp.name) +
CASE WHEN tp.name IN ('nchar','nvarchar') THEN '(' + IIF(par.max_length = -1, 'MAX',CAST(par.max_length/2 AS NVARCHAR(10))) + ')'
WHEN tp.name IN ('datetime2','datetimeoffset','time') THEN '(' + CAST(tp.scale AS NVARCHAR(10)) + ')'
WHEN tp.name IN ('binary','char','varbinary','varchar') THEN CAST(par.max_length AS NVARCHAR(10))
WHEN tp.name IN ('decimal','numeric') THEN '(' + CAST(tp.precision AS NVARCHAR(10)) + ',' + CAST(tp.scale AS NVARCHAR(10)) + ')'
ELSE '' END
+ IIF(par.is_output <> 0, ' OUTPUT ', '' )
+ IIF(par.is_readonly <> 0, ' READONLY ', '')
+ IIF(par.has_default_value <> 0, ' = ''' + CAST(par.default_value AS NVARCHAR(MAX)) + '''','')
WHEN obj.type_desc IN ('CLR_SCALAR_FUNCTION') THEN
CASE WHEN par.is_output <> 0 THEN
CHAR(13) + CHAR(10) + ') RETURNS ' + QUOTENAME(UPPER(tp.name)) ELSE
',' + CHAR(13) + CHAR(10) + par.name + SPACE(1) + UPPER(tp.name) +
CASE WHEN tp.name IN ('nchar','nvarchar') THEN '(' + IIF(tp.max_length = -1, 'MAX',CAST(tp.max_length/2 AS NVARCHAR(10))) + ')'
WHEN tp.name IN ('datetime2','datetimeoffset','time') THEN '(' + CAST(tp.scale AS NVARCHAR(10)) + ')'
WHEN tp.name IN ('binary','char','varbinary','varchar') THEN CAST(tp.max_length AS NVARCHAR(10))
WHEN tp.name IN ('decimal','numeric') THEN '(' + CAST(tp.precision AS NVARCHAR(10)) + ',' + CAST(tp.scale AS NVARCHAR(10)) + ')'
ELSE '' END
+ IIF(par.is_readonly <> 0, ' READONLY ', '')
+ IIF(par.has_default_value <> 0, ' = ''' + CAST(par.default_value AS NVARCHAR(MAX)) + '''','')
END
ELSE '' END
FROM sys.parameters par JOIN
sys.types tp ON tp.system_type_id = par.system_type_id
WHERE tp.name <> 'sysname' AND par.object_id = obj.object_id
ORDER BY CASE WHEN obj.type_desc = 'CLR_SCALAR_FUNCTION' AND par.is_output = 1 THEN 1 ELSE 0 END,
par.parameter_id
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'),1,2,'') AS param_list) as par
WHERE ass.name = @assembly_name;
SET @cmd = '/**************************** Drop CLR sql obbjects that reference assembly ' + QUOTENAME(@assembly_name) + ' ****************************/' + REPLICATE(CHAR(13) + CHAR(10),2)
INSERT #cmd VALUES(@cmd)
SET @cmd = (SELECT drop_sqlobject_cmd + CHAR(13) + CHAR(10) AS drop_sqlobject_cmd FROM #t ORDER BY id FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)')
INSERT #cmd VALUES(@cmd)
SET @cmd = '/**************************** Drop assembly ' + QUOTENAME(@assembly_name) + ' ****************************/' + REPLICATE(CHAR(13) + CHAR(10),2)
INSERT #cmd VALUES(@cmd)
SET @cmd = 'DROP ASSEMBLY ' + QUOTENAME(@assembly_name) + ';' + CHAR(13) + CHAR(10)
INSERT #cmd VALUES(@cmd)
SET @cmd = '/**************************** recreate assembly ' + QUOTENAME(@assembly_name) + ' with the new binary string ****************************/' + REPLICATE(CHAR(13) + CHAR(10),2)
INSERT #cmd VALUES(@cmd)
SET @cmd = (SELECT 'CREATE ASSEMBLY ' + QUOTENAME(name) + CHAR(13) + CHAR(10) +
'FROM ' + CAST(@new_binary_string AS NVARCHAR(MAX)) + CHAR(13) + CHAR(10) +
'WITH PERMISSION_SET = ' + IIF(@permission_set IS NULL, CASE permission_set WHEN 1 THEN 'SAFE' WHEN 2 THEN 'EXTERNAL_ACCESS' WHEN 3 THEN 'UNSAFE' END, @permission_set) + ';' + CHAR(13) + CHAR(10)
FROM sys.assemblies
WHERE name = @assembly_name)
INSERT #cmd VALUES(@cmd)
SET @cmd = '/**************************** recreate CLR sql obbjects that reference assembly ' + QUOTENAME(@assembly_name) + ' ****************************/' + REPLICATE(CHAR(13) + CHAR(10),2)
INSERT #cmd VALUES(@cmd)
IF @only_output_command = 1
BEGIN
SET @cmd = (SELECT create_sqlobject_cmd + CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10) AS create_sqlobject_cmd FROM #t ORDER BY id FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)')
INSERT #cmd VALUES(@cmd)
END
ELSE
BEGIN
INSERT #cmd
SELECT create_sqlobject_cmd + CHAR(13) + CHAR(10) AS create_sqlobject_cmd FROM #t ORDER BY id
END
CombineCmdString:
IF @only_output_command = 1
BEGIN
SET @cmd = (SELECT (SELECT cmd + 'GO' + CHAR(13) + CHAR(10) FROM #cmd ORDER BY ID FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'))
END
IF @only_output_command = 1
SELECT @cmd AS cmd
ELSE
BEGIN TRY
BEGIN TRAN
DECLARE cur CURSOR FOR
SELECT cmd FROM #cmd ORDER BY id
OPEN cur
FETCH NEXT FROM cur INTO @cmd
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC(@cmd)
FETCH NEXT FROM cur INTO @cmd
END
CLOSE cur
DEALLOCATE cur
COMMIT TRAN
END TRY
BEGIN CATCH
IF CURSOR_STATUS('GLOBAL','cur') > -1
CLOSE cur
IF CURSOR_STATUS('GLOBAL','cur') = -1
DEALLOCATE cur
IF @@TRANCOUNT > 0
ROLLBACK TRAN
DECLARE @err_msg AS NVARCHAR(4000)
SET @err_msg = ERROR_MESSAGE();
RAISERROR(@err_msg,16,1)
END CATCH
END
GO
SQL Server ->> 重新创建Assembly和自动重建相关的数据库编程对象(存储过程,函数和触发器)的更多相关文章
- SQL Server ->> 在SQL Server中创建ASSEMBLY
首先要把数据库的TRUSTWORTHY属性改为ON ALTER DATABASE [MYDB] SET TRUSTWORTHY ON GO 接下来直接创建ASSEMBLY应该就没问题了.但是往往有可能 ...
- 【sql server复制】不重新初始化快照的情况下新增表/存储过程/函数等
转发自:https://www.cnblogs.com/datazhang/p/5498789.html sqlserver同步后在不重新初始化快照的情况下新增表 在已有事务复制中,时长 ...
- 在64位SQL Server中创建Oracle的链接服务器 Link Server
有时候我们希望在一个sqlserver下访问另一个sqlserver数据库上的数据,或者访问其他oracle数据库上的数据,要想完成这些操作,我们首要的是创建数据库链接. 数据库链接能够让本地的一个s ...
- 05Microsoft SQL Server 表创建,查看,修改及删除
Microsoft SQL Server 表创建,查看,修改及删除 创建表 创建普通表 use 数据库名称 go create table 表名称( 列1 ) not null, 列2 ) not n ...
- 在64位SQL Server中创建Oracle的链接服务器
当我们同时使用SQL Server和Oracle来存储数据时,经常会用到跨库查询.为了方便使用跨库查询,一个最好的办法就是通过创建链接服务器来实现.既可以在SQL Server中创建Oracle的链接 ...
- sql server 脚本创建数据库邮件
sql server 脚本创建数据库邮件代码: --脚本创建数据库邮件 --1.开启数据库邮件 RECONFIGURE WITH OVERRIDE GO RECONFIGURE WITH OVERRI ...
- sql server中创建链接服务器图解教程
转自sql server中创建链接服务器图解教程 1.展开服务器对象-->链接服务器-->右击"新建链接服务器" 注意:必须以数据库管理员身份登录(通常也就是sa帐号) ...
- sql server 无法创建数据库,错误代码:1807
SQL Server 不能创建数据库,发生错误:1807 :未能获得数据库 'model' 上的排它锁.请稍后重试操作. declare @sql varchar(100) while ...
- SQL Server 2008创建数据库
1.数据.数据库.数据管理系统基本概念: 数据:人类有用信息的符号化表示. 数据库:按照数据结构来组织.存储和管理数据的一个仓库. 数据库管理系统(DBMS):可维护.存储并为应用系统提供数据的软件系 ...
随机推荐
- C++_类入门4-String类
很多应用程序都需要处理字符串.C语言在string.h(C++中为cstring)中提供了一系列的字符串函数,很多早期的C++实现为处理字符串提供了自己的类. string类是由头文件string支持 ...
- 2018acm-icpc青岛站心得
今年总共两场区域赛,一场南京,一场青岛.南京场队伍真正开始磨合,虽然最后还是铜牌,但是和银牌队伍其实只差一个计算几何的板子的问题.而鉴于南京的教训,所以在准备青岛站的时候,我准备了非常多的模板,还和派 ...
- UESTC - 1147 求最短路方案数
这道题很是说明了记忆化搜索的重要性 瞎bfs递推半天发现没卵用(也许是姿势不对,但我认为树形或图形dfs明显好写并且很好正确地递推) 参考了别人的写法,总感觉自己的实现能力太弱了 还有题目是1e9+9 ...
- 微信小程序图片上传放大预览删除代码
效果: 一,下面是上传图片的效果 image.js代码: Page({ //选择相册或拍照 data: { imgs: [] }, //上传图片 chooseImg: function (e) { v ...
- Blockly
Blockly简介 A library for building visual programming editors. Blockly 是个库,可用来构建可视化编程编辑器 Blockly is b ...
- Data Guard 管理原理
##三大优势>Data Guard属于Oracle 自己的产品,其技术成熟完善.稳定可靠>可以随时验证业务数据的有效性>免费产品 Data Guard由主库(PRIMARY DATA ...
- jacob自己动生成word文档目录
任务目的 1自动生成word文档目录. 用例测试操作步骤 在一个word文档的第二页填写占位符: {目录}保存.调用程序读取目标文档,自动根据标题生成目录到{目录}位置. 效果 关键代码 insert ...
- http反向代理之haproxy详解
1.反向代理定义 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求 ...
- vim 配置文件——部分配置
//vim 相关 set nu set showmatch set autoindent set smartindent set ruler set incsearch set tabstop=4 s ...
- 【linux相识相知】sed命令
在之前的博客中我们介绍了文本三剑客中grep,本次博客就另外一名剑客——sed做出详细的描述,sed真的是一款强大的工具.下面让我们来一起看一下吧! 概述和工作机制 SED的英文全称为Stream E ...