在SQLSERVER中创建 OLE 对象实例,有时我们想到数据库中执行存储过程的时候,同时调用系统中的COM对象。此时我们可以采用SQL的系统存储过程sp_OACreate ,此存储过程的调用要有一定的权限,只有 sysadmin 固定服务器角色的成员才能执行 sp_OACreate。
语法
sp_OACreate progid, | clsid,
objecttoken OUTPUT
[ , context ]
参数
progid
是要创建的 OLE 对象的程序标识符 (ProgID)。此字符串描述该 OLE 对象的类,其形式如下:
'OLEComponent.Object'
OLEComponent 是 OLE 自动化服务器的组件名称,Object 是 OLE 对象名。指定的 OLE 对象必须有效并且必须支持 IDispatch 接口。
例如,SQLDMO.SQLServer 是 SQL-DMO SQLServer 对象的 ProgID。SQL-DMO 的组件名称为 SQLDMO,SQLServer 对象是有效的,并且同所有 SQL-DMO 对象一样,SQLServer 对象支持 Idispatch。
clsid
是要创建的 OLE 对象的类标识符 (CLSID)。此字符串描述该 OLE 对象的类,其形式如下:
'{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}'
指定的 OLE 对象必须有效并且必须支持 IDispatch 接口。
例如,{00026BA1-0000-0000-C000-000000000046} 是 SQL-DMO SQLServer 对象的 CLSID。
objecttoken OUTPUT
是返回的对象令牌,并且必须是数据类型为 int 的局部变量。该对象令牌用于标识所创建的 OLE 对象,并将在调用其它 OLE 自动化存储过程时使用。
context
指定新创建的 OLE 对象要在其中运行的执行上下文。如果指定,那么此值必须为下列值之一:
1 = 仅为进程内 (.dll) OLE 服务器
4 = 仅为本地 (.exe) OLE 服务器
5 = 进程内 OLE 服务器和本地 OLE 服务器均可
如果未指定,其默认值为 5。此值将在调用 CoCreateInstance 时作为 dwClsContext 参数传递。
若允许使用进程内 OLE 服务器(通过使用上下文值 1 或 5 或者不指定上下文值),该服务器将可以访问 SQL Server 拥有的内存和其它资源。进程内 OLE 服务器可能会破坏 SQL Server 的内存或资源并导致不可预知的结果,如 SQL Server 访问违规。
当上下文值指定为 4 时,本地 OLE 服务器不能访问任何 SQL Server 资源,因而不能破坏 SQL Server 的内存或资源。
说明 此存储过程的参数按位置指定,而不是按名称指定。
返回代码值
0(成功)或非零数字(失败),是由 OLE 自动化对象返回的 HRESULT 的整数值。
我们来看一下一个具体的示例,在此示例中我们将调用一个自己写的COM组件,此组件的功能是提供读写序列号的功能。
CREATE PROCEDURE [dbo].[sp_MyCheckSN]
@ENCRYPTION nvarchar(255) out,@type int out
AS
DECLARE @object int
DECLARE @hr int
DECLARE @property varchar(255)
DECLARE @return varchar(255)
DECLARE @src varchar(255), @desc varchar(255)
-- 创建一个COM对象
EXEC @hr = sp_OACreate 'SecuritySN.CSecurity', @object OUT
IF @hr <> 0
BEGIN
set @ENCRYPTION='err'
RETURN
END
-- 调用方法
declare @aa nvarchar(255) -- 最终返回的值
EXEC @hr = sp_OAMethod @object, 'GetDiskSN', @aa out
IF @hr <> 0
BEGIN
set @ENCRYPTION='err'
RETURN
END
else
begin
set @Type=8 -- 指明注册读取方式
end
---------------------
if @aa=''
begin
-- 再读一次
EXEC @hr = sp_OAMethod @object, 'GetSNByAPI', @aa out
if @hr<>0
begin
set @ENCRYPTION='err'
RETURN
end
else
begin
set @Type=5 -- 指明是哪种方式读取注册号的
end
end
-- 销毁此对象
EXEC @hr = sp_OADestroy @object
IF @hr <> 0
BEGIN
set @ENCRYPTION='err'
RETURN
END
set @ENCRYPTION=@aa
GO
为了防止用户修改存储过程的代码。我们可以将此存储过程进行加密处理。但是加密后的存储过程也可能被破译出来。