Jus*_*ing 5 sql-server sql-clr
对于带有前缀 sp_ 的 T-SQL 存储过程,SQL Server 将在 master 数据库中搜索并使用当前过程之前的过程。对于我使用 Visual Studios 内置部署使用 SQL Server 2010 创建的 SQLCLR 存储过程,情况似乎并非如此。数据库服务器是 SQL Server 2008 R2 (SP1)。
我执行这个脚本:
SELECT name
from master.sys.procedures
WHERE type_desc='CLR_STORED_PROCEDURE' and schema_id = 1
USE tempdb
PRINT 'USING tempDb'
EXEC sp_RAISERROR_CaughtDemo;
GO
USE master
PRINT 'USING master'
EXEC sp_RAISERROR_CaughtDemo
GO
--SELECT * from sys.assembly_modules
Run Code Online (Sandbox Code Playgroud)
并且存储过程只会使用来自 master 数据库的非限定名称执行:
name
----------------------------------
sp_RAISERROR_CaughtDemo
sp_RAISERROR_UncaughtDemo
(2 row(s) affected)
USING tempDb
Msg 2812, Level 16, State 62, Line 5
Could not find stored procedure 'sp_RAISERROR_CaughtDemo'.
USING master
RAISERROR() Caught Severity 0
RAISERROR() Caught Severity 1
Msg 50000, Level 1, State 1
RAISERROR() Caught Severity 2
Msg 50000, Level 2, State 1
RAISERROR() Caught Severity 3
Msg 50000, Level 3, State 1
RAISERROR() Caught Severity 4
Msg 50000, Level 4, State 1
RAISERROR() Caught Severity 5
Msg 50000, Level 5, State 1
RAISERROR() Caught Severity 6
Msg 50000, Level 6, State 1
RAISERROR() Caught Severity 7
Msg 50000, Level 7, State 1
RAISERROR() Caught Severity 8
Msg 50000, Level 8, State 1
RAISERROR() Caught Severity 9
Msg 50000, Level 9, State 1
RAISERROR() Caught Severity 10
Msg 50000, Level 11, State 1, Line 1
RAISERROR() Caught Severity 11
Run Code Online (Sandbox Code Playgroud)
这些过程的代码如下:
name
----------------------------------
sp_RAISERROR_CaughtDemo
sp_RAISERROR_UncaughtDemo
(2 row(s) affected)
USING tempDb
Msg 2812, Level 16, State 62, Line 5
Could not find stored procedure 'sp_RAISERROR_CaughtDemo'.
USING master
RAISERROR() Caught Severity 0
RAISERROR() Caught Severity 1
Msg 50000, Level 1, State 1
RAISERROR() Caught Severity 2
Msg 50000, Level 2, State 1
RAISERROR() Caught Severity 3
Msg 50000, Level 3, State 1
RAISERROR() Caught Severity 4
Msg 50000, Level 4, State 1
RAISERROR() Caught Severity 5
Msg 50000, Level 5, State 1
RAISERROR() Caught Severity 6
Msg 50000, Level 6, State 1
RAISERROR() Caught Severity 7
Msg 50000, Level 7, State 1
RAISERROR() Caught Severity 8
Msg 50000, Level 8, State 1
RAISERROR() Caught Severity 9
Msg 50000, Level 9, State 1
RAISERROR() Caught Severity 10
Msg 50000, Level 11, State 1, Line 1
RAISERROR() Caught Severity 11
Run Code Online (Sandbox Code Playgroud)
我可以做些什么来使 SQL Server 在 master 数据库中搜索以找到此存储过程?我试过sys.sp_MS_marksystemobject无济于事。
我不知道解决方案(并且我不知道 CLR 脚手架是否曾被设计来模仿您正在谈论的功能),但一种解决方法可能是在 master 中创建一个 T-SQL 存储过程,用作将调用中继到 CLR 版本的包装器。只要用户数据库中不存在同名的存储过程,就不需要将其标记为系统对象。
编辑-刚刚证明这对我自己来说效果很好。首先,我创建了您的程序集并添加了重现所需的过程(为简洁起见,我不会在此处包含所有部分):
USE master;
GO
CREATE ASSEMBLY [Justin]
AUTHORIZATION [dbo]
FROM 0x4D5A900003000000040... lots of data here ...;
GO
ALTER ASSEMBLY [Justin]
DROP FILE ALL
ADD FILE FROM 0x4D6963726F... even more data here ...;
AS N'Justin.pdb';
GO
CREATE PROCEDURE [dbo].[sp_RAISERROR_CaughtDemo]
AS EXTERNAL NAME [Justin].[StoredProcedures].[RaiserrorCaught]
GO
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个包装存储过程,确保完全限定 CLR 过程:
CREATE PROCEDURE dbo.sp_RAISERROR_CaughtDemo_Wrapper
AS
BEGIN
SET NOCOUNT ON;
EXEC master.dbo.sp_RAISERROR_CaughtDemo;
END
GO
Run Code Online (Sandbox Code Playgroud)
然后我调整了您的重现代码以从 tempdb 调用包装器:
USE tempdb;
PRINT 'USING tempDb';
EXEC sp_RAISERROR_CaughtDemo_wrapper;
GO
Run Code Online (Sandbox Code Playgroud)
结果:
USING tempDb
RAISERROR() Caught Severity 0
RAISERROR() Caught Severity 1
Msg 50000, Level 1, State 1
RAISERROR() Caught Severity 2
Msg 50000, Level 2, State 1
RAISERROR() Caught Severity 3
Msg 50000, Level 3, State 1
RAISERROR() Caught Severity 4
Msg 50000, Level 4, State 1
RAISERROR() Caught Severity 5
Msg 50000, Level 5, State 1
RAISERROR() Caught Severity 6
Msg 50000, Level 6, State 1
RAISERROR() Caught Severity 7
Msg 50000, Level 7, State 1
RAISERROR() Caught Severity 8
Msg 50000, Level 8, State 1
RAISERROR() Caught Severity 9
Msg 50000, Level 9, State 1
RAISERROR() Caught Severity 10
Msg 50000, Level 11, State 1, Line 1
RAISERROR() Caught Severity 11
Run Code Online (Sandbox Code Playgroud)
因此,这表明您应该能够使用这样的包装器,以便能够从其他数据库调用未引用的 CLR 过程。
(但是,我建议一般来说这不应该是一个目标 - 您应该在适用的情况下使用三部分名称正确定义引用。)
我承认我确实对您的存储过程进行了一项更改,以防止 Visual Studio 对我抱怨。我变了:
while (true)
Run Code Online (Sandbox Code Playgroud)
到:
while (i <= 11)
Run Code Online (Sandbox Code Playgroud)
但当然,这一变化与范围界定问题无关。
| 归档时间: |
|
| 查看次数: |
902 次 |
| 最近记录: |