OracleParameter和IN子句

rc.*_*rc. 16 .net c# oracle

有没有办法使用System.Data.OracleClient向IN子句添加参数.

例如:

string query = "SELECT * FROM TableName WHERE UserName IN (:Pram)";
OracleCommand command = new OracleCommand(query, conn);
command.Parameters.Add(":Pram", OracleType.VarChar).Value = "'Ben', 'Sam'";
Run Code Online (Sandbox Code Playgroud)

Qua*_*noi 12

您可以通过以下方式更轻松地完成ODP.NET:

  1. TABLE在数据库中创建一个类型:

    CREATE TYPE t_varchar2 AS TABLE OF VARCHAR2(4000);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建一个集合参数:

    OracleParameter param = new OracleParameter();
    param.OracleDbType = OracleDbType.Varchar2;
    param.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 填写参数:

    param = new string[2] {"Ben", "Sam" };
    
    Run Code Online (Sandbox Code Playgroud)
  4. 将参数绑定到以下查询:

    SELECT * FROM TableName WHERE UserName IN (TABLE(CAST(:param AS t_varchar2)));
    
    Run Code Online (Sandbox Code Playgroud)

  • 那是因为你需要编写"WHERE UserName IN(SELECT column_value FROM TABLE(CAST(:param AS t_varchar2)))",但是你可能会得到"ORA-01484:数组只能绑定到PL/SQL语句"这表明这些代码应放在PL/SQL语句中,而不是C#代码中 (4认同)
  • 它对我不起作用,我一直得到ORA-00936:缺少表情 (2认同)
  • 这种方法需要数据库权限才能修改架构-这不是我的情况。 (2认同)

小智 11

您可以将其包装在OracleCommandExtension方法中:

public static class OracleCommandExtension
{
    public static OracleCommand AddParameterCollection<TValue>(this OracleCommand command, string name, OracleType type, IEnumerable<TValue> collection)
    {
        var oraParams = new List<OracleParameter>();
        var counter = 0;
        var collectionParams = new StringBuilder(":");
        foreach (var obj in collection)
        {
            var param = name + counter;
            collectionParams.Append(param);
            collectionParams.Append(", :");
            oraParams.Add(new OracleParameter(param, type) { Value = obj });
            counter++;
        }
        collectionParams.Remove(collectionParams.Length - 3, 3);
        command.CommandText = command.CommandText.Replace(":" + name, collectionParams.ToString());
        command.Parameters.AddRange(oraParams.ToArray());
        return command;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 到了2019年,Oracle仍然没有接受数组存在的事实。无论如何......这对我有用,但我必须将“OracleType”更改为“OracleDbType” (3认同)
  • 在2016年,托管.NET客户端到Oracle仍然无法将数组参数传递到`in`.只有oracle本地客户端才可以. (2认同)

小智 6

也许使用不同的方法

SELECT * FROM SCOTT.EMP WHERE EMPNO IN (SELECT TO_NUMBER(X.COLUMN_VALUE) FROM XMLTABLE('7788,7900') X);
Run Code Online (Sandbox Code Playgroud)

或者

SELECT * FROM SCOTT.EMP WHERE ENAME IN (SELECT X.COLUMN_VALUE.GETSTRINGVAL() FROM XMLTABLE('"SCOTT", "JAMES"') X);
Run Code Online (Sandbox Code Playgroud)

其中 XMLTABLE 的内容可以是单个参数。因此它应该可以在任何语言中使用。


Ada*_*ler 5

我知道这是不久前被问过的问题,但不是一个出色的答案。

我会做这样的事情 - 请原谅粗略的伪代码

string args[] = {'Ben', 'Sam'};
string bindList = "";
for(int ii=0;ii<args.count;++ii)
{
  if(ii == 0)
  {
   bindList += ":" + ii;
  }
  else
  {
   bindList += ",:" + ii;
  }
  OracleParameter param = new OracleParameter();
  param.dbType = types.varchar;
  param.value = args[ii];
  command.Parameters.Add(param);
}

query = "select * from TableName where username in(" + bindList + ")";
Run Code Online (Sandbox Code Playgroud)

因此,查询最终会包含 in(:1,:2) ,并且每个查询都是单独绑定的。

这里也有一个类似的问题:Oracle/c#: How do i use Bind Variables with select statements to return multiple record?


小智 1

这样你的查询将是:

SELECT * FROM TableName WHERE UserName IN ('''Ben'', ''Sam''');

这两个名称将作为一个值输入。

查看来自asktom.oracle.com 的这个线程,了解如何获取列表中的动态。

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:210612357425