Patrick: UPDATE anhand Spalten-Index

Hallo ihr,

ich möchte ein mysql-UPDATE durchführen und dabei die Spalte nicht über ihren Namen, sondern über den index der Spalte durchführen. Ich finde leider nirgends eine Erklärung wie ich bei einem UPDATE damit umgehe, bzw diesen anspreche.
Bei Abfragen über SELECT usw ists kein Thema.
Um Fragen für Gründe vorzubeugen, es handelt sich um ein Umfrage-Scipt, wo die entsprechende Spalte hochgezählt werden soll, diese aber nur über den Spaltenindex ansprechen kann.

LG Patrick

  1. Hi,

    ich glaube du hast da ein Problem. Meines Wissens ist die Spaltenreihenfolge in einer Tabelle zufällig, ein Beispiel ist die Reihenfolge im Create-Statement. Das ist genau der Grund, warum von SELECT * abgeraten wird, man kann das Ergebnis nur mit einer gewissen Wahrscheinlichkeit vorhersagen.
    Ich könnte mir gut vorstellen, dass UPDATE diese Möglichkeit der nummerischen Adressierung gar nicht erst unterstützt.

    MfG
    Rouven

    --
    -------------------
    Buy when there's blood running in the street and sell when everyone is pounding at your door, clawing to own your equities  --  Wisdom on Wallstreet
    1. Hi Rouven,

      also ich lasse mich gern eines besseren belehren, aber das wäre mir nicht nur neu, sondern würde auch dies hier auch keinen Sinn ergeben:
      http://de2.php.net/manual/de/function.mysql-fetch-array.php
      unter dem Beispiel 1 wird dort auf die Abfragevarianten mittels Nutzung des Spaltenindex hingewiesen.

      Dort steht, wenn ich es richtig verstehe, auch, dass die Spaltennamen assoziativ (Verbindung zur Vereinfachung) sind. Das spräche dafür, dass es eine feste Spaltenreihenfolge gibt und die Namen nur dafür da sind, um das ansprechen zu vereinfachen und nicht auf die genaue Position angewiesen zu sein.

      Wenn dem so ist und ich das richtig verstehe... dann spricht einiges dafür, dass es auch beim UPDATE, INSERT usw gehen müsste.

      LG Patrick

      1. Vielleicht habe ich was missverstanden ,
        aber wenn du die Indexspalte mit AUTO_I.. versehen hast (+primary key) sollte UPDATE ... WHERE index=n kein Problem sein. Die spalte kann beliebig genannt werden , wichtig wäre nur auto_increment.

        1. Ja, auto_increment ist gesetzt und auch das Update passiert natürlich anhand der id. Nur ich kenne halt nicht die passende Syntax und finde sie ledier auch nciht.

          $sql = "UPDATE Tabelle SET spaltea = 'bla', spalteb = (spalteb + 1)";

          Das wäre sinngemäß der sql-String. Nur muss ich halt spaltea und spalteb durch den Spaltenindex ersetzen, weil der name leider durch eine Schleife vorher unbekannt und nur der index bekannt ist.

          1. Ah..

            Dir wird wohl nichts übrig bleiben, als die Spaltennamen, solange noch bekannt, in ein Array zu packen und den SQL-String dann daraus zusammenzubasteln.
            Ich verstehe ohne Code allerdings nicht, warum Du nach einer Schleife nicht mehr die Namen, wohl aber die Indizes kennst.

            Grüße

            Das wäre sinngemäß der sql-String. Nur muss ich halt spaltea und spalteb durch den Spaltenindex ersetzen, weil der name leider durch eine Schleife vorher unbekannt und nur der index bekannt ist.

        2. Also, ich habe das so verstanden, dass er nicht den n-ten Datensatz, sondern die n-te Spalte der Tabelle updaten will, also sowas in der Art:

          UPDATE tabelle SET n-te_Spalte ...

          @Patrick: Warum kannst Du den Spaltennamen nur über den Index ansprechen?

          Grüße

          Vielleicht habe ich was missverstanden ,
          aber wenn du die Indexspalte mit AUTO_I.. versehen hast (+primary key) sollte UPDATE ... WHERE index=n kein Problem sein. Die spalte kann beliebig genannt werden , wichtig wäre nur auto_increment.

          1. Also...

            ich glaube, es ist simpler einfach das Script zu zeigen. Vielleicht hat ja auch jemand ne andere Idee...

            Die Tabelle für die Umfragen (max. 10 Anworten):

            // Die Tabelle
            /*
            CREATE TABLE Umfragen (
              id int(3) NOT NULL auto_increment,
              question text NOT NULL,
              answer1 varchar(255) NOT NULL default '',
              count1 int(7) NOT NULL default '0',
              answer2 varchar(255) NOT NULL default '',
              count2 int(7) NOT NULL default '0',
              answer3 varchar(255) NOT NULL default '',
              count3 int(7) NOT NULL default '0',
              answer4 varchar(255) NOT NULL default '',
              count4 int(7) NOT NULL default '0',
              answer5 varchar(255) NOT NULL default '',
              count5 int(7) NOT NULL default '0',
              answer6 varchar(255) NOT NULL default '',
              count6 int(7) NOT NULL default '0',
              answer7 varchar(255) NOT NULL default '',
              count7 int(7) NOT NULL default '0',
              answer8 varchar(255) NOT NULL default '',
              count8 int(7) NOT NULL default '0',
              answer9 varchar(255) NOT NULL default '',
              count9 int(7) NOT NULL default '0',
              answer10 varchar(255) NOT NULL default '',
              count10 int(7) NOT NULL default '0',
              begin varchar(10) NOT NULL default '',
              end varchar(10) NOT NULL default '',
              status tinyint(1) NOT NULL default '1',
              PRIMARY KEY  (id)
            ) TYPE=MyISAM;
            */

            <?php
            $counter = 0;

            $sql = "SELECT * FROM Umfragen WHERE begin <= '". strtotime("now") ."' && end > '". strtotime("now") ."' && status = '1' LIMIT 1";
            $query = mysql_query($sql);
            $row = mysql_fetch_array($query);

            print $row['question'];

            if (!empty($row['answer1'])) $counter++;
            if (!empty($row['answer2'])) $counter++;
            if (!empty($row['answer3'])) $counter++;
            if (!empty($row['answer4'])) $counter++;
            if (!empty($row['answer5'])) $counter++;
            if (!empty($row['answer6'])) $counter++;
            if (!empty($row['answer7'])) $counter++;
            if (!empty($row['answer8'])) $counter++;
            if (!empty($row['answer9'])) $counter++;
            if (!empty($row['answer10'])) $counter++;

            if ($_POST['vote_umfrage']) {
                print $_POST['hersteller'];
                $sql = "UPDATE Umfragen SET [". $_POST['hersteller'] ."] = ([". $_POST['hersteller'] ."] + 1) WHERE id = '". $_POST['umfrageid'] ."'";
                $query = mysql_query($sql);
            }
            ?>
            <form action="<?= $PHP_SELF; ?>" method="post">
              <input type="hidden" name="umfrageid" value="<?= $row['id']; ?>" />
              <ul class="umfrage">
                <?php
                // Inhalte anhand Index der Spalte ansprechen, jede zweite Spalte ist Antwort, beginnend bei Index 2
                for ($i = 2; $i < (($counter * 2) + 1); ($i = $i + 2)) {
                    print "<li><input type="radio" name="hersteller" value="". $i ."" /> ". $row[$i] ."</li>\n";
                }
                unset($i);
                unset($counter);
                ?>
              </ul>
              <div style="margin-top: 8px; text-align: right; margin-right: 6px;">
                <input type="image" src="/buttons/vote.gif" name="vote_umfrage" value="Login" />
              </div>
            </form>

            Hier habe ich durch die Schleife und vorher unbekannt Anzahl der Antworten keine andere Variante gefunden die Daten zu übertragen. Ich denke zu wissen, dass es auch die Möglichkeit gibt die Spalten answer1 im Ergebnis dann $row['answer1'] auszulesen, aber wie ich in dem Namen in einer Schleife die 1 da hochzählen kann, hab ich keine Ahnung...

            Alles nachvollziehbar oder hab ich nun noch mehr Verwirrung gestiftet?

            Gruß Patrick

            1. echo $begrüßung;

              Mal abgesehen von dem nicht gerade sehr glücklichen Datenbanklayout ...

              Ich denke zu wissen, dass es auch die Möglichkeit gibt die Spalten answer1 im Ergebnis dann $row['answer1'] auszulesen, aber wie ich in dem Namen in einer Schleife die 1 da hochzählen kann, hab ich keine Ahnung...

              SQL-Befehle sind Strings. Strings können auch durch Kombinieren von Text und Zahlen zusammengebaut werden.
              Beispiel: 'UPDATE tabelle SET feld' + $nummer + '="inhalt"'

              Vermutlich siehst du grade nur den Wald vor lauter Bäumen nicht. :-)

              echo "$verabschiedung $name";

            2. Hmm...

              wenn ich das jetzt richtig verstanden habe, kreuzen die
               Leute an und in Deinen $Post-Daten stehen die Nummern
               der Antworten, die sie angekreuzt haben. Nun willst Du
               für jedes $i die Spalte "count$i" hochzählen? Wie wäre
               es damit:

              $qs = "UPDATE Umfragen SET ";
              foreach( $_POST['hersteller'] as $key => $value ) {
                 if( $key > 0 ) {
                    $qs .= ", ";
                 }
                 $column = "count" . $value;
                 $qs .= $column . " = " $column . " + 1";
              }

              $qs .= <der Rest des Queries>;

              Hoffe, das hilft...

              Grüße

              if ($_POST['vote_umfrage']) {
                  print $_POST['hersteller'];
                  $sql = "UPDATE Umfragen SET [". $_POST['hersteller'] ."] = ([". $_POST['hersteller'] ."] + 1) WHERE id = '". $_POST['umfrageid'] ."'";
                  $query = mysql_query($sql);
              }
              ?>

            3. ...da fällt mir gerade noch ein:

              Hier tappst Du genau in die select-*-Falle, die Rouven
              Dir beschrieben hat:

              <?php
                  // Inhalte anhand Index der Spalte ansprechen, jede zweite Spalte ist Antwort, beginnend bei Index 2
                  for ($i = 2; $i < (($counter * 2) + 1); ($i = $i + 2)) {
                      print "<li><input type="radio" name="hersteller" value="". $i ."" /> ". $row[$i] ."</li>\n";
                  }

              Du kannst hier nicht wissen, ob die Reihenfolge der
              Felder im Result stimmt. Mag ja bis jetzt geklappt
              haben, aber verlassen kannst Du Dich darauf nicht.

              Besser wäre schon eine Schleife über $row, Abfrage, ob
              der key mit "answer" anfängt und der Wert nicht leer
              ist, dann Nummer mit substr aus dem key extrahieren und
               den Button-Wert auf "count" . $nummer setzen, dann
              hast Du die Feldnamen gleich in den $_POST-Daten :-)

              Ist das übrigens gewollt, dass Du irgendeine Umfrage
              (ohne Sortierung wohl die zuletzt eingetragene? ) aus
              der Datenbank liest? Kann es nur eine aktuelle geben?

              Nur mal so am Rande...

              <?php
              $counter = 0;

              $sql = "SELECT * FROM Umfragen WHERE begin <= '". strtotime("now") ."' && end > '". strtotime("now") ."' && status = '1' LIMIT 1";

              .
              .
              .

              <form action="<?= $PHP_SELF; ?>" method="post">
                <input type="hidden" name="umfrageid" value="<?= $row['id']; ?>" />

              Grüße

              1. Hallöchen nochmal...
                musste zwischendurch weg...

                Die genannte Falle hab ich schon gesehen gehabt... der Code war auch nur zur Verdeutlichung, des geschilderten Problems... Dass es nu anders werden muss ist klar.

                Besser wäre schon eine Schleife über $row, Abfrage, ob
                der key mit "answer" anfängt und der Wert nicht leer
                ist, dann Nummer mit substr aus dem key extrahieren und
                den Button-Wert auf "count" . $nummer setzen, dann
                hast Du die Feldnamen gleich in den $_POST-Daten :-)

                Ähm ja... aber eine Schleife bei einem einzigen Datensatz? und wie finde ich den namen des keys raus? den muss ich ja angeben um den Inhalt in der option darstellen zu können.?

                Ist das übrigens gewollt, dass Du irgendeine Umfrage
                (ohne Sortierung wohl die zuletzt eingetragene? ) aus
                der Datenbank liest? Kann es nur eine aktuelle geben?

                Jein, die Sortierung geht darüber, von wann bis wann eine Umfrage überhaupt angezeigt wird (begin, end). Da sitzt ein Timestamp drin, der Halt beginn und Ende definiert. Die Erstellung der Umfrage selbst passiert ja an ganz anderer Stelle.

                Hmmm... ich hab ztwar dazugelernt, aber schlauer bin ich immer noch net :-(

                LG Patrick

                1. Hi Patrick,

                  Ähm ja... aber eine Schleife bei einem einzigen Datensatz? und wie finde ich den namen des keys raus? den muss ich ja angeben um den Inhalt in der option darstellen zu können.?

                  Ja aber die Schleife hast Du doch sowieso, um das
                  Formular aufzubauen:

                  for ($i = 2; $i < (($counter * 2) + 1); ($i = $i + 2)) {
                          print "<li><input type="radio" name="hersteller" value="". $i ."" /> ". $row[$i] ."</li>\n";
                      }

                  Genau das sollst Du mit einer foreach-Schleife über $row machen:

                  foreach( $row as $key => $value ) {
                     if( substr( $key, 0, 6 ) == 'answer' && !empty( $value ) ) {
                        $number = substr( $key, 6 );
                        print "<li><input type="radio" name="hersteller" value="counter". $number ."" /> ". $row[$key] ."</li>\n";
                     }
                  }

                  Damit kannst Du diesen Sermon:

                  [Schnipp]

                  if (!empty($row['answer1'])) $counter++;
                  if (!empty($row['answer2'])) $counter++;
                  if (!empty($row['answer3'])) $counter++;
                  if (!empty($row['answer4'])) $counter++;
                  if (!empty($row['answer5'])) $counter++;
                  if (!empty($row['answer6'])) $counter++;
                  if (!empty($row['answer7'])) $counter++;
                  if (!empty($row['answer8'])) $counter++;
                  if (!empty($row['answer9'])) $counter++;
                  if (!empty($row['answer10'])) $counter++;

                  [Schnapp]

                  weglassen.

                  Und bitte vorher dem mysql_fetch_array ein MYSQL_ASSOC
                  (Konstante) im 2. Parameter mitgeben, der Standardwert
                  ist MYSQL_BOTH, das heisst jedes Feld steht da doppelt
                   drin, einmal numerisch indiziert, und einmal über den
                  Feldnamen.

                  Grüße

      2. Hi,

        du vermischt hier zwei völlig unterschiedliche Ebenen. PHP ist es egal was du für eine Abfrage gemacht hast, was PHP aus der Datenbank bekommt sind Spalten mit einem bestimmten Namen in einer bestimmten Reihenfolge. Ob du in PHP mittels Spaltennummer oder -name darauf zugreifst, ist vollkommen irrelevant.
        Auf der Ebene der Datenbank allerdings bietet sich ein völlig anderes Bild:
        Nehmen wir mal eine Tabelle name|vorname|alter

        SELECT name, vorname, alter ...
        gibt immer diese 3 Spalten in dieser Reihenfolge raus.

        SELECT *
        kann (und wird in aller Regel) ebenfalls name,vorname,alter liefern, es steht allerdings nirgendwo geschrieben, dass es das tun muss. Wenn es der Datenbank passt kann sie auch alter,vorname,name liefern, sie hat genauso richtig gearbeitet.

        Bei einem PHP-Zugriff bliebe nun zwar der Zugriff über die Spaltennamen weiterhin in Takt, der Zugriff über die Nummern wäre allerdings über den Haufen geworfen - es gäbe keinen Fehler, nur die Felder wären eben in der anderen Reihenfolge.

        Und eben auf genau jener Datenbankebene wird dir von der Nutzung von SELECT * abgeraten, und aus genau dem selben Grund vermute ich auch, dass es keinerlei Unterstützung für Insert/Update auf Spalten-Nummer-Basis gibt - schlichtweg weil die Spaltenreihenfolge modellgemäß irrelevant ist.
        Gleiches gilt ja für die Reihenfolge der Datensätze, du kannst ja nicht sagen du möchtest den 3. Datensatz updaten, weil es keinen dritten gibt. Die Sortierung entsteht erst über eine entsprechende Abfrage.

        MfG
        Rouven

        --
        -------------------
        Inter Arma Enim Silent Leges  --  Cicero
        1. Hi Rouven,
          danke für die ausführlich Antwort. diese ist zwar alles andere als befriedigend und stellt mich vor ein ziemliches Problem, aber nungut. Es wird sich schon eine Lösung finden.
          Nochmals Danke.

          Gruß Patrick

          1. Hi,

            nun ja, das Problem lässt sich aber sicherlich umgehen. Führe doch z.B. in einem Skript ein Array ein in dem du die Zuordnung hälst, also nummer->Spaltenname. Den so ermittelten Wert kannst ud dann innerhalb deines SQL-Statements als Variable mitverfüttern.

            MfG
            Rouven

            --
            -------------------
            When the only tool you've got is a hammer, all problems start to look like nails.
            1. Nochmal hi...

              Also ich hab grad den kompletten Quellcode mal unter "Karin" gepostet in der Hoffnung, dass einem oder dir da mehr zu einfällt.

              Es gibt mit Sicherheit eine Lösung, nur weiß ich mit meinem bisherigen Wissen nicht wie. Ein Array mit dem Bezug zum index hab ich php-intern und wollte das auch zum Hochzählen des Counters nutzen, aber das wird ja so nix.

              Wäre nett, wenn du mal einen Blick drauf werfen könntest.

        2. Hi,

          SELECT name, vorname, alter ...
          gibt immer diese 3 Spalten in dieser Reihenfolge raus.

          Nein, einen Syntax-Fehler ;-)
          Weil alter ein reserviertes Keyword ist (alter table ...)

          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.