webentwicklung-frage-antwort-db.com.de

Können Sie alles auswählen, außer 1 oder 2 Feldern, ohne dass der Autor einen Krampf hat?

Ist es in PLSQL möglich, alle Felder in einer Tabelle außer 1 oder 2 auszuwählen, ohne die gewünschten Felder angeben zu müssen?

Beispiel hat die Mitarbeiter-Tabelle die Felder: 

  • ich würde
  • vorname
  • nachname
  • hobbys

Ist es noch möglich, eine Anfrage ähnlich zu schreiben 

select * from employee

während Sie das Feld hobbies verlassen, ohne etwas davon schreiben zu müssen?

select id, firstname, lastname from employee
43
Steve
42
Yahia

Wenn Sie den Druck des Schreibers vermeiden möchten, können Sie SQL Developer verwenden und die Spaltenliste für Sie generieren lassen:

select column_name||','
from all_tab_columns
where table_name = 'YourTableName'

Und dann nehmen Sie einfach die eine oder zwei Spalten heraus, die Sie nicht möchten.

Sie können auch verwenden 

SELECT listagg(column_name, ',') within group (order by column_name) columns
FROM all_tab_columns
WHERE table_name = 'TABLE_NAME'
GROUP BY table_name;
37

Laufen Sie auf Oracle 12c?

Wenn ja, überlegen Sie, ob dies Ihren Bedürfnissen entspricht:

alter table mytable modify column undesired_col_name INVISIBLE;

In diesem Fall ist die Spalte undesired_col_name vollständig verwendbar, wird jedoch von allen SELECT *-Anweisungen und dergleichen (z. B. %ROWTYPE) ausgeschlossen, als ob sie nicht vorhanden wäre.

19
Matthew McPeak

Ein alter Thread, aber ja ... es gibt eine Möglichkeit, dies in Oracle zu tun:

with

employee(id, firstname, lastname, hobbies) as
(
  select 1, 'a', 'b', '1' from dual union 
  select 2, 'a', 'b', '2' from dual union 
  select 3, 'a', 'b', '3' from dual union 
  select 4, 'c', 'd', '3' from dual union 
  select 5, 'e', 'f', '2' from dual  
)

select * 
from employee 
pivot
( 
  max(1) -- fake  
  for (hobbies) -- put the undesired columns here
  IN () -- no values here...
) 
where 1=1 -- and your filters here...
order by id

Um zu verstehen, wie die PIVOT funktioniert und warum es die Frage löst, lassen Sie uns ein besseres Beispiel für unsere employee-Beispieltabelle geben:

select * 
from employee 
pivot
(
  max(id) foo,
  max(1)  bar
  for (hobbies) 
  IN ('2' as two, '3' as three)
)

Das Ergebnis hier ist: 

 FIRSTNAME | LASTNAME | TWO_FOO | TWO_BAR | THREE_FOO | THREE_BAR 
 c d null null 4 1 
 e f 5 1 null null 
 a b 2 1 3 1 

Die exakt gleiche Ausgabe kann mit dieser verständlicheren Abfrage erzielt werden:

select 
  firstname,
  lastname,
  max(case when hobbies = '2' then id end) two_foo,
  max(case when hobbies = '2' then 1  end) two_bar,
  max(case when hobbies = '3' then id end) three_foo,
  max(case when hobbies = '3' then 1  end) three_bar
from employee 
group by
  firstname,
  lastname

Die Spalte hobbies wird also niemals ausgewählt, genau wie die Spalte id, die beide innerhalb von angegeben sind PIVOT Klausel. Alle anderen Spalten werden gruppiert und ausgewählt.

Nun, zur ersten Abfrage zurückkehrend, funktioniert das aus zwei Gründen:
1- Sie verlieren keine Zeile im Gruppierungsprozess, weil ich würde Die Spalte ist eindeutig und es wurden keine Spalten für Aggregationen angegeben. 
2- erzeugt als Drehpunkt N * M neue Spalten, wobei N = Anzahl der Werte von IM Klausel und M = Anzahl der angegebenen Aggregationen. Wenn also keine Filter vorhanden sind, erzeugt diese harmlose Aggregation 0 * 1 = 0 neue Spalten und entfernt die in den angegebenen Spalten PIVOT Klausel, das ist nur die hobbys.


ANTWORT AUF KOMMENTAR 1

Die erste Zeile dieser Frage lautet: "... ohne die gewünschten Felder angeben zu müssen" . In allen anderen Antworten werden in den vorgeschlagenen Abfragen die gewünschten Felder in angegeben WÄHLEN Klausel, außer in meiner eigentlich. 

Auch in der Frage sagt der Titel "... ohne Krampf des Schreibers" . Nun, was ist das richtige Maß, um den Krampf eines Schriftstellers zu identifizieren? Mein Bestes wäre es, einen guten SQL-Standard für dieses Problem zu erwarten und mit meiner Antwort zu vergleichen. Ich glaube, dieser "Standard" könnte so etwas sein SELECT * NOT IN ([col1], [col2], ...)

Nun kann ich in beiden Abfragen sehen:

  • eine Liste unerwünschter Spalten;
  • ein IM Klausel;
  • eine Klausel mit drei Zeichen - FOR und NICHT;

Es bedeutet, dass Sie in meiner Herangehensweise ein wenig mehr schreiben müssen, da Sie eine gefälschte Aggregation benötigen PIVOT Klausel ... aber es sind wirklich wenige Zeichen mehr ... 

17
Felypp Oliveira

query_generator ist eine PL/SQL-Funktion, die ein select string für eine Tabelle (1. Parameter) zurückgibt, jedoch einige Spalten (2. Parameter) ausschließt.

stringlist und putil.join stammen aus PL/SQL Commons .

stringlist ist eine einfache Liste von Strings: create type StringList as table of varchar2(32767); und putil.join ist nur eine normale Join-Funktion.

create or replace function quote_list(p_list in stringlist)
return stringlist as
  v_list stringlist := stringlist();
begin
  v_list.extend(p_list.last);
  for i in p_list.first .. p_list.last loop
    v_list(i) := '''' || p_list(i) || '''';
  end loop;

  return v_list;
end;
/
show errors

create or replace function query_generator(
  p_table in varchar2,
  p_exclude in stringlist
) return varchar2 as
  v_table constant varchar2(31) := upper(p_table);
  v_exclude constant varchar2(32676) :=
    upper(putil.join(quote_list(p_exclude), ','));
  v_stmt_str constant varchar2(32676) :=
    'select column_name from all_tab_columns where table_name = ''' ||
    v_table || ''' and column_name not in (' || v_exclude ||
    ') order by column_id';
  type stmt_cur_t is ref cursor;
  v_stmt_cur stmt_cur_t;
  v_column_name varchar2(31);
  v_query varchar2(32676) := 'select ';
begin
  open v_stmt_cur for v_stmt_str;

  loop
    fetch v_stmt_cur into v_column_name;
    exit when v_stmt_cur%notfound;
    v_query := v_query || lower(v_column_name) || ', ';
  end loop;

  close v_stmt_cur;

  select rtrim(v_query, ', ') into v_query from dual;

  v_query := v_query || ' from ' || p_table || ';';

  return v_query;
end;
/
show errors

Anwendungsbeispiel:

exec dbms_output.put_line(query_generator('all_tables', stringlist('segment_created', 'result_cache')))
2
user272735

Was das OP suchte, war ungefähr so:

SELECT * MINUS hobbies from...

Um nicht viel zu tippen (und alle Spaltennamen richtig zu machen), ist es am besten, die Tabellenbeschreibung zu öffnen und alle Spaltennamen auszuschneiden und einzufügen und die nicht gewünschten Namen zu löschen Setzen Sie sie auf ein oder zwei Striche.

Es ist einfach, schnell, genau und Sie verwirren nicht die nächste Person, die an Ihrem Code arbeiten muss. 

2
user2785110
WITH O AS
(
SELECT 'SELECT ' || rtrim('NULL AS "Dummy",' || LISTAGG('"'||column_name || '"', ',' ) within group (ORDER BY COLUMN_NAME),',')|| ' FROM "'||TABLE_NAME||'"' AS SQL, TABLE_NAME  FROM USER_TAB_COLUMNS  GROUP BY (TABLE_NAME)
)
SELECT DBMS_XMLGEN.GETXMLTYPE ((SELECT REPLACE(SQL,',COLUMNNAME','') FROM O WHERE TABLE_NAME = 'TABLENAME')) FROM DUAL
1
clq

ansicht erstellen: -

ansicht view_name erstellen asselect id, first_name, last_name von Employee.

hinweis: - Dies ist wie eine virtuelle Tabelle in Ihrer Datenbank, kann jedoch Werte in der tatsächlichen Tabelle beeinflussen.

0

Polymorphe Tabellenfunktionen von Oracle 18c ermöglichen es, alles aus einer Tabelle auszuwählen und eine Liste von Spalten auszuschließen:

select * from everything_but(employee, columns(hobbies));

ID   FIRSTNAME   LASTNAME
--   ---------   --------
1    John        Smith

Für das Erstellen dieser Funktion wird das folgende Paket benötigt, das von Tim Halls Website kopiert wird https://Oracle-base.com/articles/18c/polymorphic-table-functions-18c :

CREATE OR REPLACE PACKAGE poly_pkg AS

  FUNCTION everything_but(tab IN TABLE,
                          col IN COLUMNS)
  RETURN TABLE PIPELINED
  ROW POLYMORPHIC USING poly_pkg;

  FUNCTION describe (tab IN OUT DBMS_TF.table_t,
                     col IN     dbms_tf.columns_t)
    RETURN DBMS_TF.describe_t;

END poly_pkg;
/


CREATE OR REPLACE PACKAGE BODY poly_pkg AS

  FUNCTION describe (tab IN OUT DBMS_TF.table_t,
                     col IN     dbms_tf.columns_t)
    RETURN DBMS_TF.describe_t
  AS
  BEGIN
    -- Loop through all the table columns.
    FOR i IN 1 .. tab.column.count() LOOP
      -- Loop through all the columns listed in the second parameter.
      FOR j IN 1 .. col.count() LOOP
        -- Set pass_through to true for any columns not in the exclude list.
        tab.column(i).pass_through := (tab.column(i).description.name != col(j));
        -- Exit inner loop if you find a column that shouldn't be included.
        EXIT WHEN NOT tab.column(i).pass_through;
      END LOOP;
    END LOOP;

    RETURN NULL;
  END;

END poly_pkg;
/

Ich habe auch diese einfache Wrapper-Funktion erstellt, um einen besseren Namen zu erhalten. Und erstellt eine einfache Beispieltabelle.

CREATE OR REPLACE FUNCTION everything_but(tab IN TABLE, col in COLUMNS)
  RETURN TABLE PIPELINED
  ROW POLYMORPHIC USING poly_pkg;
/

create table employee as
select 1 id, 'John' firstname, 'Smith' lastname, 'fishing' hobbies from dual;
0
Jon Heller