Ankündigung

Einklappen
Keine Ankündigung bisher.

Datenbank Spalten Typ und SQL Statement Type?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Datenbank Spalten Typ und SQL Statement Type?

    Kann mir einer den Unterschied zwischen Datenbank Spalten Typ und SQL Statement Type erklären? Am besten ganz von vorne, weil mir da einiges schleierhaft vorkommt.

    Wieso liefern SQL Abfragen immer nur Strings, selbst wenn in der Datenbank der Typ int() oder double() angegeben ist?

    Ich habe eine table column von varchar() zu double() umgewandelt, per PHP. Vorher hatte ich den Typ der column auf double(8,5) umgestellt. Beim SQL UPDATE habe ich doubleval() verwendet.

    Da bei SQL SELECT immer nur ein String geliefert wird [warum, das wüßte ich gern], habe ich auf CAST() erweitert. Das ist ein Thema für sich, weil, da gibt es unzählige Anleitungen, die irgendwie nichtssagend sind und nicht funktionieren. Am unnützesten sind die, bei denen Zahlen anstatt columnnames verwendet werden, like CAST('123.9383' as double(8,5)). Die Zahl gegen columnname austauschen funktioniert nicht, sondern es funktioniert nur mit einem weiteren AS: CAST(column as double(8,5)) AS column, zumindest bei mir. Der Witz an der ganze Sache ist, es bleibt beim String...

    Code:
    array(3) {
      ["id"]=>
      string(1) "1"
      ["gpslat"]=>
      string(8) "49.36578"
      ["gpslon"]=>
      string(8) "11.95247"
    }
    Wer kann mir das erklären? Ist das ähnlich wie bei $_POST; wo auch immer nur ein String empfangen wird. Wobei, das stimmt nicht ganz. Die Keys bei einem $_POST als array sind integer. Das liegt wohl an der unsichtbaren Verarbeitung nach Empfang durch PHP.

  • #2
    Da bei SQL SELECT immer nur ein String geliefert wird [warum, das wüßte ich gern]
    Das liegt an der Bibliothek, die du für die Datenbankkommunikation verwendest (z.B. mysqlnd), und welche Optionen du verwendest. Bei PDO weiß ich, dass im emulated mode nur strings/null geliefert wird, im non-emulated mode bekommst du auch Integers. Floats werden nie geliefert, wahrscheinlich wegen der Float-Arithmetik (unterschiedliche Implementierung der Datentypen in PHP/Datenbank) oder weil (die meisten) Datenbanken keinen Float-Typ haben.

    Das liegt wohl an der unsichtbaren Verarbeitung nach Empfang durch PHP.
    Richtig, wie bei arrays beschrieben, werden numerische keys in integer umgewandelt.

    Kommentar


    • #3
      Weil Datenbank und PHP unterschiedliche Datentypen haben, sodass diese nicht 1:1 konvertierbar sind. Deshalb liegt es am Programmierer, in welchen Datentyp er die Werte konvertieren möchte.

      Hinzu kommt noch, dass selbst in PHP die Datentypen sich von Server zu Server unterscheiden können. Ein Integer ist auf 32-Bit Systemen ein Int32 und auf 64-Bit Systemen ein Int64. Wenn ein Int64-Wert aus der Datenbank auf einem 32-Bit System in einen Integer konvertiert werden würde, hätte man einen Überlauf und kaputte Daten. Mal davon abgesehen, dass PHP nicht mal Unsigned-Integers unterstützt.

      Auch die Float-Genauigkeit kann sich je nach Server unterscheiden. Und Decimal-Werte unterstützt PHP sowieso nicht.

      Strings sind einfach die sicherste Variante zur Übertragung von Werten. Zumindest in PHP, das so unklar definierte Datentypen hat.

      Hier ein Beispiel mit einem Unsigned 64-Bit Integer:
      PHP-Code:
      $db = new PDO('mysql:host=localhost;dbname=test;charset=utf8''root''', [
          
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          
      PDO::ATTR_EMULATE_PREPARES => false
      ]);

      $db->query("
          CREATE TEMPORARY TABLE `test` (
              `value` BIGINT UNSIGNED NOT NULL
          )
      "
      );

      $db->query("
          INSERT INTO `test` (`value`)
          VALUES (10000000000000000000)
      "
      );

      $value $db->query("SELECT `value` FROM `test`")->fetch(PDO::FETCH_COLUMN);

      var_dump($value);
      // string(20) "10000000000000000000"

      var_dump((int)$value);
      // int(9223372036854775807) 

      Kommentar


      • #4
        Man kann die Werte immer als String übertragen. Das DBMS konvertiert dann in den richtigen Typ.

        Man sieht das bei bind, siehe Beispiel im Handbuch, da wird vorab der Wert auf Typ verglichen.
        PHP-Code:
        $calories 150;
        $colour 'red';
        $sth $dbh->prepare('SELECT name, colour, calories
            FROM fruit
            WHERE calories < :calories AND colour = :colour'
        );
        $sth->bindValue(':calories'$caloriesPDO::PARAM_INT);
        $sth->bindValue(':colour'$colourPDO::PARAM_STR);
        $sth->execute(); 
        Lässt man das weg und nimmt ein Array im Execute, dann sind die Werte automatisch immer Strings.
        PHP-Code:
        $sth $dbh->prepare('SELECT name, colour, calories
            FROM fruit
            WHERE calories < :calories AND colour = :colour'
        );

        $sth->execute(array(:calories 150,:colour 'red')); 
        Sicher gegen SQL injection ist Beides.

        Kommentar


        • #5
          @protexis, kommt bei deinem letzten array im execute kein Warning: Use of undefined constant :calories? Oder machst du das so wie in der PHP Doc mit hardcoded Values? Mich verwirrt das jedesmal, weil es ist nicht das Gleiche.

          Die Umstellung von varchar auf double lief mit EMULATED true, bzw. default, weil zu dieser Zeit wusste ich noch nichts davon, dass man das falsen muss, um in den wahren Genuss von PDO Preparet Statements zu kommen, mit dem separaten Senden der Daten. Dann hätte ich mir wohl das doubleval($varchar) im sql querystring sparen können.

          Kommentar


          • #6
            Zitat von psoido Beitrag anzeigen
            @protexis, kommt bei deinem letzten array im execute kein Warning: Use of undefined constant :calories? Oder machst du das so wie in der PHP Doc mit hardcoded Values? Mich verwirrt das jedesmal, weil es ist nicht das Gleiche.
            Er hat sich vertippt und die Hochkommas vergessen. Kann vorkommen und sieht jeder sofort, der auch nur eine Sekunde mitdenkt.

            Kommentar


            • #7
              Es ist ja nicht so, dass es die Variante OHNE Singlequote nicht gäbe:
              PHP-Code:
              $stmt $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); 
              https://www.php.net/manual/de/pdo.pr...statements.php
              Es kommt halt dann doch immer auf die eigenen Interessen an seine Antworten zu formulieren und damit etwas zu transportieren. Es kommt zwar an, hat allerdings keinerlei der vom Sender gewünschten Wirkungen, zumindest nicht in dem Ton. Aber danke für den netten Hinweis.

              Kommentar


              • #8
                Zitat von psoido Beitrag anzeigen
                Es ist ja nicht so, dass es die Variante OHNE Singlequote nicht gäbe:
                PHP-Code:
                $stmt $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); 
                Das sieht man ja aus dem Kontext heraus, ob das so Sinn ergibt oder ob sich jemand vertippt hat.

                Kommentar

                Lädt...
                X