问题描述
我在oracle getspname
中有一个存储过程,它将接收2个输入参数(varchar2和number)和一个游标类型的输出参数。
正在执行此存储过程的应用程序有些旧,它正在IIS6中使用VB6连接到ORACLE中的此SP,并且我正在将其迁移到IIS7。
Provider=MSDAORA.1;Data Source=XXXXXXXX;User ID=XXXXXXXXX;Password=XXXXXX
SQL是:
{call schema.Pkg_name.getspname(?,?,{resultset 0,io_cursor})}
参数:11111111; 0
在IIS6中,执行该过程并返回游标数据没有问题, 在IIS7中,如果没有,它发送输入参数,这也可以,但是我需要将这些字段发送给它,以符合应用的业务逻辑。
此解决方案也已实现,但该错误在仅输入或输出参数为varchar2 type SP的SP中得以复制stackoverflow.com/a/50643323/5904375
VB6:
Public Function execProcedure( _
ByVal sConnString As String,_
ByVal sSQL As String,_
ByRef oRs As Variant,_
ByVal sParameters As Variant,_
ByRef vntRespuesta As Variant,_
Optional Encrypt As Boolean _
) As Integer
Dim Params,i
Dim RsCmd
Dim oRecordSet
Dim RspMsg As Variant
Dim RspMsg1 As Variant
Dim RspMsg2 As Variant
Dim oConec
Dim BeforeConn As Boolean
Dim auxErr As Integer
Dim auxValue As Variant
Dim StringReg As Variant
Dim oEncrypt
Dim bEncrypt As Boolean
On Error GoTo Error_handler
'** Se verifica encriptacion del string de conexion
bEncrypt = False
If Not IsMissing(Encrypt) Then
If Encrypt Then bEncrypt = True
End If
If bEncrypt Then
Set oEncrypt = CreateObject("NR_DBconn.Encrypt")
StringReg = oEncrypt.EncriptarChrTran("azv",sConnString,2)
Set oEncrypt = Nothing
Else
StringReg = sConnString
End If
BeforeConn = True
Set ctxObject = GetObjectContext
strNombreObjeto = "ADODB.Command"
Set RsCmd = ctxObject.CreateInstance("ADODB.Command")
'Set RsCmd = CreateObject("ADODB.Command")
strNombreObjeto = "ADODB.Recordset"
Set oRecordSet = ctxObject.CreateInstance("ADODB.Recordset")
'Set oRecordSet = CreateObject("ADODB.Recordset")
strNombreObjeto = "ADODB.Connection"
Set oConec = ctxObject.CreateInstance("ADODB.Connection")
'Set oConec = CreateObject("ADODB.Connection")
'*
'* Verifica si el sSQL es válido
'*
If sSQL = "" Or Len(sSQL) = 0 Then
ctxObject.SetAbort
'La transaccion finaliza con error
Err.Raise INSTRUCCION_INVALID,"Verificar sSQL"
End If
'*
'* Se verifica string de conexión
'*
If (StringReg = "") Then
ctxObject.SetAbort
'La transaccion finaliza con error
Err.Raise INSTRUCCION_INVALID,"Verificar string de Conexion"
End If
BeforeConn = False
oConec.Open StringReg
With RsCmd
.ActiveConnection = oConec
.CommandText = sSQL
.CommandType = adCmdText ' adCmdStoredProc 'adCmdText
If Len(sParameters) <> 0 Then
Params = Split(sParameters,";")
For i = 0 To UBound(Params)
.Parameters(i).Direction = adParamInput
.Parameters(i).Value = Params(i)
Next i
End If
End With
oRecordSet.CursorLocation = adUseClient
oRecordSet.CursorType = adOpenStatic
oRecordSet.LockType = eltBatchOptimistic
Set oRecordSet = RsCmd.Execute()
'*
'* Verifica el resultado
'*
auxErr = -1
If oRecordSet.State = 1 Then
If oRecordSet.EOF Or oRecordSet.BOF Or oRecordSet Is Nothing Then
RspMsg1 = "0"
RspMsg2 = "No se obtuvo recordset de vntRespuesta - warning"
RspMsg = "[" & RspMsg1 & "]: " & RspMsg2
auxErr = 0
Set oRs = Nothing
Else
RspMsg1 = "0"
RspMsg2 = ""
RspMsg = "" '"[" & RspMsg1 & "]: " & RspMsg2
'------traspasa el recordsetresult a recordset desconectado
Dim Rsx
Dim j
Dim NumFields
Set Rsx = New ADODB.Recordset
NumFields = oRecordSet.Fields.Count - 1
With Rsx
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.LockType = eltBatchOptimistic
Set .ActiveConnection = Nothing
For i = 0 To NumFields
With .Fields
.Append oRecordSet.Fields(i).Name,adBSTR
End With
Next i
.Open
Do While Not oRecordSet.EOF
.AddNew
For j = 0 To NumFields
auxValue = oRecordSet.Fields(j)
.Fields(j) = CheckNull(auxValue)
Next j
oRecordSet.MoveNext
Loop
.MoveFirst
End With
'-------------
Set oRs = Rsx
'Set oRecordSet.ActiveConnection = Nothing
Set oRecordSet = Nothing
Set Rsx = Nothing
auxErr = 1
End If
Else
RspMsg1 = "2"
RspMsg2 = "No se obtuvo recordset de vntRespuesta - operacion no necesita"
RspMsg = "[" & RspMsg1 & "]: " & RspMsg2
auxErr = 2
Set oRs = Nothing
End If
vntRespuesta = RspMsg
Set RsCmd = Nothing
oConec.Close
Set oConec = Nothing
' If IsObject(oRs) Then
' execProcedure = oRs.RecordCount
' Else
execProcedure = auxErr
' End If
'*
'* La transacción finaliza exitosamente
ctxObject.SetComplete
Exit Function
Error_handler:
execProcedure = -1
RspMsg = ErrorMessage("SQLserver.execProcedure.",Err.Number,Err.Source,Err.Description,sSQL)
'*
'* Fin de la función,ha ocurrido un Error Fatal
'*
On Error Resume Next
If Not BeforeConn Then
If (oConec.State = adStateOpen) Then
oConec.Close
End If
End If
Set oConec = Nothing
vntRespuesta = RspMsg
'*
'* La transacción finaliza con error
'*
ctxObject.SetAbort
End Function
功能错误VB6:
Private Function ErrorMessage(ErrPath,ErrCod,ErrSource,ErrDescription,sSQL)
Dim RspMsg1
Dim RspMsg2
Dim strPathError
strPathError = "[" & ErrPath & "." & Err.Source & "] "
Select Case (ErrCod)
Case INSTRUCCION_INVALID
RspMsg1 = INSTRUCCION_INVALID
RspMsg2 = strPathError & " El string 'sSQL' esta mal formado." & _
"Verifique que el String 'sSQL' esté de acuerdo al formato SQL"
Case STRING_CONNECTION
RspMsg1 = STRING_CONNECTION
RspMsg2 = strPathError & "No existe string de conexion para esta Aplicacion "
Case NOT_REC_RETURN
RspMsg1 = NOT_REC_RETURN
RspMsg2 = strPathError & "No se retornaron registros." & _
"Intente de nuevo o con otros valores en el 'sSQL'. Este error puede deberse a una falla en la conexion con la Base de Datos. (" & sSQL & ")"
Case NOT_REC_FOUND
RspMsg1 = NOT_REC_FOUND
RspMsg2 = strPathError & "No se encontro registros." & _
"Intente con otros valores en la 'sSQL'. (" & sSQL & ")"
Case 429:
RspMsg1 = "-1"
RspMsg2 = strPathError & " No se puede crear el componente: '" & strNombreObjeto & _
"Verifique que el componente esté instalado correctamente."
'Error manipulado. En parametros de la base de datos.
Case -2147217887
RspMsg1 = "-1"
RspMsg2 = strPathError & "Error al insertar campo." & _
"Verifique el largo del valor del campo no exceda al maximo permitido en la definicion de la TABLA de la Base de Datos."
Case Else 'Cualquier otro tipo de Error
RspMsg1 = "-1"
RspMsg2 = strPathError & ErrDescription
End Select
ErrorMessage = "[" & RspMsg1 & "]: " & RspMsg2
End Function
此SP还经过了独立测试,以排除任何问题,它可以正常运行 SP ORACLE:
PROCEDURE getspname (value IN varchar2,value2 IN number,io_cursor IN OUT t_cursor)
AS
BEGIN
........
END;
END getspname;
解决方法
我在2020年8月17日星期五凌晨3点解决了这个问题,
我决定使用提供程序(OraOLEDB.Oracle)从ASP直接调用oracle SP,从而复制该行为,这是错误“运行时错误3001参数类型错误……当设置ADODB.Command对象成员”
ASP代码:
名称文件:test.asp
<%@ Language=VBScript %>
<%Response.Buffer = false%>
<%Response.Expires = 0%>
<%
Dim strConnect
strConnect = "Provider=OraOLEDB.Oracle;Data Source=XXXXXXXX;User ID=XXXXXXXXX;Password=XXXXXX"
Dim cn,rs,cmd,param
set cn = Server.CreateObject( "ADODB.Connection" )
cn.Open Cstr(strConnect)
set cmd = server.CreateObject ("ADODB.Command")
with cmd
set .ActiveConnection = cn
.NamedParameters = True
.CommandText = "{call schema.Pkg_name.getspname({resultset 0,io_cursor})}"
.CommandType = 1
end with
set rs = server.CreateObject ( "ADODB.Recordset" )
set rs = cmd.execute
Set rs = cmd.Execute
Do Until rs.EOF
for each x in rs.fields
response.write(x.name)
response.write("=")
response.write(x.value)
response.write(",")
next
response.write("<br />")
rs.MoveNext
Loop
rs.Close
%>
<%
Dim strConnect_cn
strConnect_cn = "Provider=OraOLEDB.Oracle;Data Source=XXXXXXXX;User ID=XXXXXXXXX;Password=XXXXXX"
Dim cn_cn,rs_cn,cmd_cn,param1,param2
set cn_cn = Server.CreateObject( "ADODB.Connection" )
cn_cn.Open Cstr(strConnect_cn)
set cmd_cn = server.CreateObject ("ADODB.Command")
with cmd_cn
set .ActiveConnection = cn_cn
.CommandText = "{call schema.Pkg_name.getspname(?,?,{resultset 0,io_cursor})}"
.CommandType = 1
end with
cmd_cn.parameters.append(cmd_cn.createParameter("",adVariant,adParamInput,"11111111"))
cmd_cn.parameters.append(cmd_cn.createParameter("","0"))
set rs_cn = server.CreateObject ( "ADODB.Recordset" )
set rs_cn = cmd_cn.execute
Set rs_cn = cmd_cn.Execute
Do Until rs_cn.EOF
for each x in rs_cn.fields
response.write(x.name)
response.write("=")
response.write(x.value)
response.write(",")
next
response.write("<br />")
rs_cn.MoveNext
Loop
rs_cn.Close
%>
<html>
<head>
<title> Links </title>
</head>
<body>
<p>test.asp</p>
</body>
</html>
这段代码向我抛出输入参数的以下问题,其中参数的类型错误。
“运行时错误3001”参数类型错误,超出范围 可接受范围,或在调用时彼此冲突 的”
根据我发现的文档,这很好
-
http://www-db.deis.unibo.it/courses/TW/DOCS/w3schools/asp/met_comm_createparameter.asp.html
-
https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum?view=sql-server-ver15
在Internet上的论坛中进行了大量搜索之后,我发现以下文章:
这说明:
...由于库引用的绑定较晚而引发该错误, 因此VB根本不知道adCmdStoredProc和其他常量。那 表示此错误与ADODB,Ole或SP无关...
因此,您只需在开头就将这些值声明为常量即可,如本文中所述。
因此,在我的ASP(test.asp)代码的开头,添加:
Const adVarChar = 200
Const adParamInput = &H1
Const adParamOutput = &H2
Const adCmdStoredProc = &H4
Const adVariant = 12
魔术,它起作用了!
然后,我修改了我的VB6代码,这是我必须用来符合要迁移的应用程序的业务逻辑的代码。
在文件的开头添加:
Const adVarChar As Long = 200
Const adParamInput As Long = &H1
Const adParamOutput As Long = &H2
Const adCmdStoredProc As Long = &H4
Const adCmdText As Long = 1
Const adUseClient As Long = 3
Const adOpenStatic As Long = 3
Const adVariant As Long = 12
然后像这样更改我的VB6代码:
With RsCmd
.ActiveConnection = oConec
.CommandText = sSQL
.CommandType = adCmdText ' adCmdStoredProc 'adCmdText
If Len(sParameters) <> 0 Then
.NamedParameters = True
Params = Split(sParameters,";")
For i = 0 To UBound(Params)
.Parameters.Append (.CreateParameter("",Params(i)))
Next i
End If
End With
使用提供者:MSDAORA.1 有了这个,问题就解决了!!
这是我的故事,非常感谢!!
结束。