Bernd: (Oracle) SELECT geht, SELECT DISTINCT nicht. Arrrrgh!

Hää? Oracle spinnt!

Das hier geht:

SELECT products.*
FROM   products
INNER JOIN product_info ON products.id = product_info.product_id

Das hier nicht:

SELECT DISTINCT products.*
FROM   products
INNER JOIN product_info ON products.id = product_info.product_id

FEHLER in Zeile 1:
ORA-00932: Inkonsistente Datentypen: - erwartet, CLOB erhalten

Warum warum warum??? Aaaaaaaargh!

Die Tabelle "products" besteht im wesentlichen aus id (Number), name (varchar2), und beschreibung (CLOB). Anscheinend ist es die Beschreibung die das Problem verursache. Aber waruuuuuum?

Grüße
Bernd.

PS: Sorry, Oracle treibt einen einfach in den Wahnsinn!

  1. Hi,

    aus der Fehlermeldung lässt sich doch schliessen, das Oracle eine
    DISTINCT Operation mit CLOB Datentypen nicht unterstützt? Ich nehme
    mal an, dass solch eine Operation mit grösseren Mengen an CLOB Daten
    auch sehr resourcenfressend ist, weil die Inhalte zum Vergleich mit
    heran gezogen werden müssen.

    Musst du denn unbedingt die "Beschreibungs"-Spalte mit in den Vergleich
    mit hineinnehmen?

    Hast du mehrere Produkte mit
    [ ] den gleichen Ids
    [ ] den gleichen Namen
    [ ] den gleichen Beschreibungen
    in der selben Tabelle?

    Eigentlich sollte das Produkt in der Tabelle Products durch seine Id
    oder auch den Namen eindeutig bezeichnet sein. Dein Problem klingt
    nach einem sehr mässigen Design.

    Ciao, Frank

    1. yo,

      Eigentlich sollte das Produkt in der Tabelle Products durch seine Id
      oder auch den Namen eindeutig bezeichnet sein.

      da er aber einen JOIN durchführt, können da durchaus mehrere treffer mit gleichem inhalt trotz der id der EINEN tabelle vorkommen.

      Ilja

      1. Hi Ilja,

        wozu macht er denn den Join, wenn er a) sowieso nur die linke Joinhälfte
        danach benutzt und b) alle Spalten von der linken Joinhälfte in den
        Distinct nimmt? Wenn er mehr Einträge pro Produkt-Id hat, welchen will
        er denn genau? Falsche Mittel für den falschen Zweck. :)

        Wie Joins funktionieren, weiss ich schon, so doof bin ich auch nicht ;)

        Ciao, Frank

        1. yo,

          wozu macht er denn den Join, wenn er a) sowieso nur die linke Joinhälfte
          danach benutzt und b) alle Spalten von der linken Joinhälfte in den
          Distinct nimmt? Wenn er mehr Einträge pro Produkt-Id hat, welchen will
          er denn genau? Falsche Mittel für den falschen Zweck. :)

          weil es datensätze in der products tabelle geben kann, die ausgeschlossen werden. dies kann man entweder über den join oder aber über die unterabfrage machen. aber eines von beiden sollte man tun, sprich beide tabellen müssen irgendwie mit rein. und das macht dann den DISTINCT erforderlich, weil es sich um eine 1:n beziehung handelt.

          Ilja

    2. Musst du denn unbedingt die "Beschreibungs"-Spalte mit in den Vergleich
      mit hineinnehmen?

      Hä? Wo siehst du das denn??
      Die Tabelle product_info hat einen Foreign Key auf die products Tabelle. Die Beschreibung ist in der Products-Tabelle gespeichert und wird mit gar nichts verglichen - wozu auch. Der Join geht über den PK von products ("id") und den FK von product_info ("product_id"). Die product_info Tabelle speichert eben Informationen zu Produkten die sich je nach Kunde unterscheiden können (den WHERE-Teil habe ich der Übersichtlichkeit halber nur weggelassen, hätte dies aber zugegebenermaßen verdeutlicht).
      Ich finde das ein sehr schönes Design :-)

      Bernd

      1. Hi,

        Musst du denn unbedingt die "Beschreibungs"-Spalte mit in den Vergleich
        mit hineinnehmen?
        Hä? Wo siehst du das denn??

        Da:

        SELECT DISTINCT products.*

        Du wirfst dem DISTINCT alle Spalten der Tabelle vor, also auch die "beschreibung".
        Also muß Oracle auch die Beschreibung-Spalte vergleichen, um Duplikate zu filtern.

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        Schreinerei Waechter
        O o ostern ...
        Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
        1. SELECT DISTINCT products.*

          Du wirfst dem DISTINCT alle Spalten der Tabelle vor, also auch die "beschreibung".
          Also muß Oracle auch die Beschreibung-Spalte vergleichen, um Duplikate zu filtern.

          Muß er das wirklich? Er sollte doch sicherlich klug genug sein nur den Primary Key ("id") zum Vergleich heranzuziehen.
          Hmmm... mal nachforschen.

          Gruß,
          Bernd

          1. yo,

            mal von der sortierung abgesehen, hat es dem mit to_char nun geklappt oder nicht ?

            Ilja

            1. mal von der sortierung abgesehen, hat es dem mit to_char nun geklappt oder nicht ?

              Oh ja, sorry. Danke - hat geklappt.
              Ich hab mich der Einfachheit halber aber dann doch entschlossen stattdessen ein varchar2 zu nehmen dann kann die Beschreibung halt nur 4 000 Zeichen lang sein, das sollte in meinem Fall aber genügen.

              Gruß,
              Bernd

          2. Moin!

            SELECT DISTINCT products.*

            Du wirfst dem DISTINCT alle Spalten der Tabelle vor, also auch die "beschreibung".
            Also muß Oracle auch die Beschreibung-Spalte vergleichen, um Duplikate zu filtern.

            Muß er das wirklich? Er sollte doch sicherlich klug genug sein nur den Primary Key ("id") zum Vergleich heranzuziehen.
            Hmmm... mal nachforschen.

            So ist DISTINCT nun mal definiert. Es filtert alle komplett identischen Zeilen bis auf eine aus dem Ergebnis heraus.

            Das bedeutet: Man kann DISTINCT eigentlich nur dann anwenden, wenn man selektiv tatsächlich einzelne Spalten abfragt, bei denen es zu Duplikaten kommt. DISTINCT auf eine Tabelle anzuwenden, in der eine Spalte UNIQUE ist (oder zumindest den Anschein hat, wie bei IDs üblich), ist absolut sinnlos, weil DISTINCT nichts filtern kann - jede Ergebniszeile unterscheidet sich von jeder anderen Zeile ja mindestens in dieser ID.

            - Sven Rautenberg

            --
            My sssignature, my preciousssss!
  2. yo,

    Hää? Oracle spinnt!

    nein, du verstehst nur nicht die vorhersage des orakels.... ;-)

    in prinzip sagst du es ja selber, es liebt an der spalte mit dem datentyp CLOB. die funktion to_Char() ist dein freund.

    Ilja

  3. Hallo,

    Die Tabelle "products" besteht im wesentlichen aus id (Number), name (varchar2), und beschreibung (CLOB). Anscheinend ist es die Beschreibung die das Problem verursache. Aber waruuuuuum?

    DISTINCT ist sowieso der denkbar schlechteste Weg, wenn es um solche Abfragen geht. Meist ist der Weg über GROUP BY wesentlich besser, da kontrollierter.

    An sich wäre bei den von Dir geposteten Statements ja ein JOIN nicht notwendig, allerdings vermute ich, dass Du uns in Bezug auf die eigentlich notwendige Abfrage nicht die ganze Wahrheit sagst;-)

    Wenn Du z.B. also nur Produkte selektieren willst, die in product_info bestimmte bedingungen erfüllen, so könntest Du eventuell auch über ein Subselect, oder über die obig angesprochene Verwendung von GROUP BY zum gewünschten Ziel kommen.

    Und ja, Oracle hat auch, so wie die meisten mir bekannten Datenbanken Probleme beim behandeln von LOB-Feldern.

    Grüße
      Klaus

    1. yo,

      DISTINCT ist sowieso der denkbar schlechteste Weg, wenn es um solche Abfragen geht. Meist ist der Weg über GROUP BY wesentlich besser, da kontrollierter.

      was sollte den daran besser sein ? bei einem DISTINCT muss ich ein schlüßelwort hinschreiben und beziehe mich automatisch auf alle auszugebenen spalten. bei GROUP BY muss ich jede spalte expliziet angeben. für mich hört sich das nach mehr schreibarbeit an und ist somit fehleranfälliger.

      An sich wäre bei den von Dir geposteten Statements ja ein JOIN nicht notwendig, allerdings vermute ich, dass Du uns in Bezug auf die eigentlich notwendige Abfrage nicht die ganze Wahrheit sagst;-)

      wieso das den nicht, der join sorgt dafür, dass datensätze ohne entsprechenden eintrag in beiden tabellen nicht genommen werden. das ist in aller regel ein unterschied zu den datensätze nur einer tabelle.

      Wenn Du z.B. also nur Produkte selektieren willst, die in product_info bestimmte bedingungen erfüllen, so könntest Du eventuell auch über ein Subselect, oder über die obig angesprochene Verwendung von GROUP BY zum gewünschten Ziel kommen.

      die bedingung in seinem fall ist eben die bedingung des JOINS, siehe oben. das was du sagst, wäre eine korrelierende unterabfrage und da wiederum würde ich den JOIN vorziehen.

      Ilja

      1. was hältst du einfach von:

          
        SELECT    Produkt.Id,  
                  Produkt.Name,  
                  Produkt.Beschreibung  
        FROM Produkt  
        WHERE Produkt.Id IN (SELECT {DISTINCT} ProduktId FROM Produkt_Info)  
        
        

        Punkt. Ende. Aus. Da brauchts kein Join, keine korrelierenden (du magst
        dieses Wort, nich?) Unterabfragen ...

        Bedenken, andere Vorschläge?

        Ciao, Frank

        1. yo,

          Bedenken, andere Vorschläge?

          nein das stimmt, es geht auch ohne korrelierende unterabfrage. das war mein trugschluss. allerdings bleibe ich bei meiner aussage, was GROUP BY betrifft.

          Ilja