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
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) + ‘;‘ + CHAR(13) + CHAR(10) +
                    ‘GO‘

        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) + ‘GO‘ + 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) + ‘GO‘ + 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 STUFF((
            SELECT  ‘,‘ + 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_output <> 0, ‘ OUTPUT ‘, ‘‘ )
                    + IIF(par.is_readonly <> 0, ‘ READONLY ‘, ‘‘)
                    + IIF(par.has_default_value <> 0, ‘ = ‘‘‘ + CAST(par.default_value AS NVARCHAR(MAX)) + ‘‘‘‘,‘‘)
            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 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) + ‘GO‘ + 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) +
            ‘GO‘ + 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)

SET @cmd = (SELECT create_sqlobject_cmd + CHAR(13) + CHAR(10) AS create_sqlobject_cmd FROM #t ORDER BY id FOR XML PATH(‘‘), TYPE).value(‘.‘, ‘nvarchar(max)‘) 

INSERT #cmd VALUES(@cmd)

CombineCmdString:
SET @cmd = (SELECT (SELECT cmd FROM #cmd ORDER BY ID FOR XML PATH(‘‘), TYPE).value(‘.‘, ‘nvarchar(max)‘))

EXEC (@cmd)

END
GO
时间: 2024-08-25 13:54:07

SQL Server ->> 重新创建Assembly和自动重建相关的数据库编程对象(存储过程,函数和触发器)的相关文章

SQL Server -&gt;&gt; 在SQL Server中创建ASSEMBLY

首先要把数据库的TRUSTWORTHY属性改为ON ALTER DATABASE [MYDB] SET TRUSTWORTHY ON GO 接下来直接创建ASSEMBLY应该就没问题了.但是往往有可能遇到一种情况 -- 在运行CREATE ASSEMBLY的时候发生错误 Msg 33009, Level 16, State 2, Line 5The database owner SID recorded in the master database differs from the databa

笔记-Microsoft SQL Server 2008技术内幕:T-SQL语言基础-10 可编程对象

关于批处理 下列语句不能在同一批处理中和其他语句同时编译:CREATE DEFAULT.CREATE FUNCTION.CREATE PROCEDURE.CREATE RULE.CREATE SCHEMA.CREATE TRIGGER及CREATE VIEW.例如,以下代码包含一个IF语句,之后在同一批处理中跟着一个CREATE VIEW语句,SQL Server将会报错: IF OBJECT_ID('Sales.MyView', 'V') IS NOT NULL DROP VIEW Sales

在sql server中创建一个只读login

在SQL Server中创建一个Login,并为这个login授予只读的权限 --create Login Name create login [domain\login] from windows; --create --UserName Create User DWReadOnly for login [domain\login] --Grant readonly ALTER ROLE [db_datareader] add MEMBER DWReadOnly Appendix 服务器角色参

学习ASP .NET MVC5官方教程总结(五)使用SQL Server LocalDB创建连接字符串

学习ASP .NET MVC5官方教程总结(五)使用SQL Server LocalDB创建连接字符串 在上一章中,我们创建了MovieDBContext类来连接数据库.处理Movie 对象和数据库记录的映射.但是我们没有指定使用什么数据库,也没指定使用哪个数据库.其实,在我们没有指定数据库的时候,Entity Framework 默认使用LocalDB . 在本节中我们将介绍如何在Web.config 文件中添加一个数据库连接. LocalDB 是SQL Server Express 数据库引

SQL Server 2008创建数据库

1.数据.数据库.数据管理系统基本概念: 数据:人类有用信息的符号化表示. 数据库:按照数据结构来组织.存储和管理数据的一个仓库. 数据库管理系统(DBMS):可维护.存储并为应用系统提供数据的软件系统(软件+数据库+数据管理员). 可以客观描述的事物被称为"实体",不同的数据体现了不同的实体.数据每一行(Row)对应一个实体,被称为"记录(record)",每个输入项称为"列"(Column),如编号,姓名,学号等.数据"表"

SQL Server调优系列进阶篇(如何维护数据库索引)

原文:SQL Server调优系列进阶篇(如何维护数据库索引) 前言 上一篇我们研究了如何利用索引在数据库里面调优,简要的介绍了索引的原理,更重要的分析了如何选择索引以及索引的利弊项,有兴趣的可以点击查看. 本篇延续上一篇的内容,继续分析索引这块,侧重索引项的日常维护以及一些注意事项等. 闲言少叙,进入本篇的主题. 技术准备 数据库版本为SQL Server2012,前几篇文章用的是SQL Server2008RT,内容区别不大,利用微软的以前的案例库(Northwind)进行分析,部分内容也会

SQL Server安全(7/11):使用跨数据库所有权链接(Cross-Database Ownership Chaining)的跨数据库安全

在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切.但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念.这篇文章提供了基础,因此你可以对SQL Server里的安全功能充分利用,不用在面对特定威胁,不能保护你数据的功能上浪费时间. 从让人眼花缭乱的客户端使用连接,通过到处分布的网络,尤其是互联网,关系数据库在各种应用程序里广泛使用.这使数据对任何人,在任何地方都可访问.数据库可以保存人类知识的很大部分,包括高度敏感的个人信息和让国际商务工作的关

与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。

今天同学请教我数据库为什么打不开了,打开SQL Server 2008 的 SQL Server Management Studio,输入sa的密码发现,无法登陆数据库?提示以下错误: "在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接)": 他最近刚刚装过了

出现“在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。”这样的错误!

1.基本现象:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. 2. 可能出现的情况,拷贝了别人的项目,或者在网上找的别人的项目运行时附加到自己的数据库上,特别是在有版本差异的时候进行附加的时候,(比如:用SQL2005建的数据库,你附加在SQL2008的下面的时候)你需要修改项目中Web.Config文件中的数据库连接字符串,这时候你就需要注意了,根据不同版本的数据库,它的