找不到PL / SQL过程的参数名称,仅在IIS7而非IIS6中

问题描述

我在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”参数类型错误,超出范围 可接受范围,或在调用时彼此冲突 的”

根据我发现的文档,这很好

在Internet上的论坛中进行了大量搜索之后,我发现以下文章:

这说明:

...由于库引用的绑定较晚而引发该错误, 因此VB根本不知道adCmdStoredProc和其他常量。那 表示此错误与ADODB,Ole或SP无关...

因此,您只需在开头就将这些值声明为常量即可,如本文中所述。

enter image description here

因此,在我的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 有了这个,问题就解决了!!

这是我的故事,非常感谢!!

结束。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...