Tom: MySQL >=5.1 und automatischer Timestamp bei Insert

Hello,

ich hänge mal wieder.

Habe ich das richtig im Gedächtnis, dass ich für die automatische Spaltenführung beim Insert für die Eintragungszeit den Spaltentyp "Timestamp" benutzen muss? Die AUtomatic funktioniert dann nur in der ersten Spalte mit dem Typ?

Geht das auch irgendwie mit dem Spaltentyp "Datetime", ohne jetzt ins Statement "now()" oder ähnliches einsetzen zu müssen und ohne Trigger?

Ich will auch die Möglichkeit behalten, den Timestamp gezielt setzen zu können.

Und wenn ich dann mal einen Timestamp gezielt setzen will, muss ich den vorher mit from_unixtime($unixtimestamp) ins passende Format bringen lassen?

Liebe Grüße aus dem schönen Oberharz

Tom vom Berg

--
 ☻_
/▌
/ \ Nur selber lernen macht schlau
http://bergpost.annerschbarrich.de
  1. Hello,

    gleich noch eine weitere Frage im Nachtrag. Es geht dann schlussendlich darum

    • welche Spaltentypen quotierte Daten zwingend erforderlich machen
    • welche Spaltentypen quotierte Daten zulassen, aber auch ohne arbeiten
    • welche Spaltentypen keine quotierten Daten zulassen

    bzw. in welchem Zusammenhang die Daten quotiert werden müssen, quotiert werden dürfen oder NICHT quotiert werden dürfen.

    * numerische Typen
    * Stringtypen
    ** Aufzählungstypen
    * Datumstypen
    * Binäre Typen

    ~ Strings
    Zahlen
    Daten
    Aufzählungen
    Logische Werte TRUE, FALSE, NULL

    usw.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Hallo,

      gleich noch eine weitere Frage im Nachtrag. Es geht dann schlussendlich darum

      • welche Spaltentypen quotierte Daten zwingend erforderlich machen
      • welche Spaltentypen quotierte Daten zulassen, aber auch ohne arbeiten
      • welche Spaltentypen keine quotierten Daten zulassen

      das ist ziemlich irrelevant, wenn man hübsch mit Prepared Statements arbeitet.

      siehe Handbuch
      http://dev.mysql.com/doc/refman/5.1/en/literals.html

      Freundliche Grüße

      Vinzenz

      1. Hello Vinzenz,

        gleich noch eine weitere Frage im Nachtrag. Es geht dann schlussendlich darum

        • welche Spaltentypen quotierte Daten zwingend erforderlich machen
        • welche Spaltentypen quotierte Daten zulassen, aber auch ohne arbeiten
        • welche Spaltentypen keine quotierten Daten zulassen

        das ist ziemlich irrelevant, wenn man hübsch mit Prepared Statements arbeitet.

        Das sollte an dieser Stelle nicht geschehen, aber danke für den Hinweis.
        Für die Historie wird nachher das komplett fertiggestellte SQL-Query abgespeichert. Da wüsste ich jetzt nicht, wie ich das mit prepared Statements hinbekommen könnte.

        siehe Handbuch
        http://dev.mysql.com/doc/refman/5.1/en/literals.html

        im Handbuch lese ich dauernd :-O

        Aber es ist mir leider immer noch nicht ganz klar, welche Spaltentypen nun quoted werden MÜSSEN.
        Hier mal die Funktionsgruppe, aus der mein Anliegen hervorgeht. Die dritte Funktion ist die wesentliche. Ich befürchte, bei Binary, Blob & Co. habe ich es falsch gemacht?

        Es fehlt da noch diverse Dinge; hier geht es jetzt erstmal nur um das Quoting.

        #-----------------------------------------------------------------------------------
        function db_get_column_info($con, $tablename)
        {

        $sql = "select column\_name, data\_type
                    from information\_schema.COLUMNS
                    where table\_name = '$tablename'";

        if ($res = mysqli_query($con, $sql))
            {
                $_list = array();

        while($_colinfo = mysqli_fetch_assoc($res))
                {
                    $_list[$_colinfo['column_name']] = $_colinfo['data_type'];
                }

        # lower the key names and return them
                return array_change_key_case ($_list);
            }

        return false;

        }
        #-----------------------------------------------------------------------------------
        function db_escape_values($con, $_data)
        {
            if(!is_array($_data)) { return false; }

        foreach($_data as $key => $value)
            {
                $_data[$key] = mysqli_real_escape_string($con, $value);
            }

        return $_data;
        }
        #-----------------------------------------------------------------------------------
        function db_quote_values($con, $tablename, $_escaped_data)
        {
            if (!$_typeinfo = db_get_column_info($con, $tablename)) { return false; }
            if (!is_array($_escaped_data)) {return false; }

        $_escaped_data = array_change_key_case ($_escaped_data);

        foreach($_escaped_data as $key => $data)
            {
                if (!isset($_typeinfo[$key])) { return false; }

        switch ($_typeinfo[$key])
                {
                    case 'tinyint':
                    case 'smallint':
                    case 'mediumint':
                    case 'int':
                    case 'bigint':
                    case 'bit':

        # no quoting

        break;

        case 'float':
                    case 'double':
                    case 'decimal':

        # no quoting

        break;

        case 'char':
                    case 'varchar':
                    case 'tinytext':
                    case 'text':
                    case 'mediumtext':
                    case 'longtext':

        # qoute it!
                        $_escaped_data[$key] = "'$data'";

        break;

        case 'binary':
                    case 'varbinary':
                    case 'tinyblob':
                    case 'blob':
                    case 'mediumblob':
                    case 'longblob':

        # no quoting

        break;

        case 'date':
                    case 'time':
                    case 'year':
                    case 'datetime':

        $_escaped_data[$key] = "'$data'";

        break;

        case 'timestamp':

        $_escaped_data[$key] = "from_unixtime($_escaped_data[$key])";

        break;

        case 'enum':
                    case 'set':

        $_escaped_data[$key] = "'$data'";

        break;

        default:

        ## Datatype not recognized
                        return false;
                }
            }

        return $_escaped_data;
        }
        #-----------------------------------------------------------------------------------

        Wäre nett, wenn Du deinen Kommentar mal in die dritte Funktion schreiben könntest.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hallo Tom,

          Das sollte an dieser Stelle nicht geschehen, aber danke für den Hinweis.

          irgendwie habe ich das Gefühl, dass Du ein Rad wiedererfinden willst :-(

          Es fehlt da noch diverse Dinge; hier geht es jetzt erstmal nur um das Quoting.

          » function db_get_column_info($con, $tablename)  
          
          > {  
          >   
          >     $sql = "select `column_name`, `data_type`  
          >             from `information_schema`.`COLUMNS`  
          >             where `table_name` = '$tablename'";  
          
          

          ein nicht gequoteter Tabellenname. Das kann schief gehen.
          Selbstverständlich musst Du den Tabellennamen quoten. Und zwar hier mit mysqli_real_escape_string.

          Besser: Verwende wenigstens hier ein Prepared Statement!
                  Schreibe SQL-Schlüsselwörter groß, das erhöht (für mich)
                  die Lesbarkeit.
          [...]

          Hast Du an eine Funktion

          function db_escape_schema_object_names()  
          
          

          gedacht?

          function db_escape_values($con, $_data)
          function db_quote_values($con, $tablename, $_escaped_data)

          case 'binary':
                      case 'varbinary':
                      case 'tinyblob':
                      case 'blob':
                      case 'mediumblob':
                      case 'longblob':

          # no quoting

          Wenn Du den Kram in eine SQL-Zeichenkette bringst, dann musst Du das selbstverständlich

          a) in einfache Anführungszeichen packen
          b) entsprechend quoten

          und

          c) daran denken, dass Du die max_packet_size überschreiten könntest.

          Abschließende Frage:
          Nur weil der Datentyp einer Spalte anders definiert ist, schließt das nicht die Möglichkeit aus, dass jemand anderes böswillig oder versehentlich Daten eines anderen Datentyps versucht einzugeben. Mache Dir bitte klar, wie das resultierende SQL-Statement aussehen *kann*.

          Freundliche Grüße

          Vinzenz

          1. Hello Vinzenz,

            Wenn Du den Kram in eine SQL-Zeichenkette bringst, dann musst Du das selbstverständlich

            a) in einfache Anführungszeichen packen
            b) entsprechend quoten

            Nur weil der Datentyp einer Spalte anders definiert ist, schließt das nicht die Möglichkeit aus, dass jemand anderes böswillig oder versehentlich Daten eines anderen Datentyps versucht einzugeben. Mache Dir bitte klar, wie das resultierende SQL-Statement aussehen *kann*.

            Ja, nee is klar :-(
            Falscher Ansatz. -> Tonne

            Irgendwie ging da was durcheinander.

            Eigentlich wollte ich doch das Eingabeformular mit der Tabellendefinition abgleichen, also solche Dinge, wie NULL, FALSE, TRUE usw. "übersetzen" für den SQL-String und fürs HTML.

            Ich mach mal Pause jetzt.

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
    2. Tach!

      • welche Spaltentypen quotierte Daten zwingend erforderlich machen
      • welche Spaltentypen quotierte Daten zulassen, aber auch ohne arbeiten
      • welche Spaltentypen keine quotierten Daten zulassen

      Die Spaltentypen sind hierbei unerheblich. Was zählt ist die Literalschreibweise des Wertes. Eine String-Spalte kann auch Zahlenwerte übergeben bekommen, ebenso wie ein NULL oder 0x546f6d. Was letztlich in der Spalte ankommt ist eine Frage des Parsers und der Typumwandlung.

      dedlfix.

      1. Hello Dedlfix,

        Die Spaltentypen sind hierbei unerheblich. Was zählt ist die Literalschreibweise des Wertes. Eine String-Spalte kann auch Zahlenwerte übergeben bekommen, ebenso wie ein NULL oder 0x546f6d. Was letztlich in der Spalte ankommt ist eine Frage des Parsers und der Typumwandlung.

        Ein NULL kommt aber nicht in der Tabelle an, wenn ich im SQL-String vorher 'NULL' daraus mache.

        Darum ging es mir eigentlich. Ich hatte mich dann nur verlaufen...
        Copy 'n Paste funktionierte gerade so schön *ohoh*

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hallo Tom,

          Ein NULL kommt aber nicht in der Tabelle an, wenn ich im SQL-String vorher 'NULL' daraus mache.

          Darum ging es mir eigentlich.

          wozu ich Dir das passende Handbuchkapitel verlinkt hatte :-)

          Die Frage, die Du Dir stellen musst, ist wie Du

          NULL  und 'NULL'
          TRUE  und 'TRUE'
          FALSE und 'FALSE'

          unterscheidest - und ob Du das überhaupt musst :-)
          Das hängt vom Gesamtkonzept ab, das bei Dir sehr generisch aussieht.

          Freundliche Grüße

          Vinzenz

          1. Tach!

            Die Frage, die Du Dir stellen musst, ist wie Du
            NULL  und 'NULL'
            TRUE  und 'TRUE'
            FALSE und 'FALSE'
            unterscheidest - und ob Du das überhaupt musst :-)

            Die nächste Anforderung wäre dann, dass eine Funktion ausgeführt werden muss (z.B. FROM_UNIXTIME()). Die muss ebenfalls ohne Stringbehandlung durchgereicht werden. Allerdings müssen eventuelle Parameter berücksichtigt werden.

            dedlfix.

            1. Hallo,

              Die nächste Anforderung wäre dann, dass eine Funktion ausgeführt werden muss (z.B. FROM_UNIXTIME()). Die muss ebenfalls ohne Stringbehandlung durchgereicht werden. Allerdings müssen eventuelle Parameter berücksichtigt werden.

              es soll ja keinen Spaß machen :-)
              Für meine eigenen Projekte fällt sowas unter YAGNI. Ich griffe eher zu einem Abstraktionslayer wie Doctrine.

              Freundliche Grüße

              Vinzenz

            2. Hello,

              Die nächste Anforderung wäre dann, dass eine Funktion ausgeführt werden muss (z.B. FROM_UNIXTIME()). Die muss ebenfalls ohne Stringbehandlung durchgereicht werden. Allerdings müssen eventuelle Parameter berücksichtigt werden.

              Stimmt.

              Die passt jetzt aber auch in das "Override-Array".

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
          2. Hello,

            Die Frage, die Du Dir stellen musst, ist wie Du

            NULL  und 'NULL'
            TRUE  und 'TRUE'
            FALSE und 'FALSE'

            unterscheidest - und ob Du das überhaupt musst :-)

            Das passiert jetzt mittels "Override"-Argument in der Funktion, die die Daten in das SQL-Statement
            einfügt. Und Override darf niemals nie mit Daten von fremden Quellen gefüllt werdenm sondern nur mit brechneten ais dem Script :-O

            Maskiert und quotiert wird prophilaktisch jetzt immer erstmal.

            Die Werte NULL, TRUE und FALSE müssen aus dem Formular -> Statement sowieso erst übersetzt werden.

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
  2. Hallo,

    Habe ich das richtig im Gedächtnis, dass ich für die automatische Spaltenführung beim Insert für die Eintragungszeit den Spaltentyp "Timestamp" benutzen muss? Die AUtomatic funktioniert dann nur in der ersten Spalte mit dem Typ?

    siehe Handbuch:
    http://dev.mysql.com/doc/refman/5.1/en/timestamp-initialization.html

    Geht das auch irgendwie mit dem Spaltentyp "Datetime", ohne jetzt ins Statement "now()" oder ähnliches einsetzen zu müssen und ohne Trigger?

    Nein.

    Ich will auch die Möglichkeit behalten, den Timestamp gezielt setzen zu können.

    kannst Du, siehe verlinkte Handbuchseite.

    Freundliche Grüße

    Vinzenz