[MySQL] Spalte Ignorieren

Cyperfriend

Der ohne Avatar
Registriert
14 Juli 2013
Beiträge
1.123
Gibt es eine Möglichkeit eine Spalte bei einer MySQL-Abfrage zu ignorieren? Ich lese zwei Tabellen aus, aber in beiden ist der gleiche Foreign Key eingetragen, welcher auf die ID einer dritten Tabelle verweist. (Diese wird in meinem Fall aber nicht mit ausgelesen, da diese ID in der Session mitgegeben wird)

Ich finde es furchtbar mühselig die Abfrage so zu schreiben
[src=php]select db_tabelle1.*, db_tabelle2.id, db_tabelle2.spalte2, db_tabelle2.spalte3 from db_tabelle1[/src]
Bei jeder Änderung im Script müsste man auch daran denken, dass man die Abfrage neu anpasst und außerdem sieht es halt echt hässlich aus. Bei einer Tabelle mit wenig Spalten mag eine solche Lösung noch vertretbar sein, aber wenn eine Tabelle mal zehn und mehr Spalten hat ist das echt lästig.
 
Ignorieren kannst du eine Spalte bei Verwendung der *-Syntax nicht, allerdings musst du natürlich nicht alle selektierten Werte auch tatsächlich nutzen. Abgesehen davon ist jedoch das Ansprechen der tatsächlich benötigten Spalten über ihre Bezeichner im SELECT-Query im Allgemeinen die sauberere Lösung, insbesondere dann, wenn du aus einer grösseren Tabelle bzw. einem Verbind aus mehreren Tabelle nur einige wenige Spalten benötigst.
 
  • Thread Starter Thread Starter
  • #3
Ich brauche aber an dieser Stelle alle Spalten von Tabelle 1 und alle Spalten der Tabelle 2 mit Ausnahme einer Spalte, weil diese in beiden Tabellen identisch ist. (Foreign Key eben)
 
Identisch ist sie nicht - da sie vom DBMS mit dem vollen Namen also DB.Tabellenname.Spaltenname angesprochen wird - und der komplette Name ist nicht gleich außer bei einem selfjoin ...
 
Auf PHP-Seite gibt es beim Selektieren, z.B. mit fetch_array(), aber das Problem, dass DB und Tabellenname nicht berücksichtigt werden, da nur der Spaltenname im Index des Arrays landet. Daher wird nur die letzte Spalte, bei gleich lautendem Namen, im Array abgelegt, bzw. werden die anderen dadurch überschrieben.

Dadurch wird das ganze unzuverlässig, denn was passiert wenn später gleich lautende Spalten, unabhänig vom Programm, in der Datenbank dazukommen? -Dann landen plötzlich unerwartete Werte im Array, man arbeitet dann mit den falschen Spalten, wenn das Programm nicht auch angepasst wird.

Lösen lässt sich das Problem meines Wissens nur mit Alias-Namen für die Spalten beim SELECT oder durch numerisches ansprechen des Indexes, dann geht es aber nicht mehr mit Wildcard. Oder tabellenübergreifende, eindeutigen Spaltennamen im DBMS.

Schön wäre, es wenn man PHP sagen könnte, dass der Array-Index der Rückgabewerte von PHP-DB-Funktionen wie fetch_array() mindestens aus Tabellenname+Spaltenname bestehen soll.
 
Zuletzt bearbeitet:
Das kannst du, wenn du den Zugriff auf die Datenbank durch eine Modellschicht abstrahierst welche Kenntnis über die Datenbankstruktur hat und dir dementsprechend die passende Queries incl. Alias für die Spalten automatisch generieren kann.

Wenn du allerdings die Queries immer direkt innerhalb der Anwendungslogik in SQL schreiben willst, tja, dann hast du Pech.

Die Wildcard-Funktionalität ist eh nur eine Komfort-Funktion für handgeschriebene, dahingeschluderte Abfragen, es gibt in der Praxis keinen Grund warum man die in einer Anwendung verwenden sollte. Zu hoch ist das Risiko, dass nach einer Änderung / Erweiterung / Optimierung der Datenbankstruktur der Wildcard mit einem mal nicht mehr die selben Spalten wie vorher liefert - der Fehler aber unbemerkt bleibt weil der Wildcard immer noch gültig ist und lediglich die Spalten im Resultat fehlen was dann erst während der weiteren Verarbeitung auffallen kann. Das kann nicht passieren, wenn man immer schön brav alle benötigten(!) Spalten explizit angibt (dann schmeißt dir die Datenbank zu Recht einen Fehler wenn eine benötigte Spalte nicht mehr existiert!), und einen Alias zu vergeben bei der Gelegenheit tut auch nicht weh.
 


ja du hast natürlich recht mit den Wildcards. Aber in php wird es wohl den Fehler den du beschreibst nicht geben. Da du die Spalten so ansprichst:

PHP:
Expand Collapse Copy
<?php
$abfrage = "SELECT * FROM xyz";
$ergebnis = mysql_query($abfrage);
while($row = mysql_fetch_object($ergebnis))
{
   echo $row->spaltenname;
}
?>

Anders sieht es in java aus:

PHP:
Expand Collapse Copy
for (int i = 1; i <= columns; i++) {
      System.out.println(rs.getString(i));
}

Da die Spalten über einen Index angesprochen werden
 
Das kannst du, wenn du den Zugriff auf die Datenbank durch eine Modellschicht abstrahierst welche Kenntnis über die Datenbankstruktur hat und dir dementsprechend die passende Queries incl. Alias für die Spalten automatisch generieren kann.
Das bedeutet oftmals jedoch auch, dass man die Information über das Datenmodell dupliziert - sie wird dann sowohl durch die Datenbankstruktur als auch durch die Modellschicht repräsentiert. Das kann natürlich sinnvoll sein, insbesondere dann, wenn ein Modell-Datensatz nicht bloss einer Zeile in einer einzelnen Tabelle entspricht oder wenn die Datenbank nicht exklusiv durch eine Anwendung verwendet wird und daher u.U. ohne Kenntnis der Anwendung geändert werden kann, doch als die in jedem Fall beste Lösung würde ich das nicht betrachten. Wenn man das Modell direkt aus der Datenbankstruktur ableiten will und jede Tabellenzeile genau einem Datensatz des Modells entspricht (was für eine spätere Erweiterbarkeit IMHO nicht unbedingt schlecht ist), kann ein SELECT-*-Query eine Daseinsberechtigung haben.



Cyperfriend, allerdings sehe ich in diesem Fall dein Problem nicht. Bei Verwendung von fetch_assoc bzw. fetch_object wird die Spalte überschrieben (was kein Problem darstellt, wenn die Inhalte ohnehin identisch sind) und im SQL-Statement (WHERE, ORDER BY, ...) musst du sie mit vollem Namen ansprechen.
 
Nun es gäbe auch noch die Möglichkeit nicht-assoziativ zuzugreifen. Etwa mit und dem result_type MYSQL_NUM.
Dann wird das Ergebnis zwar unglaublich "unleserlich", die Überschreibungen aufgrund gleicher Namen sollten jedoch nicht mehr stattfinden.

Andererseits könnte man dort, wo es notwendig ist auch einfach das Query modifizieren und die Spalten einfach umbenennen:

Statt:
[src=mysql]SELECT beitrag.id, autor.id, ...[/src]
Einfach:
[src=mysql]SELECT beitrag.id as beitragsid, autor.id as autorid, ...[/src]

Dann sind zwar SELECT * - Querys nicht mehr möglich, die sind aber mMn ohnehin eher suboptimal.
Als vollkommen böse oder schlecht möchte ich sie allerdings nicht bezeichnen!
 
Nun es gäbe auch noch die Möglichkeit nicht-assoziativ zuzugreifen. Etwa mit und dem result_type MYSQL_NUM.
Dann wird das Ergebnis zwar unglaublich "unleserlich", die Überschreibungen aufgrund gleicher Namen sollten jedoch nicht mehr stattfinden.
Das stimmt, allerdings sind dann SELECT-*-Queries wirklich problematisch, da eine Änderung des Datenbankschemas, z.B. die Entfernung oder das Einfügen einer Spalte, dann nicht-offensichtliche Änderungen an diversen Indizes notwendig macht. Ausserdem führen bei numerischen Indizes Tippfehler sehr leicht zu schwer zu identifizierenden Fehlern, während sie bei assoziativen Indizes durch die erzeugten E_NOTICE-Warnungen beim Zugriff auf ein unbekanntes Feld leicht zu finden sind. Daher würde ich von einer numerischen Indexierung des Ergebnisses im Allgemeinen absehen.
 
Zuletzt bearbeitet:
Ja, deshalb habe ich es auch versucht eher vorsichtig als Möglichkeit zu beschreiben und keine Empfehlung dafür ausgesprochen.
 
  • Thread Starter Thread Starter
  • #12
Also ich hatte mir eine Lösung wie diese gedacht (von der Logik her)
[src=php]select db_tabelle1.*, db_tabelle2.*(except[spalteX]) from db_tabelle1[/src]

Da es aber sowas offenbar nicht gibt (ein echtes Versäumnis wie ich meine) ist die Frage soweit beantwortet.
 
Es gibt afaik keinen Shortcode dafür, allerdings könntest du dir das mit Subquerys zusammenbasteln:

[src=mysql]SELECT db_tabelle1.*, cropped2.*
FROM db_tabelle1, (SELECT db_tabelle2.feld_i, db_tabelle2.feld_j, db_tabelle2.feld_k from tabelle2) cropped2
...[/src]

Wenn dich dann stört, dass du beim Query immer das Subquery formulieren musst, könntest du noch mit Views arbeiten:

Einmalig den View anlegen:
[src=mysql]CREATE OR REPLACE VIEW `cropped2` AS
SELECT db_tab2.feld1, db_tab2.feld2, db_tab2.feld3, ...
FROM db_tab2[/src]

Querys immer mit Hilfe von View ausführen:

[src=mysql]SELECT db_tabelle1.*, cropped2.*
FROM db_tabelle1, cropped2
...[/src]
 
Beispiel:
[src=mysql]SELECT tabelle1.id as 'idTabelle1', tabelle2.id as 'idTabelle2' FROM tabelle1 LEFT JOIN tabelle2 ON (tabelle2.idTabelle1 = tabelle1.id)
oder
SELECT tabelle1.*, tabelle2.* FROM tabelle1 LEFT JOIN tabelle2 ON (tabelle2.idTabelle1 = tabelle1.id)[/src]

Damit ich per PHP an beide IDs komme, muss ich hier entweder Alias-Namen verwenden, oder das Array numerisch ansprechen. Beides ist doof, gerade wenn die Tabellen aus sehr vielen Spalten bestehen und eine gewisse Dynamic dabei sein soll.

Könnte man nicht nicht auch einfach die PHP-DB Funktionen durch overriding/extending/subclassing der richtigen PHP-Klassen so umbiegen, das diese den Tabellennamen im assoziativen Array mit aufnehmen wenn ich z.B. fetch_array() ausführe?

Die Frage hierbei wird sein, ob die PHP-DB-Klassen, wie mysqli, intern überhaupt wissen können aus welcher Tabelle die Spalte ursprünglich kam. Diese Info müsste bereits der Datenbanktreiber vermutlich an PHP während des SELECTs übergeben.

Dann könnte man die Daten im Array immer noch assoziativ, aber diesmal richtig adressiert, z.B. so ansprechen: $row['Tabelle1.id'], $row['Tabelle2.id'].
Auch wäre das vorhanden sein von zwei identischen Spaltennamen, aber von der Bedeutung her unterschiedlichen Feldwerten, in unterschiedlichen Tabellen, insbesondere beim Joinen doch kein Problem mehr, auch auf Aliase könnte man dann verzichten und Wildcards würden immer noch gehen.
 
Zuletzt bearbeitet:
Zurück
Oben