Ergebnis 1 bis 21 von 21

Thema: Datenbankabfrage -> Too few arguments to build the query string

  1. #1
    Contao-Nutzer
    Registriert seit
    07.08.2011.
    Beiträge
    110

    Standard Datenbankabfrage -> Too few arguments to build the query string

    Hallo zusammen,

    ich bekomme bei der DB Abfrage folgende Meldung: Too few arguments to build the query string.

    Ich habe bereits versucht die WHERE Bedingung in den execute() Aufruf auszulagern aber das brachte auch keine Lösung.

    Statement lautet: SELECT title FROM titles WHERE user = 1 AND FROM_UNIXTIME( created, "%Y") = 2012 AND FROM_UNIXTIME( created, "%m") = 11 AND FROM_UNIXTIME( created, "%d") = 18

    Kann mir jemand helfen?

  2. #2
    Contao-Urgestein Avatar von Toflar
    Registriert seit
    15.06.2009.
    Beiträge
    4.467
    Partner-ID
    8667
    User beschenken
    Wunschliste

    Standard

    Das geht nicht, weil die Funktionen intern "sprintf()" aufruft und Du "%" im Query verwendest. Also entweder musst Du die maskieren, oder ->query() aufrufen, was den Query direkt an die DB weiterleitet.
    Geändert von Toflar (20.11.2012 um 07:27 Uhr)
    Contao Core-Entwickler @terminal42 gmbh
    Wir sind Contao Premium-Partner!
    Für Individuallösungen kannst du uns gerne kontaktieren.
    PS: Heute schon getrakked?

  3. #3
    Contao-Nutzer
    Registriert seit
    07.08.2011.
    Beiträge
    110

    Standard

    ahh okay.. dann weiß ich ja jetzt bescheid.

    Danke

  4. #4
    HeikoH
    Gast

    Standard

    Hallo zusammen,

    ich erhalte zur Zeit die gleiche Fehlermeldung.

    In einem Formular kann der Anwender mehrere Suchbegriffe eingeben.
    Die einzelnen Suchbegriffe werden dann anhand des Leerzeichens gesplittet und dann wird der SQL-String zusammengebaut.

    Der Code kann dann folgendermaßen aussehen:

    PHP-Code:
    $SQLSelect="SELECT DISTINCT link.id_link, l_name, l_video, l_ziel FROM link INNER JOIN zt_kategorie_link 
    ON zt_kategorie_link.id_link=link.id_link WHERE link.id_benutzer = ? AND 
    (( l_ziel LIKE '%begriff1%' AND  l_ziel LIKE '%begriff2%') OR 
    ( l_beschreibung LIKE '%begriff1%' AND  l_beschreibung LIKE '%begriff2%') OR 
    ( l_name LIKE '%begriff1%' AND  l_name LIKE '%begriff2%' )) AND l_video=1 
    ORDER by l_name"
    ;

    $obj=$this->Database->prepare($SQLSelect)                            
           ->
    execute($id_benutzer); 
    Das quittiert Contao dann mit der o.a. Fehlermeldung.
    Wenn ich 1 Suchbegriff eingebe, dann funktioniert es.

    Bei der Ausführung im phpmyAdmin liefert er mir immer das korrekte Ergebnis.

    Wie kann man dieses Problem beheben.

    Schöne Grüße


    Heiko

  5. #5
    Wandelndes Contao-Lexikon Avatar von BugBuster
    Registriert seit
    15.06.2009.
    Ort
    Berlin
    Beiträge
    10.512
    User beschenken
    Wunschliste

    Standard SQL Like Abfrage in doppelten Prozentzeichen

    Grüße, BugBuster
    "view source" is your guide.
    Danke an alle Amazon Wunschlisten Erfüller

  6. #6
    HeikoH
    Gast

    Standard

    Hallo,

    danke für die Antwort.
    Diesen Weg bin ich auch schon gegangen.
    Ich weiss nur nicht wie ich das so implementieren kann, da die Anzahl ja je nach Eingabe der Suchbegriffe stark variieren kann.

    Ich hatte es jetzt mal auf folgendem Weg ausprobiert

    PHP-Code:
    for ($i=0;$i COUNT($myArray);$i++)
    {                            
         
    $arr[]="'%".$myArray[$i]."%'";                        
    }  

    $SQLSelect="SELECT DISTINCT link.id_link, l_name, l_video, l_ziel FROM link INNER JOIN zt_kategorie_link ON 
    zt_kategorie_link.id_link=link.id_link WHERE link.id_benutzer = ? AND (( l_ziel LIKE ? AND  l_ziel LIKE ?) OR 
    ( l_beschreibung LIKE ? AND  l_beschreibung LIKE ?) OR ( l_name LIKE ? AND  l_name LIKE ? )) AND l_video=1 
    ORDER by l_name"
    ;

    $obj=$this->Database->prepare($SQLSelect)                            
         ->
    execute($id_benutzer,implode(",",$arr));

    /*
    Der Inhalt des Arrays (Ausgabe nach dem implode) würde folgendermaßen aussehen
    '%begriff1%','%begriff2%','%begriff1%','%begriff2%','%begriff1%','%begriff2%'
    */ 
    Das hat auch nicht funktioniert, da kommt die gleiche Fehlermeldung.


    Gruß Heiko

  7. #7
    Wandelndes Contao-Lexikon Avatar von BugBuster
    Registriert seit
    15.06.2009.
    Ort
    Berlin
    Beiträge
    10.512
    User beschenken
    Wunschliste

    Standard

    Da wird doch bestimmt auch die SQL Anweisung ausgegeben bei der Fehlermeldung, oder?
    Ich vermute da was, dass das Ergebnis von Implode als ein Parameter übergeben wird und nicht als 6 wie gewünscht.
    Grüße, BugBuster
    "view source" is your guide.
    Danke an alle Amazon Wunschlisten Erfüller

  8. #8
    Contao-Urgestein Avatar von fiedsch
    Registriert seit
    09.07.2009.
    Ort
    München
    Beiträge
    2.943

    Standard Datenbankabfrage -> Too few arguments to build the query string

    Zitat Zitat von HeikoH Beitrag anzeigen
    PHP-Code:
    $obj=$this->Database->prepare($SQLSelect)                            
         ->
    execute($id_benutzer,implode(",",$arr));

    /*
    Der Inhalt des Arrays (Ausgabe nach dem implode) würde folgendermaßen aussehen
    '%begriff1%','%begriff2%','%begriff1%','%begriff2%','%begriff1%','%begriff2%'
    */ 
    Das implode ergibt aber nur einen Parameter (einen String, der eine kommaseparierte Liste enthält). Ich denkeDu brauchst

    array_unshift($id_benutzer,$arr);

    und dann

    ->execute($arr);
    Contao-Community-Treff Bayern: http://www.contao-bayern.de

  9. #9
    HeikoH
    Gast

    Standard

    Super, es funktioniert .

    Von dem Statement wurden nur die ersten Zeichen angezeigt. Aber Ihr hattet Recht, er hat das als ein Parameter gesehen. Am Anfang wurden 2 Hockommas gesetzt.

    Folgendes hat dann die Lösung gebracht:

    PHP-Code:

    array_unshift
    ($arr,$id_benutzer);

    $obj=$this->Database->prepare($SQLSelect)                            
               ->
    execute($arr); 
    Vielen Dank für Eure Hilfe.

    Schöne Grüße und einen guten Rutsch in das Jahr 2013.


    Heiko

  10. #10
    Contao-Fan Avatar von Stranger
    Registriert seit
    20.06.2009.
    Ort
    Blankenburg
    Beiträge
    746
    Partner-ID
    5635
    User beschenken
    Wunschliste

    Standard

    Hallo,

    kriegt man das Problem auch gelöst, wenn man ohne prepare arbeitet?

    Ich will einfach nur folgendes machen:

    $this->Database->execute("SELECT * FROM tl_tabelle t1 WHERE t1.title LIKE '%".$varKeyword."%' OR t1.teaser LIKE '%".$varKeyword."%' OR t1.text LIKE '%".$varKeyword."%'");

    Aber jedes mal kommt dieser dumme Fehler

    Fatal error: Uncaught exception Exception with message Too few arguments to build the query string thrown in system/modules/core/library/Contao/Database/Statement.php on line 316
    Du willst dich bei mir bedanken?
    Ich freue mich über Geschenke von meiner Amazon-Wunschliste.

    Contao-Anwender seit 2008
    Contao-Entwickler seit 2013, mehr als 50 Contao Erweiterungen programmiert

    Mein Unternehmen aus Blankenburg (Harz): Fast & Media

  11. #11
    Wandelndes Contao-Lexikon Avatar von BugBuster
    Registriert seit
    15.06.2009.
    Ort
    Berlin
    Beiträge
    10.512
    User beschenken
    Wunschliste

    Standard SQL Like Abfrage in doppelten Prozentzeichen

    nein, das geht nicht ohne prepare, siehe den Grund hier:
    SQL_Like_Abfrage_in_doppelten_Prozentzeichen
    Grüße, BugBuster
    "view source" is your guide.
    Danke an alle Amazon Wunschlisten Erfüller

  12. #12
    Contao-Urgestein Avatar von Andreas
    Registriert seit
    19.06.2009.
    Ort
    Mönchengladbach
    Beiträge
    7.703
    User beschenken
    Wunschliste
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Zitat Zitat von Toflar Beitrag anzeigen
    Das geht nicht, weil die Funktionen intern "sprintf()" aufruft und Du "%" im Query verwendest. Also entweder musst Du die maskieren, oder ->query() aufrufen, was den Query direkt an die DB weiterleitet.
    Das Maskieren geht, indem man doppelte Prozentzeichen benutzt.
    PHP-Code:
    ... LIKE '%%foo%%' ... 
    Habe das gerade benötigt für das Feld Bedingung im Auflistungsmodul.
    Bitte!
    Vor Anfragen im Forum HTML validieren.
    Codesnippets hier im Froum sauber einrücken. Nur Tabs o. nur Leerzeichen verwenden.

    Vielen Dank an alle Wunschlistenerfüller
    Andreas Burg, Web Solutions

  13. #13
    Maintainer Avatar von xtra
    Registriert seit
    02.07.2009.
    Ort
    Tuebingen
    Beiträge
    2.007
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von Andreas Beitrag anzeigen
    Das Maskieren geht, indem man doppelte Prozentzeichen benutzt.

    Das kann man schon so machen... oeffnet sich damit jedoch dann bei einem Beispiel wie von Stranger oben fyr SQL injections sofern die Variable vom Client kommt.

    Es bleibt also dabei, man sollte immer mit prepared statements arbeiten und parameter verwenden.
    Bedenke stets: Wenn Du ungenaue oder unzureichende Angaben machst, so koennte dies die Bearbeitung deiner Frage endlos verzoegern (oder sogar dazu fyhren, dass ich zu viel nachdenken muss und die Antwort vergesse!). Kein Support per PN.

  14. #14
    Contao-Urgestein Avatar von Andreas
    Registriert seit
    19.06.2009.
    Ort
    Mönchengladbach
    Beiträge
    7.703
    User beschenken
    Wunschliste
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Das Auflistungsmodul hat leider keinen HOOK. Ich habe deshalb den Umstand ausgenutzt, dass man im Feld Bedingung eine Abfrage formulieren kann. Diese Abfrage erzeuge ich in diesem Feld dynamisch mit {{file::build-query.php}}. Die Getparameter hole ich so (schematisch)
    PHP-Code:
    <?php

    $param1 
    = \Input::get('param1');
    $param2 = \Input::get('param2');
    ...
    echo 
    'param1 LIKE "%%'.$param1.'%%" AND param2 LIKE "%%'.$param2.'%%"';
    Da laufen doch alle möglichen Sicherheitsmechanismen drüber https://github.com/contao/core/blob/.../Input.php#L79
    z.B.
    • cleanKey()
    • decodeEntities()
    • xssClean()
    • stripTags()
    • u.a.

    Das sollte doch eigentlich sicher sein. Oder?
    Bitte!
    Vor Anfragen im Forum HTML validieren.
    Codesnippets hier im Froum sauber einrücken. Nur Tabs o. nur Leerzeichen verwenden.

    Vielen Dank an alle Wunschlistenerfüller
    Andreas Burg, Web Solutions

  15. #15
    Contao-Fan Avatar von PaddySD
    Registriert seit
    26.10.2016.
    Ort
    Andechs
    Beiträge
    656

    Standard

    Theoretisch könnte Dir trotzdem noch jemand ein "falsches" SQL-Statement anhängen, daher das "prepare"...

    Einen Strichpunkt gefolgt von einem SQL-Statement sollte klappen bei Deiner Version...

    PHP-Code:
    param2 'test%%;DROP TABLE tl_page;SELECT * FROM tl_page WHERE test LIKE "%%'.param1";
    echo 'param1 LIKE "
    %%'.$param1.'%%" AND param2 LIKE "%%'.$param2.'%%"'; 
    Aber ich bin da echt kein Experte, meine aber, dass das so klappen könnte, Dir was unterzuschieben.... Das ist jetzt natürlich nicht die korrekte Schreibweise, aber "you get the idea"...

    Vielleicht kann ja jemand anderes mit etwas mehr Einblick noch was zu sagen...

  16. #16
    Contao-Urgestein Avatar von Andreas
    Registriert seit
    19.06.2009.
    Ort
    Mönchengladbach
    Beiträge
    7.703
    User beschenken
    Wunschliste
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Und wieso wird das nicht dementsprechend von \Input::get() bereinigt?

    Wenn ich z.B. mit dem Auflistungsmodul die URL manipuliere
    Code:
    ...&show=42 => ...&show=do something
    Dann wird "do something" ja auch in das execute($id) eingetragen. https://github.com/contao/core/blob/...sting.php#L379
    Dann macht das prepare in ModuleListing.php ja auch keinen Sinn.
    Bitte!
    Vor Anfragen im Forum HTML validieren.
    Codesnippets hier im Froum sauber einrücken. Nur Tabs o. nur Leerzeichen verwenden.

    Vielen Dank an alle Wunschlistenerfüller
    Andreas Burg, Web Solutions

  17. #17
    Maintainer Avatar von xtra
    Registriert seit
    02.07.2009.
    Ort
    Tuebingen
    Beiträge
    2.007
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von Andreas Beitrag anzeigen
    Und wieso wird das nicht dementsprechend von \Input::get() bereinigt?
    Weil das falsch waere und du in keinen Eingabefeldern mehr Zeichen verwenden dyrftest die in queries erlaubt sind... Das macht keinen Sinn.
    Addendum: In Contao 5 wird diese Input bereinigung komplett entfallen und wir werden im Frontend Output encoding verwenden, da MUSST du dann zwingend prepared statements nehmen.
    Der Weg jeglichen Input einfach zu cleanen hat bei vielen Extensions die yber ein simples CE hinaus geht schon mal zu Problemen gefyhrt, weshalb es auch postRaw usw. inzwischen gibt.
    Praeventiv jeglichen Input zu cleanen ohne den Kontext zu kennen in welchem er angewandt wird geht einfach nicht, weshalb der Programmierer immer selbst verantwortlich ist diesen zu pryfen und ggf. zu bereinigen oder (IMO besser) zuryckzuweisen.

    Um das Problem mal extrem zu verdeutlichen, du koenntest auch fragen warum die Inputklasse nicht alles ausser Ziffern bereinigt, denn du moechtest in deinem Query ja nur nach einer id suchen.
    Dass damit dann jegliche Texteingabe unmoeglich gemacht wird is klar.
    Die Problematik geht letztendlich schlicht darauf hinaus, dass die Input Klasse viel zu "fryh" dran kommt um sowas zu entscheiden.

    Zitat Zitat von Andreas Beitrag anzeigen
    Wenn ich z.B. mit dem Auflistungsmodul die URL manipuliere
    Code:
    ...&show=42 => ...&show=do something
    Dann wird "do something" ja auch in das execute($id) eingetragen. https://github.com/contao/core/blob/...sting.php#L379
    Dann macht das prepare in ModuleListing.php ja auch keinen Sinn.
    Doch, das macht Sinn, schau dir doch mal an was aus dem Query wird, ich bereinige mal die statischen (und damit irrelevanten) Variablen die nicht vom user kommen:
    PHP-Code:
    $id '1;DROP TABLE tl_page;';
    // ORIGINAL
    $objRecord $this->Database->prepare("SELECT column1, column1 FROM tl_table WHERE id=?")
                                        ->
    execute($id);
    // ergibt: SELECT column1, column1 FROM tl_table WHERE id='1;DROP TABLE tl_page;'

    // Deine Variante:
    $objRecord $this->Database->prepare("SELECT column1, column1 FROM tl_table WHERE id=" $id)
                                        ->
    execute();
    // ergibt: SELECT column1, column1 FROM tl_table WHERE id=1;DROP TABLE tl_page; 
    Du siehst den Unterschied beim parameterisierten Query? Der Parameter wird als ein Wert vom Typ String erkannt und eingesetzt.
    Bei deiner Variante wird nichts gecheckt sondern einfach eingesetzt und schwupps is das Problem da.
    Bedenke stets: Wenn Du ungenaue oder unzureichende Angaben machst, so koennte dies die Bearbeitung deiner Frage endlos verzoegern (oder sogar dazu fyhren, dass ich zu viel nachdenken muss und die Antwort vergesse!). Kein Support per PN.

  18. #18
    Contao-Urgestein Avatar von Andreas
    Registriert seit
    19.06.2009.
    Ort
    Mönchengladbach
    Beiträge
    7.703
    User beschenken
    Wunschliste
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Danke für die ausführliche Erklärung.

    Da ich meine Werte in doppelte Anführungszeichen einschließe
    PHP-Code:
    ... WHERE (param1 LIKE "%value1%" AND param2 >= "value2") ... 
    müsste es dann ja eigentlich reichen, wenn ich die Anführungszeichen mit einem Backslash escape. Oder?
    PHP-Code:
    ... WHERE (param1 LIKE "%value1\";DROP TABLE tl_page%" AND param2 >= "value2\"foo") ... 
    Bitte!
    Vor Anfragen im Forum HTML validieren.
    Codesnippets hier im Froum sauber einrücken. Nur Tabs o. nur Leerzeichen verwenden.

    Vielen Dank an alle Wunschlistenerfüller
    Andreas Burg, Web Solutions

  19. #19
    Maintainer Avatar von xtra
    Registriert seit
    02.07.2009.
    Ort
    Tuebingen
    Beiträge
    2.007
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von Andreas Beitrag anzeigen
    Danke für die ausführliche Erklärung.

    Da ich meine Werte in doppelte Anführungszeichen einschließe
    PHP-Code:
    ... WHERE (param1 LIKE "%value1%" AND param2 >= "value2") ... 
    müsste es dann ja eigentlich reichen, wenn ich die Anführungszeichen mit einem Backslash escape. Oder?
    PHP-Code:
    ... WHERE (param1 LIKE "%value1\";DROP TABLE tl_page%" AND param2 >= "value2\"foo") ... 
    Bedenke dann aber auch, dass ich auch einfach noch ein \ in meine Daten direkt reinmachen koennte, also musst du die \ auch escapen.
    Ansonsten macht dein escaping aus einem " einfach \" und somit ist der backslash dann escaped und das Problem wieder da.

    Das kannst du theorethisch so machen, aber dann stellt sich die Frage, warum du nicht einfach prepare() und execute() verwendest, welches genau dieses tut und diese Faelle abfaengt und genau zu diesem Zwecke erfunden wurde.
    Man kann sicherlich Dinge auf viele Arten erledigen, doch was am sinnvollsten ist, das ist von Fall zu Fall verschieden. Ich fange doch auch nicht an und feile mich durch einen Stahltraeger wenn ich eine Flex habe.

    Ich rate dir nicht nur aus diesem Grunde zu prepared statements sondern auch hinsichtlich eines Upgrades zu Contao 4 und damit der Verwendung von Doctrine und DBO, welches "echte" prepared statements verwendet.
    Diese werden mit den Parameteren an den Server geschickt und koennen dort optimiert gecached werden.
    Wenn du jedesmal das komplette Query schickst (und somit nicht parameterisiert) muss der Server jedes Query von dir gesondert parsen, optimieren, executen und dann die Daten liefern.
    Bei prepared statements (Wie gesagt nicht Contao 3, da hier die Parameter schon so wie du es oben vorschlaegst in die Queries injected) muss der Server das Query nur beim ersten Mal parsen und optimieren.
    Bei jedem weiteren Aufruf werden serverseitig schlicht die Parameter ausgewertet und direkt die Suche ausgefyhrt was die Last auf dem DB Server verringert und generell besser ist.

    Ich verstehe allgemein nicht, warum du dich so gegen die "richtigen" Werkzeuge straeubst.
    Evtl. kannst du mir das erklaeren, damit ich deine Denkweise besser nachvollziehen kann.
    Bedenke stets: Wenn Du ungenaue oder unzureichende Angaben machst, so koennte dies die Bearbeitung deiner Frage endlos verzoegern (oder sogar dazu fyhren, dass ich zu viel nachdenken muss und die Antwort vergesse!). Kein Support per PN.

  20. #20
    Contao-Fan Avatar von PaddySD
    Registriert seit
    26.10.2016.
    Ort
    Andechs
    Beiträge
    656

    Standard

    @xtra
    Auch von mir vielen Dank für die ausführliche Aufdröselung. Im Grunde das, was ich wusste, aber keinsefalls so sagen könnte wie Du.

    Danke übrigens auch für den Ein- und Ausblick bzgl. Contao 4. Das mit den prepared statements hört sich ja sehr gut an, ich sollte es mir doch mal anschauen...

  21. #21
    Contao-Urgestein Avatar von Andreas
    Registriert seit
    19.06.2009.
    Ort
    Mönchengladbach
    Beiträge
    7.703
    User beschenken
    Wunschliste
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Nein, ich sträube mich nicht dagegen, im Gegenteil, ich sehe das so wie du und möchte auch die dafür vorgesehenen Methoden benutzen.

    Ich habe hier nur den Fall, wo ich es mir einfach machen und nicht programmieren wollte. D.h. ich wollte das Auflistungsmodul dazu benutzen Datensätze aufzulisten. Es unterstützt aber nur die Parameter search (ein Feld der Tabelle) und for (den Wert). Die Feldauswahl (search) geht im FE über ein Input-Select. Ich habe daraus 4 einzelne Input-Text-Felder gemacht, damit ich gleichzeitig über mehrere Felder suchen kann. Da das Modul keinen Hook besitzt, hole ich die vom Benutzer eingegebenen Such-Werte in das BE-Feld Bedingung (list_where) (Feld vom Auflistungsmodul).

    Das hier steht in ModuleListing.php vom Core
    PHP-Code:
    if ($this->list_where)
    {
        
    $strQuery .= " WHERE (" $this->list_where ")";

    Dort wird meine list_where (Bedingung) dann eingeschleust.
    PHP-Code:
    if ($this->list_where)
    {
        
    $strQuery .= " WHERE ("field1 LIKE "%value1%" AND field2 <= "value2"")";

    Die Feldnamen sind sicher, ich hole sie mit \Input::get('fieldname'). Nur die Values muss ich jetzt noch absichern.
    Bitte!
    Vor Anfragen im Forum HTML validieren.
    Codesnippets hier im Froum sauber einrücken. Nur Tabs o. nur Leerzeichen verwenden.

    Vielen Dank an alle Wunschlistenerfüller
    Andreas Burg, Web Solutions

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •