【发布时间】:2016-12-30 09:04:27
【问题描述】:
select banner
from v$version
;
BANNER
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
"CORE 12.1.0.2.0 Production"
TNS for Solaris: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production
在其 12c 版本中,Oracle 添加了允许在 SQL 语句顶部直接声明 Pl/SQL 函数的功能(请参阅https://oracle-base.com/articles/12c/with-clause-enhancements-12cr1)
这可能是一个非常方便的功能,尤其是。在需要从用户权限仅限于 SELECT 语句的数据库中提取数据的项目上。
以下(显然是简化的)查询在 Oracle SQL Developer 中运行良好:
with
function add_string(p_string in varchar2) return varchar2
is
--Function to add a string
l_buffer varchar2(32767);
begin
l_buffer := p_string || ' works!';
--
return l_buffer;
--
end ;
--
select add_string('Yes, it') as outVal
from dual
;
---------
OUTVAL
Yes, it works!
现在,我正在尝试将基于相同原理的查询结果集加载到 MS-Access 2007 中的 ADODB 记录集中。我知道 ADO 不会无缝处理以 WITH 子句开头的查询(参见,例如Why can't I do a "with x as (...)" with ADODB and Oracle?)。我通常解决这个问题的方法是将查询包含在一个 SELECT 块中,如下所示:
select hey_yo
from (
with sub as (
select 'hey' as hey
from dual
)
select hey || ' yo!' as hey_yo
from sub
)
;
---------
HEY_YO
hey yo!
不幸的是,在 Oracle 中处理 WITH 子句中的函数时,这似乎不是合法的语法:
select *
from (
with
function add_string(p_string in varchar2) return varchar2
is
--Function to add a string
l_buffer varchar2(32767);
begin
l_buffer := p_string || ' works!';
--
return l_buffer;
--
end ;
--
select add_string('Yes, it') as outVal
from dual
)
;
---------
PLS-00103: Encountered the symbol ")" when expecting one of the following:
. , @ ; for <an identifier>
<a double-quoted delimited-identifier> group having intersect
minus order partition start subpartition union where connect
sample
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
这是我试图在 VBA 中运行的子程序:
Sub TestSub()
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
'Connection details
Dim strHostName As String
Dim nPortNum As Integer
Dim strUser As String
Dim strPassword As String
Dim strServiceName As String
Dim strConnection As String
Dim strSQL As String
Set conn = New ADODB.Connection
'[... set credentials ...]
'Open Connection
With conn
.ConnectionString = "Provider=MSDAORA;" & _
"Data Source=(DESCRIPTION=(ADDRESS_LIST=" & _
"(ADDRESS=(PROTOCOL=TCP)(HOST=" & strHostName & ")(PORT=" & nPortNum & ")))(CONNECT_DATA=(SERVICE_NAME=" & strServiceName & ")));" & _
"User ID=" & strUser & ";Password=" & strPassword & ";"
.Open
End With
Set rs = New ADODB.Recordset
strSQL = "WITH FUNCTION add_string(p_string IN VARCHAR2) RETURN VARCHAR2 IS l_buffer VARCHAR2(32767); BEGIN l_buffer := p_string || ' works!'; RETURN l_buffer; END ; SELECT add_string('Yes, it') AS outval FROM dual"
rs.Open strSQL, conn, adOpenStatic, adLockReadOnly
'[... do stuff with data ...]
rs.MoveFirst
Debug.Print rs.Fields(0).Value
rs.Close
Set rs = Nothing
conn.Close
Set conn = Nothing
End Sub
任何想法如何解决这个问题? (不幸的是,在数据库中编译函数不是这个特定项目的选项)。
更新: 我应该提到我在运行 VBA 代码时遇到的错误:
运行时错误 3704:当对象处于运行状态时不允许操作 关闭。
rs.MoveFirst
【问题讨论】:
-
您能否尝试使用 Oracle Provider for OLE DB:
Provider=OraOLEDB.Oracle而不是 MSDAORA。你可以从这里下载它:32-bit Oracle Data Access Components。它可能会起作用,Microsoft 提供商是 deprecated 很长时间了 -
@WernfriedDomscheit:恐怕我被 MS 驱动卡住了,客户端对软件下载/安装非常严格。
-
也许你运气好,并且已经安装了 oledb 提供程序。
-
@WernfriedDomscheit:你是对的,它已安装,它解决了问题! :) 您可以发表您的评论作为答案,以便我接受吗?
标签: oracle vba ms-access adodb oracle12c