我正在尝试在Oracle 11g数据库中执行包和函数。 我有以下代码,但是,我在第一个 .Execute 命令时收到错误。
VBA中的Locals窗口为我提供了以下错误:
Description : "Unspecified error" : String
Number : -2147467259 : Long
Source : "OraOLEDB" : String
哦,我已经引用了Microsoft ActiveX Data Object 6.1 Library。
我已尝试对代码进行各种更改,但它们都会返回相同的错误消息。
Sub QueryGLComb()
Dim OraCon As ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim objErr As ADODB.Error
Dim lngRow As Long
On Error GoTo err_test
Set OraCon = CreateObject("ADODB.Connection")
OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
"Data Source=DEMO;" & _
"User ID=scott;" & _
"Password=tiger;"
OraCon.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon
If OraCon.State = adStateClosed Then
MsgBox "false"
End If
With cmd
.ActiveConnection = OraCon
.CommandText = "fnd_flex_keyval.validate_segs"
.CommandType = adCmdStoredProc
.CommandTimeout = 60
.Parameters.Append .CreateParameter("return", adBoolean, adParamReturnValue)
.Parameters.Append .CreateParameter("operation", adVariant, adParamInput, , "CHECK_COMBINATION")
.Parameters.Append .CreateParameter("appl_short_name", adVariant, adParamInput, , "SQLGL")
.Parameters.Append .CreateParameter("key_flex_code", adVariant, adParamInput, , "GL#")
.Parameters.Append .CreateParameter("structure_number", adNumeric, adParamInput, , "50268")
.Parameters.Append .CreateParameter("concat_segments", adVariant, adParamInput, , "67000.2400.4001.01")
.Parameters.Append .CreateParameter("validation_date", adVariant, adParamInput, , "sysdate")
.Execute
End With
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon
With cmd
.ActiveConnection = OraCon
.CommandText = "begin FND_FLEX_KEYVAL.ERROR_MESSAGE"
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("message", adVariant, adParamReturnValue)
.Execute
End With
MsgBox "Return Message = " & cmd.Parameters(0)
OraCon.Close
err_test:
MsgBox Error$
For Each objErr In OraCon.Errors
MsgBox objErr.Description
Next
OraCon.Errors.Clear
Resume Next
End Sub
第一个“.Execute”行是发生错误的地方。
这是我在SQLDeveloper / Toad中使用的Oracle代码。我调用的包是“FND_FLEX_VALIDATE”,函数是“VALIDATE_SEGS”。这是Oracle eBS中Oracle提供的软件包。如果对fnd_flex_keyval.validate_segs的初始调用返回true,那么一切都很好。如果它返回错误,那么我们必须调用“FND_FLEX_KEYVAL.ERROR_MESSAGE”来检索错误消息。
DECLARE
l_return boolean;
l_message varchar2(240);
BEGIN
l_return := fnd_flex_keyval.validate_segs(operation => 'CHECK_COMBINATION'
,appl_short_name => 'SQLGL'
,key_flex_code => 'GL#'
,structure_number => 50268 --- Pass your chart of accounts id
,concat_segments => '67000.2400.4001.01' --- Pass your account combination string you want to create
,validation_date => sysdate); --- effective date by which you want the combination to be validated
l_message := FND_FLEX_KEYVAL.ERROR_MESSAGE;
If l_return THEN
dbms_output.put_line('Valid');
Else
dbms_output.put_line(l_message);
End if;
END;
我已经创建了一个要测试的新文件。我现在尝试执行的程序有3个参数:1英寸,2英寸。同样,当代码到达 .Execute 命令时,我仍然会收到相同的错误。
Sub ExecutePackageP()
Dim OraCon As New ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim objErr As ADODB.Error
Dim lngRow As Long
On Error GoTo err_test
Set OraCon = CreateObject("ADODB.Connection")
OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
"Data Source=demo;" & _
"User ID=scott;" & _
"Password=tiger;"
OraCon.Open
cmd.ActiveConnection = OraCon
If OraCon.State = adStateClosed Then
MsgBox "false"
End If
With cmd
.ActiveConnection = OraCon
.CommandType = adCmdStoredProc
.CommandText = "XXX_VALIDATE_ACCOUNT"
.CommandTimeout = 60
.Parameters.Append .CreateParameter("param1", adVariant, adParamInput, , "67000.2400.4001.01")
.Parameters.Append .CreateParameter("param2", adBoolean, adParamOutput)
.Parameters.Append .CreateParameter("param3", adVariant, adParamOutput)
.Execute
End With
MsgBox "Reurtn = P_CCID=" & cmd.Parameters(1) & "; P_RESULT=" & cmd.Parameters(2) & ";"
OraCon.Close
End sub
我将参数类型从adVariant更改为adVarchar,并收到一条错误消息,指出Parameter对象未正确定义。只有adVariant似乎有效。我想起了一个站点,它显示了在针对不同数据库执行时要使用的类型,并且它表示varchar2使用adVariant。 添加xxx_validate_account的过程代码:(注意,此过程调用名为fnd_flex_ext.get_ccid的内部oracle函数)
CREATE OR REPLACE PROCEDURE APPS."XXX_VALIDATE_ACCOUNT" (p_account_flex in varchar2,
p_valid out boolean,
p_message out varchar2) is
x_structure_id number;
x_ccid number := 0;
pragma autonomous_transaction;
begin
execute immediate 'alter session set nls_language = ''AMERICAN''';
p_valid := false;
select chart_of_accounts_id
into x_structure_id
from gl_ledgers
where short_name = 'XXX';
x_ccid := fnd_flex_ext.get_ccid(application_short_name => 'SQLGL',
key_flex_code => 'GL#',
structure_number => x_structure_id,
validation_date => to_char(sysdate,'YYYY/MM/DD HH24:MI:SS'),
concatenated_segments => p_account_flex);
if x_ccid > 0 then
p_valid := true;
commit;
else
p_valid := false;
p_message := fnd_message.get;
end if;
exception when others then
p_message := sqlerrm;
p_valid := false;
end xxx_validate_account;
/
更新:25/09/2015: 不幸的是,由于使用它的其他软件包和应用程序,我无法更新软件包。 所以,我决定创建一个具有简单功能的新包。 我确保输入和输出不是布尔值来解决该问题。 但是对于我的生活,我仍然得到同样的问题! 我试图在参数字符串中使用“adVarchar,100”,但是excel只是告诉我参数的类型错误。认真思考我的机器存在某种问题......
要遵循的新功能和代码:
create or replace package apps.xxxx_return_username is
function return_username (p_user_id in number) return varchar2;
end xxxx_return_username;
/
create or replace package body apps.xxxx_return_username as
function return_username(p_user_id in number) return varchar2 is
x_user_name varchar2(100);
begin
select user_name into x_user_name
from apps.fnd_user where user_id = p_user_id;
return x_user_name;
exception
when no_data_found then return 'xxxxx';
end return_username;
end xxxx_return_username;
/
Sub newfunctioncall()
Dim OraCon As New ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command
Set OraCon = CreateObject("ADODB.Connection")
OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
"Data Source=demo;" & _
"User ID=scott;" & _
"Password=tiger;"
OraCon.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon
If OraCon.State = adStateClosed Then
MsgBox "false"
End If
Set param1 = cmd.CreateParameter("param1", adNumeric, adParamInput, , "15483")
cmd.Parameters.Append param1
Set param2 = cmd.CreateParameter("param2", adVariant, , adParamReturnValue)
cmd.Parameters.Append param2
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "xxecu_return_username.return_username"
Set recset = cmd.Execute
MsgBox "Reurtn = USERNAME=" & cmd.Parameters(0)
OraCon.Close
End Sub
答案 0 :(得分:0)
您如何知道在Oracle数据库中执行有效命令?您可能希望首先使用SQLplus进行尝试。不太清楚你在哪里打电话。它可能是:
begin FND_FLEX_KEYVAL.ERROR_MESSAGE
但这不是一个完整的陈述。至少它需要以下内容。
begin
FND_FLEX_KEYVAL.ERROR_MESSAGE;
end;
但是,如果FND_FLEX_KEYVAL.ERROR_MESSAGE是一个函数,则前一个代码也不会运行。在这种情况下,您要选择函数值:
select FND_FLEX_KEYVAL.ERROR_MESSAGE from dual
答案 1 :(得分:0)
很好地描述了问题的背景......
我看到了几个可能出错的地方。如果不确切知道它可能是什么,我认为这是一个可以完成你所寻求的工作代码的例子 - 尽管我承认我可能有一些错误。
首先,在您的程序中,如果您将变量声明为参数:
create or replace procedure validate_segs(
operation in varchar2,
appl_short_name in varchar2,
key_flex_code in varchar2,
structure_number in number,
concat_segments in varchar2,
validation_date in date,
message out varchar2,
results out numeric
) as
BEGIN
message := 'Hello';
results := 1;
END;
然后,在VBA中,我认为你可以做这样的事情。使用VBA / OleDB和Oracle,我从来没有让布尔人表现出来。它们在C#中运行良好,但是我没有用VBA取得成功,所以我把它转换为这个例子中的一个数字,它似乎总是在VBA中转换为布尔值。
With cmd
.ActiveConnection = OraCon
.CommandText = "validate_segs"
.CommandType = adCmdStoredProc
.CommandTimeout = 60
.NamedParameters = True
.Parameters.Append .CreateParameter( _
"operation", adVarChar, adParamInput, 255, "CHECK_COMBINATION")
.Parameters.Append .CreateParameter( _
"appl_short_name", adVarChar, adParamInput, 255, "SQLGL")
.Parameters.Append .CreateParameter( _
"key_flex_code", adVarChar, adParamInput, 255, "GL#")
.Parameters.Append .CreateParameter( _
"structure_number", adNumeric, adParamInput, 10, 50268)
.Parameters.Append .CreateParameter( _
"concat_segments", adVarChar, adParamInput, 255, "67000.2400.4001.01")
.Parameters.Append .CreateParameter( _
"validation_date", adDate, adParamInput, , Now())
.Parameters.Append .CreateParameter("message", adVarChar, adParamOutput, 255)
.Parameters.Append .CreateParameter("return", adNumeric, adParamOutput, 1)
.Execute
End With
然后,实际挖掘存储过程的结果:
Dim result As Boolean
Dim message As String
message = cmd.Parameters(6).Value
result = cmd.Parameters(7).Value
我意识到你可能会被锁定在VBA中,但是如果你有选择权,那么.NET的界面可以为调试这种东西提供更好的环境。
- 编辑9/24/15 -
我认为你的代码几乎就在那里,但我可以看到剩下的两个问题,其中一个我不是100%肯定是一个问题,但我认为另一个是。我之前在解决方案中没有提及,但我现在认为这可能是核心问题:似乎OLEDB和Oracle Booleans并不能很好地协同工作。看到这篇文章:
https://support.microsoft.com/en-us/kb/306530
要解决此问题,如果将其切换为Oracle和VBA中的数字,它应该可以正常工作。
我不确定是否真实的另一个问题是,当我认为你应该使用字符串(或Varchar)Db Type时,你正在使用Variant Db类型。你提到你在文档中看到使用变体,所以也许这无关紧要......但是Varchar会起作用。你确实需要文本长度的附加参数来正确编译(我使用255作为踢法)。
所以,我建议的两个变化是:
1)在存储过程中从布尔值更改为数字:
CREATE OR REPLACE PROCEDURE "XXX_VALIDATE_ACCOUNT" (
p_account_flex in varchar2, p_valid out number, p_message out varchar2) is
-- blah blah blah
p_valid := 0;
2)更改您的VBA代码以期望返回一个数字(并将Variant转换为Varchar)
.Parameters.Append .CreateParameter("param1", adVarChar, adParamInput, 255, _
"67000.2400.4001.01")
.Parameters.Append .CreateParameter("param2", adNumeric, adParamOutput)
.Parameters.Append .CreateParameter("param3", adVarChar, adParamOutput, 255)
即使你把它作为布尔值
Dim result As Boolean
result = cmd.Parameters(1).Value
我必须说,调试器返回的错误消息根本没有帮助。