如何将 OLE 对象集成到 SQL Server






4.92/5 (31投票s)
本文将演示如何将 T-SQL 与外部应用程序集成。
引言
本文将演示如何将 T-SQL 与外部应用程序集成。
背景
当我们需要在 SQL Server 数据库中存储或检索数据时,我们会使用 T-SQL。但关键是如何将 T-SQL 与外部应用程序集成?例如,我们想将 SQL Server 与 Microsoft Word、Excel 或 Microsoft Exchange Server 集成。那么如何实现呢?
Using the Code
有七个扩展存储过程可以调用外部应用程序,例如 DLL。这些存储过程的名称和描述如下:
| 存储过程 | 描述 | 
| sp_OACreate | 在 Microsoft SQL Server 的实例上创建 OLE 对象实例 | 
| sp_OADestroy | 销毁已创建的 OLE 对象 | 
| sp_OAGetErrorInfo | 获取 OLE 自动化错误信息 | 
| sp_OAGetProperty | 获取 OLE 对象的属性值 | 
| sp_OASetProperty | 将 OLE 对象的属性设置为新值 | 
| sp_OAMethod | 调用 OLE 对象的方法 | 
| sp_OAStop | 停止全局 OLE 自动化存储过程执行环境 | 
参考:SQL Server Books Online。
让我们用一个简单的例子来实现这一点。我们的要求是从 SQL Server 存储过程中访问第三方 DLL。
以下是使用 C# .NET 开发的两个函数。
函数 (a) getOSPlatform 将返回系统平台,函数 (b) writeToFile 将使用参数给定的值将文本写入名为 CLRTempE.txt 的文本文件中。
示例 COM+ 代码 (C#. NET)
public string getOSPlatform()
{    // Return the System Platform. 
      return Convert.ToString(System.Environment.OSVersion.Platform);      
}
          
public int writeToFile(
                        string strPath
                      , string strText)
{
    int intResult = -1;
    try
    {
        if (strPath != "")
        {
            if (System.IO.File.Exists(strPath))
            {
                FileStream stream = new FileStream(
                                            strPath
                                          , FileMode.Open
                                          , FileAccess.Write);
                StreamWriter writer = new StreamWriter(stream);
                writer.BaseStream.Seek(0, SeekOrigin.End);
                writer.Write("TimeStamp: [ "
                                    + Convert.ToString(System.DateTime.Now)
                                    + " ] "
                                    + strText
                                    + " || (:-> || Info ! [Successfully inserted.]");
                writer.Write(Environment.NewLine);
                writer.Flush();
                writer.Close();
              }
               else
                    {
                        FileStream stream = new FileStream(
                            strPath
                          , FileMode.CreateNew
                          , FileAccess.Write);
                        StreamWriter writer = new StreamWriter(stream);
                        writer.BaseStream.Seek(0, SeekOrigin.End);
                        writer.Write("TimeStamp: [ "
                                    + Convert.ToString(System.DateTime.Now)
                                    + " ] "
                                    + strText
                                    + " || (:-> || Info ! [Successfully inserted.]");
                        writer.Write(Environment.NewLine);
                        writer.Flush();
                        writer.Close();
                    }
                    intResult = 0;
         }
    }
         catch (Exception ex)
         { throw ex; }
            return intResult;
}
示例 SQL 存储过程
--EXEC dbo.spCLRExample
CREATE PROCEDURE dbo.spCLRExample
AS
BEGIN
DECLARE @intResult INT
DECLARE @comHandle INT
DECLARE @errorSource VARCHAR(8000)
DECLARE @errorDescription VARCHAR(8000)
DECLARE @inputText VARCHAR(500)
DECLARE @OSPlatform VARCHAR(500)
DECLARE @isSuccess INT     
    set @inputText = 'This is a simple text.' 
    EXEC @intResult = sp_OACreate 'CLRExample.Example', @comHandle OUTPUT, 4
    IF (@intResult <> 0)
        BEGIN
        -- Error Handling 
            EXEC sp_OAGetErrorInfo @comHandle, @errorSource OUTPUT, _
				@errorDescription OUTPUT
            SELECT [Error Source] = @errorSource, [Description] = @errorDescription
            RETURN
        END
    
    -- Call a method into the component
    EXEC @intResult = sp_OAMethod @comHandle, 'getOSPlatform',@OSPlatform OUTPUT
    Print @OSPlatform
    IF (@intResult <> 0)
        BEGIN
        -- Error Handling 
            EXEC sp_OAGetErrorInfo @comHandle, @errorSource OUTPUT, _
					@errorDescription OUTPUT
            SELECT [Error Source] = @errorSource, [Description] = @errorDescription
            RETURN
        END
     -- Call a method into the component
      EXEC @intResult = sp_OAMethod @comHandle, _
	'writeToFile',@isSuccess OUTPUT, 'C:\CLRTempE.txt', @inputText
    IF (@intResult <> 0)
        BEGIN
        -- Error Handling 
            EXEC sp_OAGetErrorInfo @comHandle, _
		@errorSource OUTPUT, @errorDescription OUTPUT
            SELECT [Error Source] = @errorSource, [Description] = @errorDescription
            RETURN
        END
    -- Release the reference to the COM object */
    EXEC sp_OADestroy @comHandle
END
GO
现在我们将讨论上述代码的工作原理。sp_OACreate 将创建 DLL 到 SQL Server 的实例。如果成功创建,则输出为 0。如果非零,则将其发送到 sp_OAGetErrorInfo 并获取错误消息。sp_OAMethod 用于调用 DLL 的方法。在第一种情况下,我们调用只具有返回值的方法 getOSPlatform。sp_OACreate 的最后一个参数必须是 1、4 或 5。它指定新创建的 OLE 对象运行的执行上下文。如果指定,此值必须是以下值之一:
- 1 = 仅进程内 (.dll) OLE 服务器
- 4 = 仅本地 (.exe) OLE 服务器
- 5 = 允许进程内和本地 OLE 服务器
如果未指定,则默认值为 5。
如果允许进程内 OLE 服务器(通过使用上下文值 1 或 5 或不指定上下文值),它就可以访问 SQL Server 拥有的内存和其他资源。进程内 OLE 服务器可能会损坏 SQL Server 内存或资源,并导致不可预测的结果,例如 SQL Server 访问冲突。
当我们指定上下文值 4 时,本地 OLE 服务器无法访问任何 SQL Server 资源,也无法损坏 SQL Server 内存或资源。最后,sp_OADestroy 将销毁 SQL Server 中已创建的 OLE 对象。
参考 SQL Server Books Online。
兴趣点
注册 COM+ 时,我们必须使用 Visual Studio 命令提示符执行以下命令:
Commands
C:\Program Files\Microsoft Visual Studio 9.0\VC> RegAsm CLRExample.dll \ tlb: CLRExample.tlb \ codebase
注意:注册 COM+ 时不要使用 regsvr32。
结论
我希望这篇文章对您有所帮助。尽情享受吧!
历史
- 2009 年 6 月 15 日: 初始发布


