sql >> Database >  >> RDS >> Oracle

SQL:doorzoek een lijst met kolommen met een bepaalde waarde (binnen een rij)

Dit is geen normaal stukje databasefunctionaliteit. Je bent echter niet de eerste die hier om heeft gevraagd, of iets dergelijks.

De oplossing vereist twee dingen. De eerste is de datadictionary; de Oracle-database ondersteunt Reflection niet, maar het wordt geleverd met een reeks weergaven die ons metagegevens over onze database-objecten geven. In dit geval hebben we user_tab_columns . nodig , die ons de kolommen voor een bepaalde tabel geeft. Het tweede ding is dynamische SQL; dit is de mogelijkheid om tijdens runtime een SQL-query samen te stellen en vervolgens uit te voeren. Er zijn een aantal manieren om dit te doen, maar meestal zijn ref-cursors voldoende.

De volgende code is een proof of concept. Er zijn vier parameters nodig:

  1. de naam van de tafel waarin u wilt zoeken
  2. de naam van de primaire sleutelkolom van die tabel
  3. de waarde van de primaire sleutel die u wilt beperken met
  4. de waarde waarnaar u wilt zoeken.

Het is ruw en klaar, dus je moet het misschien bewerken om de uitvoer op te schonen of om het programma flexibeler te maken.

create or replace procedure search_cols
  (tname in user_tables.table_name%type
   , pk_col in user_tab_columns.column_name%type
   , pk in number
   , val in number )
is
    firstcol boolean := true;
    stmt varchar2(32767);
    result varchar2(32767);
    rc sys_refcursor;
begin
    stmt := 'select ';
    << projection >>
    for lrec in ( select column_name from user_tab_columns
                  where table_name = tname
                  and column_name != pk_col
                  and data_type = 'NUMBER'
                  order by column_id )
    loop
        if not firstcol then
            stmt := stmt || chr(10) || '||'',''||';
        else
            firstcol := false;
        end if;
        stmt := stmt || ' case when '|| lrec.column_name||' = '|| val ||
                           ' then '''|| lrec.column_name || ''' else null end';
    end loop projection;
    stmt := stmt || chr(10)|| ' from '||tname||' where '|| pk_col || ' = '|| pk;
    --  dbms_output.put_line(stmt);
    open rc for stmt;
    fetch rc into result;
    close rc;
    dbms_output.put_line(tname || '::' || val || ' found in '||result);
end search_cols;
/

Zoals u kunt zien, is dynamische SQL moeilijk te lezen. Het is moeilijker te debuggen :) Het is dus een goed idee om een ​​middel te hebben om de definitieve verklaring te tonen.

Hoe dan ook, hier zijn de resultaten:

SQL> set serveroutput on size unlimited
SQL> exec search_cols('T23', 'ID', 111, 10)
T23::10 found in ,COL_B,COL_C,

PL/SQL procedure successfully completed.

SQL> exec search_cols('T23', 'ID', 222, 10)
T23::10 found in COL_A,,,

PL/SQL procedure successfully completed.

SQL>


  1. Waarom is een UDF zo veel langzamer dan een subquery?

  2. MySQL:datumbereik uitbreiden naar nieuwe rijen

  3. GROUP of DISTINCT na JOIN retourneert duplicaten

  4. SQL:Kan ik verwijzen naar/toegang krijgen tot de huidige rij in een vensterfunctie?