2012-08-29 3 views
12

Wie erstelle ich eine temporäre Ergebnismenge für die Verwendung in einer SQL ohne Erstellen einer Tabelle und Einfügen der Daten?Oracle - Erstellen Sie eine temporäre Ergebnismenge für die Verwendung in einer Abfrage

Beispiel: Ich habe eine Liste von, sagen wir 10 Codes zum Beispiel. Ich möchte dies in eine Abfrage einfügen und dann die Datenbank abfragen, um zu sehen, welche Codes in dieser temporären Liste in einer Tabelle nicht existieren.

Wenn es bereits in einer Tabelle ist, kann ich so etwas wie:

SELECT 
    ITEM_CODE 
FROM 
    TEMP_ITEMS 
MINUS 
SELECT 
    ITEM_CODE 
FROM 
    M_ITEMS 

Gibt es einen Weg ohne PL mit/SQL und reine SQL eine temporäre Rowset zu erstellen, bevor die Abfrage? Bitte antworten Sie nicht mit so etwas wie:

SELECT 1 FROM DUAL 
UNION ALL 
SELECT 2 FROM DUAL 

Ich bin irgendwie an etwas gedacht, wo ich meine Codes in einer IN-Anweisung zur Verfügung stellen kann, und es stellt sich, dass in Reihen für die Verwendung in einer späteren Abfrage.

Edit: so weiß jeder mein Ziel hier, im Grunde bekomme ich manchmal eine Liste von Produktcodes, die ich finden muss, welche in der Liste nicht in unserem System eingerichtet sind. Ich möchte einen schnellen Weg, dies in eine SQL-Anweisung zu werfen, so dass ich sehen kann, welche nicht im System sind (anstatt Daten usw. zu importieren). Ich habe diese in der Regel in Excel, dann eine Formel tun, wie:

="'"&A1&"'," 

Damit ich meine durch Kommata getrennte Liste erstellen kann.

+0

Was meinen Sie, wenn Sie sagen, Sie haben eine Liste? Ich nehme an, dass Sie sich nicht auf eine PL/SQL-Sammlung beziehen. Stellen Sie fest, dass Sie etwas wie eine durch Komma getrennte Zeichenfolge haben, die eine Liste darstellt? Und Sie möchten diese Zeichenfolge in SQL analysieren, um separate Zeilen mit den einzelnen Codes zu erhalten? –

+0

Ja das ist richtig. So etwas wie (‚A‘, ‚B‘, ‚C‘) – Lock

Antwort

22

Wenn Sie Oracle 11g verwenden Sie können dies tun,

with t as 
(
select (column_value).getnumberval() Codes from xmltable('1,2,3,4,5') 
) 
SELECT * FROM t 
WHERE NOT EXISTS (SELECT 1 FROM M_ITEMS M WHERE codes = M.ITEM_CODE); 

oder

with t as 
(
select (column_value).getstringval() Codes from xmltable('"A","B","C"') 
) 
SELECT * FROM t 
WHERE NOT EXISTS (SELECT 1 FROM M_ITEMS M WHERE codes = M.ITEM_CODE); 
+0

Das sieht vielversprechend aus. Ich werde es versuchen. – Lock

+0

Danke, das wird funktionieren für das, was ich will! – Lock

3

ich gehen würde:

with t as (
    select 1 as val from dual union all 
    select 2 as val from dual 
) 
select . . . 

Und dann „t“ verwenden oder was auch immer Sie es nennen, in dem nachfolgenden Abfrageblock.

Ich bin mir nicht sicher, was der Einwand gegen die Auswahlmethode ist. . . Einfach die gewünschten Werte in eine Spalte in Excel einfügen und den Code für jeden Wert erstellen, indem Sie die Formel kopieren. Fügen Sie die Ergebnisse anschließend wieder in Ihre Abfrageoberfläche ein.

Wenn Sie eine temporäre Tabelle verwenden möchten, können Sie die Klausel values ​​verwenden. Alternativ können Sie Zeichenfolgenfunktionen verwenden, wenn Sie nur die IN-Funktionalität wünschen. Setzen Sie die Werte in einer durch Kommata getrennte Liste und überprüfen, um zu sehen, ob es einen bestimmten Wert übereinstimmt:

where ','||<list>||',' like '%,'||col||',%' 
+0

Danke für die Antwort, aber meine Frage Staaten Ich will nicht thsese Antworten. Wenn Sie mit ungefähr 100 Datensätzen arbeiten, ist es nicht wirklich machbar, dies auf diese Weise zu tun. Ich hatte gehofft, dass es einen besseren Weg gibt, als es so zu machen. – Lock

3

Es gibt zwei Ansätze, auf die ich mich stützen würde:

1. Globale temporäre Tabelle

Obwohl Sie sagen, dass Sie keine Tabelle erstellen möchten, hängt es von , warum Sie keine Tabelle möchten. Wenn Sie eine globale temporäre Tabelle erstellen, sind die Zeilen nur für die Sitzung sichtbar, in die sie eingefügt wurden. Es ist also so, als hätten Sie eine private In-Memory-Tabelle, aber Sie können alle Vorteile einer realen Tabelle nutzen zu ihm.

2.Pipeline-Funktion

Sie können eine Funktion erstellen, die die Ergebnisse in einem Formular zurückgibt, das mit dem Operator TABLE() abgefragt werden kann. Mehr Infos hier: http://www.oracle-base.com/articles/misc/pipelined-table-functions.php

2

Es ist ein bisschen kitschig aussehen. Sie können jedoch einen String mit regulären Ausdrücken in separate Zeilen zerlegen, vorausgesetzt, Sie verwenden 10g oder höher. Zum Beispiel

SQL> ed 
Wrote file afiedt.buf 

    1 SELECT REGEXP_SUBSTR('a,b,c,def,g', '[^ |,]+', 1, LEVEL) parsed_str 
    2  FROM dual 
    3* CONNECT BY LEVEL <= REGEXP_COUNT('a,b,c,def,g', '[^ |,]+') 
SQL>/

PARSED_STR 
-------------------------------------------- 
a 
b 
c 
def 
g 

Persönlich würde ich eine Pipeline-Tabellenfunktion oder einen PL/SQL-Block finden, die eine Sammlung einfacher zu verstehen erzeugt, aber wenn man es in SQL zu tun hat, können Sie.

Wenn Sie eine Liste der Produktcodes erhalten, die sich bereits in einer Datei befinden, erscheint es sinnvoller, eine externe Tabelle zu verwenden, um die Datei als Tabelle verfügbar zu machen oder SQL zu verwenden * Loader zum Laden der Daten in eine Tabelle (temporär oder permanent), die Sie abfragen können. Abgesehen von einem dieser Optionen, wenn Sie wirklich die Liste in Excel zunächst manipulieren wollen, wäre es sinnvoll, eine IN Liste in Excel zu generieren und einfach kopieren und Vergangenheit, die in Ihre Anfrage. Das Erzeugen einer durch Kommas getrennten Liste von Codes in Excel, nur um diese Liste in ihre Bestandteile in SQL zu analysieren, scheint viel zu viele Schritte.

+0

gut, aber mit 11g nur: http://docs.oracle.com/cd/B28359_01/server.111/b28286/functions135.htm –

2

Dies ist interessant, weil es nicht eine Vereinigung ist und paßt in einem einzigen wählen. Sie haben die Zeichenfolge mit Trennzeichen eingeben ('a/b/c/def') zwei Mal aber:

SELECT regexp_substr('a/b/c/def', '[^/]+', 1, ROWNUM) var, 
regexp_substr('2/432/sd/fsd', '[^/]+', 1, ROWNUM) var2 
FROM dual 
CONNECT BY LEVEL <= length(regexp_replace('a/b/c/def', '[^/]', '')) + 1; 

var var2 
=== ==== 
a 2 
b 432 
c sd 
def fsd 

Hinweis: Credits gehen zu: https://stackoverflow.com/a/1381495/463056

So mit Klausel die es würde some geben wie:

with tempo as (
SELECT regexp_substr('a/b/c/def', '[^/]+', 1, ROWNUM) var, 
regexp_substr('2/432/sd/fsd', '[^/]+', 1, ROWNUM) var2 
FROM dual 
CONNECT BY LEVEL <= length(regexp_replace('a/b/c/def', '[^/]', '')) + 1 
) 
select ... 

oder Sie es in einer FROM-Klausel verwenden:

select ... 
from (
SELECT regexp_substr('a/b/c/def', '[^/]+', 1, ROWNUM) var, 
regexp_substr('2/432/sd/fsd', '[^/]+', 1, ROWNUM) var2 
FROM dual 
CONNECT BY LEVEL <= length(regexp_replace('a/b/c/def', '[^/]', '')) + 1 
) tempo 
Verwandte Themen