Oracle
 sql >> Base de données >  >> RDS >> Oracle

Paramètres Oracle avec instruction IN ?

Vous pouvez utiliser une collection Oracle de nombres comme paramètre (variable de liaison) lorsque vous utilisez ODP.NET comme fournisseur de données. Cela fonctionne avec le serveur Oracle 9, 10 ou 11 et la version ODP.net>=11.1.0.6.20 .

Une solution similaire est possible lorsque vous utilisez le fournisseur de données .NET de Devart pour Oracle.

Sélectionnons les contrats avec contractnum's 3 et 4.

Nous devons utiliser un type Oracle pour transférer un tableau de numéros de contrat vers notre requête.

MDSYS.SDO_ELEM_INFO_ARRAY est utilisé car si nous utilisons ce type Oracle déjà prédéfini, nous n'avons pas à définir notre propre type Oracle. Vous pouvez remplir MDSYS.SDO_ELEM_INFO_ARRAY avec un maximum de 1048576 numéros.

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

L'index sur contract.contractnum n'est pas utilisé lorsqu'on omet l'indice /*+ cardinality(tab 10) */. J'ai supposé que contractnum est la clé primaire, donc cette colonne sera indexée.

Voir aussi ici :http://forums.oracle.com/forums/thread.jspa?messageID=3869879#3869879