sql >> Databáze >  >> RDS >> Oracle

Vrací výsledek i pro prvky v seznamu IN, které v tabulce neexistují

Ze strany SQL byste mohli definovat typ tabulky a použít jej k připojení k vašim skutečným datům, něco jako:

create type my_array_type as table of number
/

create or replace function f42 (in_array my_array_type)
return sys_refcursor as
  rc sys_refcursor;
begin
  open rc for
    select a.column_value as id,
      case when t.id is null then 'missing'
        else 'present' end as status
    from table(in_array) a
    left join t42 t on t.id = a.column_value
    order by id;

  return rc;
end f42;
/

SQL Fiddle demo s funkcí wrapper, takže jej můžete přímo dotazovat, což dává:

        ID STATUS             
---------- --------------------
         1 present              
         2 present              
         3 present              
         4 missing              
         8 missing              
        23 present              

Z Java můžete definovat ARRAY na základě typu tabulky naplnit z pole Java a zavolat funkci přímo; vaše proměnná vazby s jedním parametrem je ARRAY a získáte zpět sadu výsledků, kterou můžete opakovat jako obvykle.

Jako obrys strany Java:

int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("MY_ARRAY_TYPE",
  conn);
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);

cStmt = (OracleCallableStatement) conn.prepareCall("{ call ? := f42(?) }");
cStmt.registerOutParameter(1, OracleTypes.CURSOR);
cStmt.setArray(2, ora_ids);
cStmt.execute();
rSet = (OracleResultSet) cStmt.getCursor(1);

while (rSet.next())
{
    System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}

Což dává:

id 1: present
id 2: present
id 3: present
id 4: missing
id 8: missing
id 23: present

Jak Maheswaran Ravisankar zmiňuje, umožňuje to předat libovolný počet prvků; nepotřebujete vědět, kolik prvků je v době kompilace (nebo se zabývat teoretickým maximem), nejste omezeni maximálním počtem výrazů povoleným v IN nebo délkou jednoho odděleného řetězce a nemusíte skládat a rozkládat řetězec, abyste předali více hodnot.

Jak zdůraznil ThinkJet, pokud nechcete vytvářet svůj vlastní typ tabulky, můžete použít předdefinovanou kolekci, jak je ukázáno zde; hlavní funkce je stejná kromě deklarace parametru:

create or replace function f42 (in_array sys.odcinumberlist)
return sys_refcursor as
...    

Funkce wrapper naplní pole mírně odlišně, ale na straně Java stačí změnit tento řádek:

ArrayDescriptor aDesc =
  ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );

Použití tohoto také znamená (jak poukázal i ThinkJet!), že můžete spustit svůj původní samostatný dotaz bez definování funkce:

select a.column_value as id,
case when t.id is null then 'missing'
else 'present' end as status
from table(sys.odcinumberlist(1, 2, 3, 4, 8, 23)) a
left join t42 t on t.id = a.column_value
order by id;

(SQL Fiddle).

A to znamená, že můžete dotaz volat přímo z Java:

int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);

sql = "select a.column_value as id, "
    + "case when t.id is null then 'missing' "
    + "else 'present' end as status "
    + "from table(?) a "
    + "left join t42 t on t.id = a.column_value "
    + "order by id";
pStmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pStmt.setArray(1, ora_ids);
rSet = (OracleResultSet) pStmt.executeQuery();

while (rSet.next())
{
    System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}

... které byste mohli dát přednost.

Existuje předdefinovaný ODCIVARCHAR2LIST zadejte také, pokud ve skutečnosti předáváte řetězce – zdá se, že váš původní kód pracuje s řetězci, i když obsahují čísla, takže si nejste jisti, které skutečně potřebujete.

Protože tyto typy jsou definovány jako VARRAY(32767) jste omezeni na hodnoty 32 kB, zatímco definování vlastní tabulky toto omezení odstraní; ale to samozřejmě záleží jen na tom, když předáváte hodně hodnot.



  1. Jak zakázat omezení cizího klíče v SQL Server (příklady T-SQL)

  2. Počkejte na statistiky a úložiště dotazů

  3. Zobrazit řazení v MariaDB

  4. SQL vyberte max(datum) a odpovídající hodnotu