IN查询的绑定变量

时间:2011-05-13 08:52:52

标签: c# oracle

使用绑定变量时,它没有获取值

eg,, SELECT * FROM EMP WHERE USER IN (:VALUES)

如果我使用上面的查询,则不执行

直接传递值

SELECT * FROM EMP WHERE USER IN (+ arraylist +)工作正常

========================================

这是样本caode

string[] Myarray = ListVal.split(','); Query = "SELECT * FROM EMP WHERE USER IN (:VALUES)"

OracleParameter Param = { new OracleParameter (":VALUES",OracleDBType.Array)

};

Param[0].value = Myarray;

using(dr = OracleFactory.ExecuteReader(CommandType.Text,Query,true,Param)) {

}

执行此操作时,我得到一个例外

无效的参数绑定ParameterName VALUES

4 个答案:

答案 0 :(得分:3)

您需要将值作为数组传递并稍微修改查询。以下代码适用于ODP.NET。我不知道是否也可以使用微软已弃用的Oracle驱动程序。

首先,您需要定义一个表类型(例如 VARCHAR ):

CREATE TYPE varchar_table AS TABLE OF VARCHAR2(2000); 

为查询创建参数时,将其声明为关联的PL / SQL数组:

OracleParameter param1 = new OracleParameter(); 
param1.OracleDbType = OracleDbType.Varchar2; 
param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 

然后分配一些值:

param1 = new string[2] { "johnp", "billt" }; 

您的查询需要演员:

SELECT * FROM EMP WHERE USER IN (TABLE(CAST(:values AS varchar_table)))

答案 1 :(得分:1)

不幸的是,您无法传递数组来绑定变量。

您唯一的选择是直接在查询中插入以逗号分隔的列表,或者编写自己的帮助程序/包装程序,自动将您的语句重写为

IN (:value1, :value2, :value3...)

并自动填充这些值。至少在某些情况下(如果您有大量具有相同参数的重复查询)可以简化Oracle解析器的工作。

答案 2 :(得分:0)

首先,我严重怀疑查询是否未执行。

或者更确切地说,如果没有被执行,那么你会得到一个例外,你会问这个问题。

我认为你所说的是你没有得到任何结果,而且那是不同的。

原因是您无法在大多数数据库中参数化IN子句。

最终要做的就是你只用一个值做一个IN子句。究竟该值是什么取决于您传入的集合以及如何将其转换为查询引擎的适当类型。可能是你最终在集合上调用了.ToString()并填充了那里的内容。

无论如何,都无法做到。你必须采用字符串连接方式。

或者,您可以创建SQL,以便在IN子句中添加足够的参数,使每个参数具有1个值。

换句话说,您可以为4元素集合执行此操作:

SELECT * FROM EMP WHERE USER IN (:V1, :V2, :V3, :V4)

然后将每个参数绑定到集合的其中一个元素。您仍然需要动态构建SQL。

答案 3 :(得分:0)

Also cross-posted to

我知道这是一个古老的问题,但这是所选答案不能解决我的问题的几个问题之一,我不想就该主题开始另一个话题,所以我只列出我发现的内容在我的旅行中希望对您有所帮助。这是一个重复的答案,因为我不确定如果有人正在寻找这样的解决方案,哪个更有可能出现。

我与Oracle的合作并不多,但是,就像在SQL Server中一样,似乎要传递表值参数,您需要具有一个具有EXECUTE权限的对应UDT(用户定义表)(我可能是错误)。这意味着建议使用内置SYS UDT的其他答案也需要一些运费,我无法弄清楚是否确实有可能将表传递给当前版本中不是PL / SQL存储过程的对象ODP.net。

第二,出于所有明显的原因(无法缓存执行计划或Oracle所谓的执行计划,扩展性不佳等),字符串解析解决方案是一个难题。

因此,我花了很多时间尝试在数据集市上使用表值参数来执行IN子句,在此之前,我仅对数据集具有READ权限,然后才被明显的盲目击中(在ASP.net上)论坛)。事实证明,Oracle“本地”支持Xml查询,因此您可以传递xml列表(如果您只需要这样),而不是传递值数组。同样,我可能是错的,但是它被当作合法的绑定参数来处理,这是一个使用起来很简单的示例(使用NuGet包的vb.net,ADO.net,ODP.net):

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()

这更是一种观察,而不是经过仔细研究的解决方案,因此请评论是否有任何不适当的方式这样做。

编辑。使用此方法显然有4000个字符的限制(如果为NVARCHAR,则为2000个字符),因此我不得不观看分页。如果经过检查,则得到的提示性错误消息是“ ORA-01460:请求未实现或不合理的转换”