Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Zwracanie wyniku nawet dla elementów z listy IN, które nie istnieją w tabeli

Od strony SQL możesz zdefiniować typ tabeli i użyć go do połączenia z prawdziwymi danymi, na przykład:

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;
/

Wersja demonstracyjna SQL Fiddle z funkcją opakowującą, dzięki której można bezpośrednio odpytywać, co daje:

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

Z Javy możesz zdefiniować ARRAY w oparciu o typ tabeli, zapełnij z tablicy Java i wywołaj funkcję bezpośrednio; twoją jednoparametrową zmienną wiązania jest ARRAY , a otrzymasz z powrotem zestaw wyników, który możesz normalnie powtarzać.

Jako zarys strony 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 daje:

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

Jak wspomina Maheswaran Ravisankar, pozwala to na przekazanie dowolnej liczby elementów; nie musisz wiedzieć, ile elementów jest w czasie kompilacji (lub radzić sobie z teoretycznym maksimum), nie jesteś ograniczony maksymalną liczbą wyrażeń dozwolonych w IN lub przez długość pojedynczego oddzielonego ciągu i nie musisz komponować i rozkładać ciągu, aby przekazać wiele wartości.

Jak zauważył ThinkJet, jeśli nie chcesz tworzyć własnego typu tabeli, możesz użyć predefiniowanej kolekcji, pokazanej tutaj; główna funkcja jest taka sama z wyjątkiem deklaracji parametru:

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

Funkcja wrappera nieco inaczej zapełnia tablicę, ale po stronie Javy wystarczy zmienić ten wiersz:

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

Użycie tego oznacza również (jak zauważył ThinkJet!), że możesz uruchomić swoje oryginalne, samodzielne zapytanie bez definiowania funkcji:

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;

(Skrzypce SQL).

A to oznacza, że ​​możesz wywołać zapytanie bezpośrednio z Javy:

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

... co wolisz.

Istnieje predefiniowana ODCIVARCHAR2LIST wpisz też, jeśli faktycznie przekazujesz ciągi znaków - Twój oryginalny kod wydaje się działać z ciągami, nawet jeśli zawierają liczby, więc nie jesteś pewien, którego naprawdę potrzebujesz.

Ponieważ te typy są zdefiniowane jako VARRAY(32767) jesteś ograniczony do 32k wartości, podczas gdy zdefiniowanie własnej tabeli usuwa to ograniczenie; ale oczywiście ma to znaczenie tylko wtedy, gdy przekazujesz wiele wartości.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Odzyskiwanie plików edytora SQL (zapytania, procedury) po awarii lub zawieszeniu się ropuchy w przypadku awarii lub zawieszenia Oracle

  2. Jak zainstalować Oracle Instant Client na komputerze Mac?

  3. Funkcja ASIN() w Oracle

  4. Funkcje o wartościach tabelarycznych w ORACLE 11g ? ( widoki parametryczne )

  5. Tworzenie lub symulacja dwuwymiarowych tablic w PL/SQL