Oracle Parameters with IN statement?

前端 未结 5 1426
忘了有多久
忘了有多久 2020-11-30 08:14

Got a c#.net app which I need to modify. The query at the moment effectively does this:

select * from contract where contractnum = :ContractNum
5条回答
  •  被撕碎了的回忆
    2020-11-30 08:40

    I know this is an old question but it is one of several in which the selected answer did not solve my problem and I don't want to start yet another thread on this topic so I'll just put down what I found in my travels in the hope that it might help someone.

    I don't work with Oracle much but, like in SQL Server, it seems that to pass a table-valued parameter you need to have a corresponding UDT (user defined table) to which you have EXECUTE permissions (I could be wrong). This means that other answers suggesting the use of a built-in SYS UDT come with some freight and I couldn't figure out whether it really is possible to pass a table to something that is not a PL/SQL stored procedure in the current version of ODP.net.

    Second, the string-parse solution is a kludge for all the obvious reasons (can't cache the execution plan or whatever Oracle calls it, doesn't scale well, etc).

    So I spent rather a lot of time trying do the IN-clause using a table-valued parameter on a datamart to which I have only READ permission before I was hit by a blinding flash of the obvious (At an ASP.net forum no less). Turns out Oracle supports Xml queries 'natively' so instead of passing an array of values you can pass an xml list (if that is all you need). Again, I may be wrong, but it gets handled as a legitimate bind parameter and this is an example of how simple it is to use (vb.net, ADO.net, ODP.net using NuGet package):

        Dim xe As New XElement("l", New XElement("i", "ITEM-A"), New XElement("i", "ITEM-B"))
        Using conn As New OracleConnection(myConnectionString)
            conn.Open()
            Using cmd As OracleCommand = conn.CreateCommand()
                cmd.CommandType = CommandType.Text
                Dim query As String
                query = "  SELECT s.FOO, q.BAR " & vbCrLf
                query &= " FROM TABLE1 s LEFT OUTER JOIN " & vbCrLf
                query &= "      TABLE2 q ON q.ID = s.ID " & vbCrLf
                query &= " WHERE (COALESCE(q.ID, 'NULL') NOT LIKE '%OPTIONAL%') AND "
                query &= "       (s.ID IN ("
                query &= "                      SELECT stid "
                query &= "                      FROM XMLTable('/l/i' PASSING XMLTYPE(:stid) COLUMNS stid VARCHAR(32) PATH '.')"
                query &= "                 )"
                query &= "        )"
                cmd.CommandText = query
                Dim parameter As OracleParameter = cmd.Parameters.Add("stid", OracleDbType.NVarchar2, 4000)
                parameter.Value = xe.ToString
                Using r As OracleDataReader = cmd.ExecuteReader
                    While r.Read()
                        //Do something
                    End While
                End Using
            End Using
            conn.Close()
    

    This is more of an observation than a carefully researched solution so please comment if there is anything inappropriate about doing it this way.


    There is apparently a 4000 character limit using this method (2000 if NVARCHAR) so I had to watch my paging. The informative error message you get if you go over is

    ORA-01460: unimplemented or unreasonable conversion requested

提交回复
热议问题