Über C++ erstelle SQL Befehlt liefert keine Daten



  • Hallo zusammen,

    die Suche im Google und hier hat mir leider nichts gebracht. Daher dachte ich, ich poste ma die Frage. Falls ich zu blöd war um es zu finden, wäre ich froh über Tipps wie man am besten sowas finden kann.

    Nun zu meine Frage
    Für mein Programme hole ich verschiedene Daten aus der Datenbank. Mit dem folgendem Befehl bekomme ich richtige ergebnisse zurück, aber nur wenn alle Felder Daten enthalten. Sobald ein Feld leer ist, steht in SQL-Befehl (Feldnummer = '(null)') und so bekomme ich keine Daten zurückgeliefert.

    Quellcode
    s.sprintf(L"SELECT * FROM IPM_BEM2IP WHERE (PRJBESITZER = %u) and (PRJNUMMER = %lu) and (DAPNUMMER = %lu) and (LIFKUBEZEICH = '%s') and (ISAATRINDEX = '%s') ", PRJBesitzer, PRJNummer, DAPNummer, _LIFKuBezeich, _ISAATRIndex);

    Erzeugtes SQL-Befehl
    SELECT *
    FROM IPM_BEM2IP
    WHERE (PRJBESITZER = 600 ) and (PRJNUMMER = 3 ) and (DAPNUMMER = 0 ) and (LIFKUBEZEICH = '(null)') and (ISAATRINDEX = '19')

    Ich kann natürlich eine If-Anweisung in C++ schreiben aber bin mir Sicher das es ein SQL-Befehl gibt die mir da weiter helfen kann.

    Danke im Voruas

    LG
    Samir



  • Was willst du machen wenn LIFKuBezeich NULL ist?
    Was soll das generierte SQL Statement dann machen?



  • Naja wenn der String leer ist dann soll auch leer-String geholt werden....

    Das heißt er soll folgendes holen
    LIFKuBezeich = "";
    LIFKuBezeich = NULL;

    Das sollte er nicht zurückliefern
    LIFKuBezeich = L"BUS";



  • s.sprintf(
        L"SELECT * "
        L"FROM IPM_BEM2IP "
        L"WHERE PRJBESITZER = %u "
        L"  and PRJNUMMER = %lu "
        L"  and DAPNUMMER = %lu "
        L"  and ISNULL(LIFKUBEZEICH, '') = '%s' "
        L"  and ISAATRINDEX = '%s' ",
        PRJBesitzer,
        PRJNummer,
        DAPNummer,
        _LIFKuBezeich ? _LIFKuBezeich : "",
        _ISAATRIndex);
    


  • Danke für die Hilfe 🙂

    Leider bekomme ich folgende Fehlermeldung
    Konvertierung von 'UnicodeString' nach 'bool' nicht möglich 😕

    Ich kannte die If-Anweisung innerhalb von sprintf auch nicht. Dank dir weiß ich es jetzt. Also nochmals Danke... 👍 😃

    Ich habe jetzt ein bisschen nach sprintf und if-Anweisung gegoogelt und fand da nur einen einzigen Forumabfrage auf Englisch. Sonst findet man immer nur die Standard Dinge zum Beispiel das hier "http://de.cppreference.com/w/cpp/io/c/fprintf". Kannst du mir vielleicht verraten wo ich solche "Insider" Informationen bekommen kann?

    LG
    Samir



  • Oh, ich dachte _LIFKuBezeich wäre ein wchar Zeiger. Weil du die Variable einfach so an sprintf übergibst. Das ist nämlich undefiniertes Verhalten wenn die Variable keine "eingebauten" Typ hat sondern eine Instanz von irgend einem "user defined type" ist.

    Vorausgesetzt es handelt sich um die UnicodeString Klasse aus der ICU Library sollte das funktionieren:

    s.sprintf(
        L"SELECT * "
        L"FROM IPM_BEM2IP "
        L"WHERE PRJBESITZER = %u "
        L"  and PRJNUMMER = %lu "
        L"  and DAPNUMMER = %lu "
        L"  and ISNULL(LIFKUBEZEICH, N'') = '%s' " // bzw. IFNULL, NVL oder COALESCE - je nachdem was der Server unterstützt 
        L"  and ISAATRINDEX = '%s' ",
        PRJBesitzer,
        PRJNummer,
        DAPNummer,
        _LIFKuBezeich.isEmpty() ? static_cast<UChar const*>(L"") : _LIFKuBezeich.getTerminatedBuffer(),
        _ISAATRIndex.getTerminatedBuffer());
    

    Samir schrieb:

    Ich kannte die If-Anweisung innerhalb von sprintf auch nicht. Dank dir weiß ich es jetzt. Also nochmals Danke... 👍 😃

    Ich habe jetzt ein bisschen nach sprintf und if-Anweisung gegoogelt und fand da nur einen einzigen Forumabfrage auf Englisch. Sonst findet man immer nur die Standard Dinge zum Beispiel das hier "http://de.cppreference.com/w/cpp/io/c/fprintf". Kannst du mir vielleicht verraten wo ich solche "Insider" Informationen bekommen kann?

    Was den ? Operator angeht - das ist kein Insiderwissen, das ist einfach C++. Hat auch mit printf nichts zu tun - das kann man überall verwenden.
    http://www.cplusplus.com/doc/tutorial/operators/
    http://www.cplusplus.com/forum/articles/14631/

    Was das ISNULL (bzw. IFNULL/NVL/COALESCE ) angeht - das sind SQL Funktionen. Auch kein Insiderwissen. Welche du verwenden kannst hängt davon ab mit welchem SQL Server du arbeitest. Und ob es im ISNULL/IFNULL/NVL/COALESCE dann N'' oder einfach nur '' heissen muss kommt auch wieder aus den Server drauf an. ISNULL(LIFKUBEZEICH, N'') sollte mit MS SQL Server funktionieren.



  • ISNULL Funktion von SQL kannte ich bereits, auch die Operatoren. Nur bei ? habe ich dann wohl verschalfen. Aber Danke für die Links, waren sehr informativ... 😃

    Bei
    static_cast<UChar const*>(L"")
    Bekomme ich die Fehlermeldung "Typname erwartet".
    Ich verwende C++ Builder XE7 von Embarcadero und habe leider kein funktionierendes Header-Datei gefunden die ich einbinden kann damit es erkannt wird.

    Danach habe ich es durch Unicodestring ersetzt um zu sehen ob sonst alles Okay ist.
    Bei

    _LIFKuBezeich.getTerminatedBuffer()
    

    bekomme ich die Fehlermeldung das getTerminatedBuffer kein Member von Unicodestring ist. Ich wollte es durch was anderes ersetzen aber leider finde ich nichts mit Terminated oder Buffer. Und ohne funktioniert es auch nicht.

    P.S. Die UnicodeString die ich benutze ist von

    class RTL_DELPHIRETURN UnicodeString
    


  • Gut.
    Dann ändere es so dass die Funktionen verwendet werden die deine String Klasse eben hat.
    Das musst du schaffen wenn du dich irgendwann Programmierer nennen willst.



  • Samir schrieb:

    Ich verwende C++ Builder XE7 von Embarcadero...

    Ich bohre hier mal etwas nach... Welches Framework nutzt du um die SQL-Befehle auszuführen? Ist dies eine C++ Builder spezifische Bibliothek?



  • Naja leider finde ich nichts mit Buffer in der Liste sonst hätte ich es bereits gemacht. Aber ist ok wenn du nicht Weißt wie es geht. Es gibt ja auch andere hier.

    @asc
    Ich benutze die TADO um die Befehle auf dem SQL-Server auszuführen.



  • Samir schrieb:

    @asc
    Ich benutze die TADO um die Befehle auf dem SQL-Server auszuführen.

    Und dann bastelst du dir die SQL-Befehle mit sprintf, statt mit SQL-Parametern zusammen? Ich kann zwar nicht viel Gutes zu den TADO-Komponenten sagen, da sind einige kommerzielle Frameworks (wie z.B. SDAC) wesentlich besser und schneller, aber auch diese Komponenten sollten mit SQL-Parametern klar kommen.

    Dynamisches setzen ist zwar etwas kompliziert (und der Beispielcode ist auch nicht wirklich das, was ich als sauber bezeichnen würde: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/ADODB_TADOQuery.html ), aber wenn die Komponenten in einem DataModule angelegt werden, ersparst du dir das (Da kannst du die Eigenschaften entsprechend setzten).

    SQL-Parameter solltest du dir schon alleine der Sicherheit halber einmal anschauen, ich habe in den 2 Jahren in den ich in der QS aktiv war schon so manche Datenbank zerlegt, nachdem mir ein Entwickler gesagt hatte das alles in Ordnung wäre... (Thema: SQL-Injection; Ohne SQL-Parameter kann ich dir DROP Table-Befehle und ähnliches unterjubeln).



  • Samir schrieb:

    Naja leider finde ich nichts mit Buffer in der Liste sonst hätte ich es bereits gemacht. Aber ist ok wenn du nicht Weißt wie es geht. Es gibt ja auch andere hier.

    Oh ich weiss schon wie es geht.

    Ich hab nur keine Lust deinen Job für dich zu machen.
    Wenn du es nicht schaffst dir aus der Hilfe ein paar einfache Funktionen rauszusuchen, dann kann bzw. will ich dir einfach nicht helfen.

    ps:
    Dass du keinen Plan hast wie man Fragen richtig stellt und man dir alle Informationen aus der Nase ziehen bzw. erraten muss hilft auch nicht.



  • http://docwiki.embarcadero.com/Libraries/XE8/de/System.UnicodeString_Methods

    Mit 'ner ordentlichen IDE sollte man das aber auch ohne google raus finden können. Das ist wohl das, was hustbaer meinte.



  • Hi,

    TADOQuery würde ich nicht mehr nehmen, das ist eine Krücke, die genau wie TADOTable nur gemacht wurde um die entsprechenden BDE-Funktionen nachzubilden.

    Für SQL-Befehle die was zurück geben (ne Tabelle aufmachen...) nimm TADODataSet und für reine Ausführungsbefehle nimm TADOCommand. Die sind wesentlich sauberer programmiert.

    Ich arbeite praktisch nur noch mit .mdb-Dateien, und da ist ADO das Mittel der Wahl. Kann mich da über die Funktionalität und Zuverlässigkeit nicht beklagen.

    Für das Setzen von Parametern habe ich mir ne modifizierte Version von ADODataset und ADOCommand abgeleitet, bei der ich einen Parameter mit einer Anweisung komplett setze:

    // Funktionsdeklaration
    procedure TADODataSetMod.SetParameter(Name: AnsiString; FeldType: TFieldType;
      Wert: Variant);
    begin
      Parameters.ParamByName( Trim( Name ) ).DataType := ftInteger;
      Parameters.ParamByName( Trim( Name ) ).Value    := Wert;
    end;
    
    // das Anwenden erfolgt dann so:
    dsSchlag.SetParameter( 'Jahr', ftInteger, MainForm.Jahr );
    

    Ist Delphi, sollte aber leicht nach C++ übertragbar sein.
    Dadurch hat man alle Angaben zu einem Parameter in einer Zeile, was es übersichtlihcer macht.

    Gruß Mümmel



  • muemmel, der Vorgang hatte schon seit etwa 3 Monaten keine weiteren Antworten mehr, wahrscheinlich wird der OP bereits eine Problemlösung haben oder sich nicht mehr für das Thema interessieren...



  • Hi Asc,

    asc schrieb:

    muemmel, der Vorgang hatte schon seit etwa 3 Monaten keine weiteren Antworten mehr...

    Hab leider auch erst nach dem Antworten gemerkt, dass ich gerade an einer angefaulten Leiche Wiederbelebungsversuche gemacht habe.
    Manchmal bildet lesen eben nicht nur, sondern erspart - rechtzeitig angewendet - auch Arbeit.

    Gruß Mümmel


Log in to reply