甲骨文参数中陈述?(Oracle Parameters with IN statement?)

2019-09-01 07:21发布

有一个C#.net应用程序中,我需要修改。 目前该查询有效地做到这一点:

select * from contract where contractnum = :ContractNum

(非常简单,只是为了显示我们正在使用=和一个参数)

该参数读取从Settings.Settings在C#应用程序文件,并在其一个字符串。 我需要修改它包括多个合同,所以我想我可以改变SQL语句:

select * from contract where contractnum in (:ContractNum)

但不返回任何结果,无论我如何格式化参数字符串。

有没有一种方法可以让我得到神谕做一个与参数?

任何帮助表示赞赏,感谢所有。

Answer 1:

还没有找到支持评估包含逗号分隔作为唯一一个字符串变量分贝IN子句。

你的选择是子字符串变量,以便以逗号分隔的变量内容都变成了行,这样,那么你可以加入到这一点。 或者使用动态SQL,则执行语句前是作为一个字符串在一个存储过程构造SQL语句。



Answer 2:

您可以使用管道函数将一个字符串转换成可与使用表IN操作符。 例如(具有10gR2中测试):

SQL> select * from table(demo_pkg.string_to_tab('i,j,k'));

COLUMN_VALUE
-----------------
i
j
k

用下面的包:

SQL> CREATE OR REPLACE PACKAGE demo_pkg IS
  2     TYPE varchar_tab IS TABLE OF VARCHAR2(4000);
  3     FUNCTION string_to_tab(p_string VARCHAR2,
  4                            p_delimiter VARCHAR2 DEFAULT ',')
  5        RETURN varchar_tab PIPELINED;
  6  END demo_pkg;
  7  /

Package created
SQL> CREATE OR REPLACE PACKAGE BODY demo_pkg IS
  2     FUNCTION string_to_tab(p_string VARCHAR2,
  3                            p_delimiter VARCHAR2 DEFAULT ',')
  4        RETURN varchar_tab PIPELINED IS
  5        l_string          VARCHAR2(4000) := p_string;
  6        l_first_delimiter NUMBER := instr(p_string, p_delimiter);
  7     BEGIN
  8        LOOP
  9           IF nvl(l_first_delimiter,0) = 0 THEN
 10              PIPE ROW(l_string);
 11              RETURN;
 12           END IF;
 13           PIPE ROW(substr(l_string, 1, l_first_delimiter - 1));
 14           l_string          := substr(l_string, l_first_delimiter + 1);
 15           l_first_delimiter := instr(l_string, p_delimiter);
 16        END LOOP;
 17     END;
 18  END demo_pkg;
 19  /

Package body created

您的查询应该是这样的:

select * 
  from contract 
 where contractnum in (select column_value
                         from table(demo_pkg.string_to_tab(:ContractNum)))


Answer 3:

您可以使用数字的一个Oracle集合作为一个参数(绑定变量)当您使用ODP.NET为数据提供器。 这适用于Oracle服务器9,10或11和ODP.net释放> = 11.1.0.6.20。

当您使用Devart的用于Oracle .NET数据提供程序类似的解决方案是可能的。

我们选择与contractnum的3和4的合约。

我们使用Oracle类型合同的数字阵列转移到我们的查询。

MDSYS.SDO_ELEM_INFO_ARRAY的使用,因为如果我们采用这种已经可以预定义的Oracle类型,我们没有定义我们自己的Oracle类型。 您可以填写MDSYS.SDO_ELEM_INFO_ARRAY ,最大1048576号。

using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;

[OracleCustomTypeMappingAttribute("MDSYS.SDO_ELEM_INFO_ARRAY")]
public class NumberArrayFactory : IOracleArrayTypeFactory
{
  public Array CreateArray(int numElems)
  {
    return new Decimal[numElems];
  }

  public Array CreateStatusArray(int numElems)
  {
    return null;
  }
}

private void Test()
{
  OracleConnectionStringBuilder b = new OracleConnectionStringBuilder();
  b.UserID = "sna";
  b.Password = "sna";
  b.DataSource = "ora11";
  using (OracleConnection conn = new OracleConnection(b.ToString()))
  {
    conn.Open();
    using (OracleCommand comm = conn.CreateCommand())
    {
      comm.CommandText =
      @" select  /*+ cardinality(tab 10) */ c.*  " +
      @" from contract c, table(:1) tab " +
      @" where c.contractnum = tab.column_value";

      OracleParameter p = new OracleParameter();
      p.OracleDbType = OracleDbType.Array;
      p.Direction = ParameterDirection.Input;
      p.UdtTypeName = "MDSYS.SDO_ELEM_INFO_ARRAY";
      //select contract 3 and 4
      p.Value = new Decimal[] { 3, 4 };
      comm.Parameters.Add(p);

      int numContracts = 0;
      using (OracleDataReader reader = comm.ExecuteReader())
      {
        while (reader.Read())
        {
           numContracts++;
        }
      }
      conn.Close();
    }
  }
}

当一个省略的提示/ * +基数(标签10)* /不使用上contract.contractnum索引。 我以为contractnum是主键,以便本栏目将被编入索引。

在此还看到: http://forums.oracle.com/forums/thread.jspa?messageID=3869879#3869879



Answer 4:

对于使用参数中陈述,你可以使用这样的结构:

select * from contract where contractnum
in (select column_value from table (:ContractNum))

其中ContractNum是自定义数组类型。



文章来源: Oracle Parameters with IN statement?