我的主要目标是写一个PLSQL程序创建数据库链接时,主机,端口,服务,用户名和密码是给定的。在那里,我需要阻止创建数据库链接到同一数据库。我怎样才能阻止创建到同一数据库的数据库链接,这样我就可以通知用户到同一数据库的数据库链接是不允许的。
确保提供的主机和服务名与运行的数据库不相同。您可以从'USERENV'命名空间中的SYS_CONTEXT函数中获取此信息:
SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS SERVICE_NAME,
SYS_CONTEXT('USERENV', 'SERVER_HOST') AS SERVER_HOST
FROM DUAL
例如,您的过程可能像这样:
CREATE OR REPLACE PROCEDURE CREATE_DB_LINK(pinHost IN VARCHAR2,
pinPort IN NUMBER,
pinService IN VARCHAR2,
pinUsername IN VARCHAR2,
pinPassword IN VARCHAR2)
AS
strHost VARCHAR2(100);
strService VARCHAR2(100);
BEGIN
SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME'),
SYS_CONTEXT('USERENV', 'SERVER_HOST')
INTO strService,
strHost
FROM DUAL;
IF pinHost = strHost AND
pinService = strService
THEN
RAISE_APPLICATION_ERROR(-20001, 'Cannot create link to current DB');
END IF;
-- rest of code
END CREATE_DB_LINK;
由于这是您编写的过程,请将检查包含在其中。
例如,存储应该排除到表中的数据库列表(这样您就不必将它们的名称硬编码到过程中)。然后检查数据库(其参数作为参数)是否被列入黑名单。如果是,通知用户不能创建数据库链接。
如何?可以通过过程的OUT
参数,也可以通过RAISE_APPLICATION_ERROR
参数。
在创建数据库链接的过程中,在实际创建数据库链接之前,您可以让它检查这些视图中的一个。
- DBA_DB_LINKS -所有数据库中定义的DB链接
- ALL_DB_LINKS -当前用户可以访问的所有DB链接
- USER_DB_LINKS -当前用户拥有的所有数据库链接
如果该链接已经存在于其中一个视图中,要么引发错误,要么不再创建它。
您的方法中有一个致命的缺陷:任何使用默认调用者权限运行此过程的人都必须授予他们CREATE DATABASE LINK特权才能使该过程工作。这将允许他们直接创建链接,并完全绕过您的过程。
或者,如果创建过程以所有者权限而不是默认调用者权限运行,则要么在另一个模式中创建数据库链接,而用户无论如何都无法访问它,要么必须创建公共数据库链接——通常不应该使用这种链接,而应该只由DBA创建。时期。简而言之,整个概念是有缺陷的,不能像你所描述的那样实现。用户要么会忽略您的过程,要么会造成安全问题。总的来说,我同意@EdStevens和@MarmiteBomber之前的评论,即数据库链接应该永远只由DBA创建。我甚至会进一步建议,链接应该通过使用API模式中的本地视图和同义词来访问,并且永远不要由用户直接访问。
对数据库链接的访问打开了一个关于远程数据库的世界的信息,大多数用户不应该访问这些信息(像ALL_USERS获取系统上每个有效用户帐户的列表),并且应该只作为正式的、版本控制的数据模式的一部分。使用API通过链接提取数据可以防止用户直接查询远程数据字典,并增强了两个系统的安全性。