hawkmaster: Problem mit Prepared Statement bei Postgres

Hallo zusammen,

Ich versuche mich gerade an einer Umstellung von MySQL zu Postgres.
Ich verwende PDO und Prepared Statements.

Eine SQL Abfrage in MySQL funktionierte so:
$dboResultText = $DBO->prepare("SELECT TextID, ".$userlang."  FROM ir_text  WHERE :userlang != '' AND UsedInInterface = 'yes'");
$dboResultText->bindParam(':userlang', $userlang);
$dboResultText->execute();

Für Postgres versuche ich es nun so:

$dboResultText = $DBO->prepare('SELECT "TextID", '.$userlang.'  FROM ir.ir_text  WHERE :userlang != "" AND "UsedInInterface" = "yes"');
$dboResultText->bindParam(':userlang', $userlang);
$dboResultText->execute();

Hier kommt nun aber eine Fehlermeldung:

FEHLER: Bezeichner in Anführungszeichen hat Länge null bei »""« LINE 1: ...TextID", English FROM ir.ir_text WHERE $1 != "" AND

Vermutlich kann bindParam nicht aufgelöst werden bzw. stimmt "WHERE :userlang" nicht.
Ich weiss aber nicht wie man dies anders schreiben könnte?

vielen Dank und viele Grüße
hawk

  1. Moin Moin!

    Eine SQL Abfrage in MySQL funktionierte so:

    $dboResultText = $DBO->prepare("SELECT TextID, ".$userlang."  FROM ir_text  WHERE :userlang != '' AND UsedInInterface = 'yes'");

    $dboResultText->bindParam(':userlang', $userlang);
    $dboResultText->execute();

    
    >   
    > Für Postgres versuche ich es nun so:  
    >   
    > ~~~php
    
    $dboResultText = $DBO->prepare('SELECT "TextID", '.$userlang.'  FROM ir.ir_text  WHERE :userlang != "" AND "UsedInInterface" = "yes"');  
    
    > $dboResultText->bindParam(':userlang', $userlang);  
    > $dboResultText->execute();
    
    

    Hier kommt nun aber eine Fehlermeldung:

    FEHLER: Bezeichner in Anführungszeichen hat Länge null bei »""« LINE 1: ...TextID", English FROM ir.ir_text WHERE $1 != "" AND

    Vermutlich kann bindParam nicht aufgelöst werden bzw. stimmt "WHERE :userlang" nicht.

    Mumpitz. Lies die Fehlermeldung.

    Ich weiss aber nicht wie man dies anders schreiben könnte?

    Na, richtig halt. ;-)

    MySQL kennt zwischen Single und Double Quotes keinen Unterschied, beide erzeugen Strings. Der Rest der SQL-Welt nutzt Single Quotes für Strings und Double Quotes für Identifier. Letztere quoted MySQL an allen Standards vorbei mit Backticks. Frag mich nicht, was die Leute geraucht haben ...

    Schau Dir die Where-Bedingung mal genauer an. Hast Du eine Spalte namens ""? Oder eine namens "yes"?

    Am Rande: Woher hast Du eigentlich die merkwürdige Idee, alle Identifier quoten zu müssen?

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
    1. Hi!

      MySQL kennt zwischen Single und Double Quotes keinen Unterschied, beide erzeugen Strings.

      Jedenfalls wenn MySQL nicht im ANSI_QUOTES SQL-Mode läuft. Um in dem Fall Identifier identifizieren zu können, sind die Backticks vorgesehen.

      Der Rest der SQL-Welt nutzt Single Quotes für Strings und Double Quotes für Identifier. Letztere quoted MySQL an allen Standards vorbei mit Backticks. Frag mich nicht, was die Leute geraucht haben ...

      Diese Aussage stimmt nicht. Man kann es umstellen.

      Am Rande: Woher hast Du eigentlich die merkwürdige Idee, alle Identifier quoten zu müssen?

      Wegen.

      Lo!

      1. Moin Moin!

        MySQL kennt zwischen Single und Double Quotes keinen Unterschied, beide erzeugen Strings.

        Jedenfalls wenn MySQL nicht im ANSI_QUOTES SQL-Mode läuft. Um in dem Fall Identifier identifizieren zu können, sind die Backticks vorgesehen.

        Der Rest der SQL-Welt nutzt Single Quotes für Strings und Double Quotes für Identifier. Letztere quoted MySQL an allen Standards vorbei mit Backticks. Frag mich nicht, was die Leute geraucht haben ...

        Diese Aussage stimmt nicht. Man kann es umstellen.

        Diese Aussage stimmt nicht. Out of the Box läuft MySQL so, wie von mir beschrieben. Klar kann man MySQL Manieren beibringen, aber in der Default-Konfiguration läuft MySQL ohne ANSI Quotes.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
    2. Hallo Alexander,

      danke für deine Hilfe.

      Am Rande: Woher hast Du eigentlich die merkwürdige Idee, alle Identifier quoten zu müssen?

      nun deswegen drehe ich mich schon eine Weile im Kreis. Ich hatte von MySQL zu Postgres migriert. Vorher hatte in MySQl dies wunderbar funktioniert.

      query("SELECT LanguageID,LanguageDescription,TextID,CountryCode, ConfigName FROM ir_language ORDER BY LanguageID ASC")

      Ein Aufruf in Postgres aber brachte Fehlermeldungen ohne Ende.Offensichtlich interpretiert Postgres alle Spalten in Kleinbuchstaben.
      Für Postgres muss ich alle Spaltennamen in Hochkomma einschließen und auch noch den Datenbankname vor jede Tabelle setzen.
      query('SELECT "LanguageID","LanguageDescription","TextID","Count ryCode","ConfigName" FROM testdb.ir_language ORDER BY "LanguageID" ASC')

      Mir wäre natürlich viel lieber ich könnte meinen bisherigen Code zumindest teilweise so beibehalten. Alle SQL und Spaltennamen zu ändern ist aufwendig ohne Ende.
      Jetzt habe ich einen anderen Converter ausprobiert. Hier kann man angeben ob die Namen in Kleinbuchstaben umgewandelt werden sollen. Nachdem ich dies versucht habe,kann ich meine alten Abfragen ohne Hochkomma verwenden.
      Dies ist aber auch nur eine Lösung. Das Problem ist nun nämlich das man z.b. bei Returnwerten einer Funktion auch alles klein schreiben muss.

      vorher:
      return $foundroot['MyDirectoryPath'];

      mus ich nun ändern in;
      return $foundroot['mydirectorypath'];

      Du siehst ich drehe mich immer noch im Kreis. Wie dedlfix und auch Vinzenz schön öfters gesagt haben. Einheitlichen Code DB übergreifend hinzubekommen ist vermutlich eine Illusion.

      Wenn du also einen Ausweg aus der Misere mit der Groß- Kleinschreibweise weisst, dann bin ich für alles zu haben

      vielen Dank und viele Grüße
      hawk

      1. Hallo,

        Für Postgres muss ich alle Spaltennamen in Hochkomma einschließen

        nur in bestimmten Fällen :-)

        und auch noch den Datenbankname vor jede Tabelle setzen.

        a) ist es nicht der Datenbankname, sondern der Schemaname.
        b) sollte der Dir von mir ans Herz gelegte Handbuchabschnitt aufzeigen, wie
           Du das Verwenden von (teil-)qualifierten Bezeichnern vermeiden kannst.

        Freundliche Grüße

        Vinzenz

        1. Hallo Vinzenz,
          danke nochmals für deine Geduld und Hilfe.

          b) sollte der Dir von mir ans Herz gelegte Handbuchabschnitt aufzeigen, wie
             Du das Verwenden von (teil-)qualifierten Bezeichnern vermeiden kannst.

          Ich habe mir das zwar durchgelesen aber wenn ich ehrlich bin, so richtig weitergeholfen hat es mich auch nicht.
          Ich habe das so verstanden, dass man dadurch das Problem mit dem Schema Name vor der Tabelle also etwa, mydatabase.ir_language verhindern kann.
          Ich hatte dies nicht im Zusammenhang mit den Hochkomma um die Spaltennamen verstanden.

          vielen Dank und viele Grüße
          hawk

          1. Hallo,

            danke nochmals für deine Geduld und Hilfe.

            b) sollte der Dir von mir ans Herz gelegte Handbuchabschnitt aufzeigen, wie
               Du das Verwenden von (teil-)qualifierten Bezeichnern vermeiden kannst.

            Ich habe mir das zwar durchgelesen aber wenn ich ehrlich bin, so richtig weitergeholfen hat es mich auch nicht.
            Ich habe das so verstanden, dass man dadurch das Problem mit dem Schema Name vor der Tabelle also etwa, mydatabase.ir_language verhindern kann.

            eben. Indem Du

            SET search_path TO mydatabase;

            verwendest, wie es in diesem Abschnitt steht. Dort steht auch, dass es oft keine gute Idee ist, Schemanamen in Anwendungscode bei allen Statements hart zu verdrahten.

            Ich hatte dies nicht im Zusammenhang mit den Hochkomma um die Spaltennamen verstanden.

            Dafür hatte ich Dir wiederum einen anderen Handbuchabschnitt verlinkt, siehe auch https://forum.selfhtml.org/?t=203186&m=1373734

            Freundliche Grüße

            Vinzenz

            1. Hallo Vinzenz,

              ich habe nun nochmals deinen Ratschlag aus meinem ursprünglichen Post wegen den Hochkommas ausprobiert.

              ALTER TABLE test ADD COLUMN "LangID" integer;

              Lass Doch die Anführungszeichen weg. Dann ist der Spaltenname case-insensitive:

              ALTER TABLE test ADD COLUMN LangID integer;

              Ich habe also mal im PGAdmin direkt im SQL Editor ein;
              ALTER TABLE test ADD COLUMN TextID integer;

              ausgeführt. Dann sind zwar keine Hochkommas um den Spaltennamen, aber Postgres mach dann automatisch alles in Kleinbuchsten und die Spalte ist dann
              testid

              Das ist ja dann wieder nicht was ich wollte. Eigentlich wollte ich ja die ursprüngliche Schreibweise meiner MySQL DB Spalten beibehalten.

              vielen Dank und viele Grüße
              hawk

      2. Moin Moin!

        Hallo Alexander,

        danke für deine Hilfe.

        Am Rande: Woher hast Du eigentlich die merkwürdige Idee, alle Identifier quoten zu müssen?

        nun deswegen drehe ich mich schon eine Weile im Kreis. Ich hatte von MySQL zu Postgres migriert. Vorher hatte in MySQl dies wunderbar funktioniert.

        Es funktioniert noch viel besser, wenn Du dich bei den Identifiern auf das Set [A-Za-z0-9_] beschränkst und auf die Quotes verzichtest. Dann ist SQL nämlich case insensitiv.

        Dies ist aber auch nur eine Lösung. Das Problem ist nun nämlich das man z.b. bei Returnwerten einer Funktion auch alles klein schreiben muss.

        vorher:
        return $foundroot['MyDirectoryPath'];

        mus ich nun ändern in;
        return $foundroot['mydirectorypath'];

        Das ist zur Hälfte eine Macke von PostgreSQL, dessen Identifier sind im Gegensatz zu den meisten anderen RDBMS intern als Kleinbuchstaben statt als Großbuchstaben abgelegt und auch an der Schnittstelle so wieder ausgibt.

        Die andere Hälfte des Problems ist, dass Du PDO::CASE_XXX offenbar nicht kennst. (Am Rande: Perls DBI nennt das FetchHashKeyName.) Damit bekommst Du DB-unabhängig immer Bit für Bit die selben Spaltennamen.

        Du siehst ich drehe mich immer noch im Kreis. Wie dedlfix und auch Vinzenz schön öfters gesagt haben. Einheitlichen Code DB übergreifend hinzubekommen ist vermutlich eine Illusion.

        Nein, nur ein fehlender Layer zwischen DB-Schnittstelle und Programm.

        Ich hab mit ein paar hundert Zeilen Perl, aufsetzend auf DBI, schon im letzten Jahrhundert DB-unabhängigen Code geschrieben. Das Programm lief (und läuft noch heute) ohne eine Zeile Code zu ändern auf diversen Versionen von Oracle, MS SQL Server und PostgreSQL; DB2-Support war geplant, MySQL (3 und 4) wegen der diversen Macken explizit ausgeschlossen. Prinzipiell müßte das System auch mit SQLite und anderen RDBMS funktionieren.

        Natürlich muß man sich dabei ein wenig einschränken, was Features angeht. Man kann nicht einfach irgendein MySQL-Script in Oracle stopfen und hoffen, dass Oracle das ohne Murren verdaut. Mein Layer hat sich damals hauptsächlich um Meta-Informationen (welche Tabellen gibt es, welche Spalten haben sie), Datentypen-Mapping ("STRING:255" heißt in Oracle VARCHAR2(255), in MSSQL "NVARCHAR(255)" und in PostgreSQL "VARCHAR(255)") und Insert-Statements gekümmert, der Rest ging ohne Mehraufwand direkt durch zum DBI.

        Heute würde ich vermutlich einen ORM zwischen Anwendung und DB-Schnittstelle setzen, damit spare ich mir für Routine-Fälle das SQL komplett, weil es stumpf automatisch generiert wird, sobald der ORM über die darunter liegende DB informiert ist.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
        1. Hallo

          Nur mal so am Rand.
          Wie macht ihr Experten denn die Schreibweise mit den Spaltennamen?
          Ich habe viele Tabellen wo ich die Spaltennamen in gemischter Groß- Kleinschreibweise habe. Also etwa;
          LanguageID oder TextID

          Ist das sinnvoll oder wäre es nicht einfacher dann gleich alles in Kleinschreibweise zu machen?
          Denn selbst wenn man mit
          PDO::ATTR_CASE: Force column names to a specific case.
                PDO::CASE_LOWER: Force column names to lower case.

          auf lower case umstellen kann, dann kann ich doch mir gleich die Mühe machen und alle Spalten auf Kleinbuchstaben umzustellen. Dann habe ich später weniger Probleme.
          Oder sehe ich das falsch?

          vielen Dank und viele Grüße
          hawk

          1. Hi!

            Wie macht ihr Experten denn die Schreibweise mit den Spaltennamen?

            MySQL ist da ja so nett, die Groß-Kleinschreibung zu bewahren. Genau die Probleme mit der automatischen Anpassung sind mir auch mal bei einem Oracle-Einsatz negativ aufgefallen, was dazu führte, dass ich konsequent die Bezeichner quotierte. So behielt ich die Lesbarkeit und musste nicht mit irgendwelchen upper- oder lower-Funktionen hantieren. (PDO gabs damals noch nicht.)

            Ich habe viele Tabellen wo ich die Spaltennamen in gemischter Groß- Kleinschreibweise habe. Also etwa;
            LanguageID oder TextID

            Finde ich auf alle Fälle besser lesbar als eine komplette Klein- oder Großschreibung. Wenn man da die Lesbarkeit bewahren will, müsste man sich mit Zusatzzeichen behelfen: language_id oder TEXT_ID.

            Ist das sinnvoll oder wäre es nicht einfacher dann gleich alles in Kleinschreibweise zu machen?

            Ich mag Systemem nicht, die mir eine Schreibweise aufzwingen wollen, wenn auch implizit, weil die Antwort einfach in Kleinbuchstaben daherkommt und nicht so wie ich das mal geschrieben habe. Du musst nun entscheiden, was dir lieber ist. Entweder du passt dich an das System an und nimmst generell auch Kleinbuchstaben. Oder du beachtest, dass alles in Kleinbuchstaben zurückkommt und schreibst eventuell Übersetzungstabellen, damit die Anwendung eine ordentliche Schreibweise nehmen und das DBMS seinen eigenen Stiefel fahren kann.

            Denn selbst wenn man [...] auf lower case umstellen kann, dann kann ich doch mir gleich die Mühe machen und alle Spalten auf Kleinbuchstaben umzustellen. Dann habe ich später weniger Probleme. Oder sehe ich das falsch?

            Das wirst du dann sehen, wenn die Probleme auftauchen.

            Lo!

            1. Hi dedlfix,

              vielen Dank für deinen Rat und deine Hinweise.
              Mir ist eigentlich auch eine Camel Case Schreibweise lieber. Finde ich auch besser lesbar.

              Na mal sehen wie ich jetzt hier bei Postgres weiter vorgehe.

              vielen Dank und viele Grüße
              hawk

          2. Moin Moin!

            Hallo

            Nur mal so am Rand.
            Wie macht ihr Experten denn die Schreibweise mit den Spaltennamen?

            Ungequoted aus dem Set [A-Z0-9_], sowohl für Spalten als auch für andere Identifier (Namen von Tabellen, Views, Prozeduren, Funktionen, Variablen, ...).

            Ich habe viele Tabellen wo ich die Spaltennamen in gemischter Groß- Kleinschreibweise habe. Also etwa;
            LanguageID oder TextID

            LANGUAGE_ID, Language_ID, language_id, wie es Dir gerade paßt. Ist alles beliebig, so lange Du die Finger von den Quotes läßt.

            Ist das sinnvoll oder wäre es nicht einfacher dann gleich alles in Kleinschreibweise zu machen?

            Es ist völlig egal, ob Du groß oder klein schreibst, so lange Du die Finger von den Quotes läßt.

            Denn selbst wenn man mit
            PDO::ATTR_CASE: Force column names to a specific case.
                  PDO::CASE_LOWER: Force column names to lower case.

            auf lower case umstellen kann, dann kann ich doch mir gleich die Mühe machen und alle Spalten auf Kleinbuchstaben umzustellen. Dann habe ich später weniger Probleme.
            Oder sehe ich das falsch?

            Ja. Die nächste DB, auf die Du portierst, liefert Dir die Spaltennamen wieder in Großbuchstaben. PDO::ATTR_CASE + PDO::CASE_LOWER bzw. PDO::CASE_UPPER sorgt dafür, dass die Spaltennamen unabhängig von den Details der DB-Implementierung sind.

            Außerdem zwingst Du jeden, der sich irgendwann mal mit Deiner Software und der darunter liegenden DB rumschlagen muß, ebenfalls alle Identifier zu quoten, was gerade bei Wartungsarbeiten echt lästig ist.

            Überlaß es der DB, ob sie die Identifier als upper oder lower case speichern will, damit ersparst Du Deinem Nachfolger auch die Quoting-Orgien. PDO kümmert sich darum, dass Du die Spalten im Programm unter konstanten Namen ansprechen kannst.

            Alexander

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            1. Hallo Alexander,

              Ungequoted aus dem Set [A-Z0-9_], sowohl für Spalten als auch für andere Identifier (Namen von Tabellen, Views, Prozeduren, Funktionen, Variablen, ...).

              OK, das würde ja auch meiner bisherigen Schreibweise entsprechen.

              LANGUAGE_ID, Language_ID, language_id, wie es Dir gerade paßt. Ist alles beliebig, so lange Du die Finger von den Quotes läßt.

              Ok, stellt sich mir nun nochmals die Frage. Ist dann dein SQL Code identisch zur DB. Wenn du also z.b. eine PHP Datei hast wo etwa:
              SELECT LanguageID FROM mytable WHERE UserID = 3
              steht. Ist dann auch in deiner DB die Spaltenbezeichnung in dieser Schreibweise?
              Wenn ja bin ich wieder bei dem alten Problem, siehe;

              http://forum.de.selfhtml.org/my/?t=203232&m=1374036

              Bei MySQL kann ich ja problemlos meine Spalten in Groß-Kleinschreibweise anlegen.
              Postgres macht mir hier aber automatisch um jeder Spalte diese Hochkommas.
              Ich habe bis jetzt zumindest keine Möglichkeit gefunden eine Spalte in PG z.b. LanguageID zu bezeichnen, ohne Hochkommas

              vielen Dank und viele Grüße
              hawk

              1. Moin Moin!

                Hallo Alexander,

                Ungequoted aus dem Set [A-Z0-9_], sowohl für Spalten als auch für andere Identifier (Namen von Tabellen, Views, Prozeduren, Funktionen, Variablen, ...).

                OK, das würde ja auch meiner bisherigen Schreibweise entsprechen.

                LANGUAGE_ID, Language_ID, language_id, wie es Dir gerade paßt. Ist alles beliebig, so lange Du die Finger von den Quotes läßt.

                Ok, stellt sich mir nun nochmals die Frage. Ist dann dein SQL Code identisch zur DB.

                Hä?

                Wenn du also z.b. eine PHP Datei hast wo etwa:
                SELECT LanguageID FROM mytable WHERE UserID = 3
                steht. Ist dann auch in deiner DB die Spaltenbezeichnung in dieser Schreibweise?

                Ich lege Tabellen- und Spaltennamen an, ohne Quoting zu benutzen. Wie die DB das intern speichert, ist mir völlig egal.

                Ich benutze Tabellen- und Spaltennamen in SQL-Statements ohne Quoting, wie die DB damit intern arbeitet, ist mir völlig egal.

                In Fetches kümmert sich DBI darum, dass die Spaltennamen in eine von der DB unabhängige Schreibweise umgesetzt werden, je nach Projektalter und Tageslaune beim Anlegen des Projekts mal Kleinbuchstaben, mal Großbuchstaben. PDO sollte das über die CASE-Konstanten ebenfalls können.

                Wenn ja bin ich wieder bei dem alten Problem, siehe;

                https://forum.selfhtml.org/?t=203232&m=1374036

                Wo ist da nur das Problem? Einmal Editor-Kommando "search and replace in files" für alle Projektdateien pro Spaltenname, fertig. Notfalls klappt das auch mit find, xargs und sed.

                Bei MySQL kann ich ja problemlos meine Spalten in Groß-Kleinschreibweise anlegen.

                Das kannst Du auch in vielen anderen RDBMS.

                Postgres macht mir hier aber automatisch um jeder Spalte diese Hochkommas.

                Hä? Wo erzeugt PostgreSQL Single Quotes?

                Ich habe bis jetzt zumindest keine Möglichkeit gefunden eine Spalte in PG z.b. LanguageID zu bezeichnen, ohne Hochkommas

                Identifiers and Key Words

                Pack Identifier in Double Quotes und PostgreSQL erlaubt Dir fast jeden Unfug als Identifier zu benutzen: "Quoted identifiers can contain any character, except the character with code zero. (To include a double quote, write two double quotes.) This allows constructing table or column names that would otherwise not be possible, such as ones containing spaces or ampersands. The length limitation still applies." Du kannst sogar beliebige Zeichen aus Unicode herauspicken, solltest Du Deine Spalten mal in Kanji, Kyrillisch oder Arabisch benennen wollen.

                Ohne Double Quotes gelten die Regeln für einfache Identifier: "SQL identifiers and key words must begin with a letter (a-z, but also letters with diacritical marks and non-Latin letters) or an underscore (_). Subsequent characters in an identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($). Note that dollar signs are not allowed in identifiers according to the letter of the SQL standard, so their use might render applications less portable. The SQL standard will not define a key word that contains digits or starts or ends with an underscore, so identifiers of this form are safe against possible conflict with future extensions of the standard. [...] Key words and unquoted identifiers are case insensitive."

                In Sachen Wartbarkeit habe ich Dir ja bereits geraten, Dich auf einfache Identifier zu beschränken, vergiß also am besten, dass es Quoted Identifiers überhaupt gibt.

                Alexander

                --
                Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                1. Hallo Alexander,

                  Ich lege Tabellen- und Spaltennamen an, ohne Quoting zu benutzen. Wie die DB das intern speichert, ist mir völlig egal.

                  Ich benutze Tabellen- und Spaltennamen in SQL-Statements ohne Quoting, wie

                  die DB damit intern arbeitet, ist mir völlig egal.

                  irgendwie drehen wir uns im Kreis :-)
                  Beispiel:
                  im Tool pgAdmin lege ich eine Tabelle test an.
                  Dann eine Spalte LanguageID
                  Hier kann ich auch noch sagen "Wie das PG intern speichert ist mir völlig egal".
                  Aber;
                  Ein Select im pgAdmin;

                  select LanguageID from test
                  bringt dann;
                  FEHLER:  Spalte »languageid« existiert nicht
                  LINE 1: select LanguageID from test
                                 ^
                  Das bedeutet ich muss doch meine Spalte LanguageID mit "" quoten.
                  Von daher kapier ich es leider immer noch nicht (sorry für meine lange Leitung) wie du einerseits eine Spalte ala "LanguageID" ansprichst die PG automatisch in "LanguageID" quotet und du in deinem Code LanguagID ohne Quotes ausführst.

                  vielen Dank und viele Grüße
                  hawk

                  1. Moin Moin!

                    Hallo Alexander,

                    Ich lege Tabellen- und Spaltennamen an, ohne Quoting zu benutzen. Wie die DB das intern speichert, ist mir völlig egal.

                    Ich benutze Tabellen- und Spaltennamen in SQL-Statements ohne Quoting, wie
                    die DB damit intern arbeitet, ist mir völlig egal.

                    irgendwie drehen wir uns im Kreis :-)
                    Beispiel:
                    im Tool pgAdmin lege ich eine Tabelle test an.

                    Schau an, pgAdmin. Nicht pgAdmin III?

                    Dann eine Spalte LanguageID

                    Und was macht pgAdmin III daraus?

                    Hier kann ich auch noch sagen "Wie das PG intern speichert ist mir völlig egal".

                    Richtig. Du sagst pgAdmin III aber implizit, dass Du exakt diese Schreibweise haben willst. Das kannst Du im Reiter SQL des Create-Table-Dialogs sehen.

                      
                    CREATE TABLE test  
                    (  
                       "LanguageID" integer  
                    ) WITH (OIDS=FALSE)  
                    ;  
                    
                    

                    Quoted Identifier, case-sensitiv.

                    Durch Ausprobieren läßt sich leicht herausfinden, dass (der Create-Table-Dialog in) pgAdmin III nur quotet, was Großbuchstaben (oder Sonderzeichen) enthält:

                      
                    CREATE TABLE test  
                    (  
                       ganz_klein integer,  
                       "GANZ_GROSS" integer,  
                       "WiLd_GeMiScHt" integer  
                    ) WITH (OIDS=FALSE)  
                    ;  
                    
                    

                    Aber;
                    Ein Select im pgAdmin;

                    select LanguageID from test
                    bringt dann;
                    FEHLER:  Spalte »languageid« existiert nicht
                    LINE 1: select LanguageID from test
                                   ^

                    Logisch. Folgefehler des Verhaltens von pgAdmin III.

                    Das bedeutet ich muss doch meine Spalte LanguageID mit "" quoten.

                    Nein. Entweder legst Du die Spaltennamen über das Mausschubsertool ausschließlich mit Kleinbuchstaben an, oder du schreibst Dir ein Create-Tables.sql, in dem Du beliebige Schreibweisen benutzen kannst. Das kannst Du dann auch über pgAdmin III ausführen, oder jeden anderen PostgreSQL-Client.

                    Von daher kapier ich es leider immer noch nicht (sorry für meine lange Leitung) wie du einerseits eine Spalte ala "LanguageID" ansprichst die PG automatisch in "LanguageID" quotet und du in deinem Code LanguagID ohne Quotes ausführst.

                    Kannst Du mal Deine Begriffe sortieren? Ich führe keine Spalten aus und PG erzeugt keine Quotes.

                    pgAdmin III erzeugt bei Deiner Arbeitsweise Identifier, die ein Quoten der Identifier im SQL notwendig machen. Letztlich brichst Du die Konvention / Regel, nur ungequotete Identifier zu benutzen.

                    Schreib Dir die Create-Table-Statements selbst und das Problem ist weg.

                      
                    CREATE TABLE test (  
                        LanguageID integer,  
                        foo integer,  
                        Bar integer,  
                        BAZ integer  
                    );  
                      
                    SELECT lAnGuAgEiD,fOO,bAr,baz FROM test;  
                    
                    

                    Keine Quotes, keine Probleme.

                    Alexander

                    --
                    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                    1. Hi Alex,

                      nochmals herzlichen Dank für deine Geduld.
                      ich weiss das sehr zu schätzen und das ist nicht selbstverständlich.
                      Jetzt ist mir das Ganze auch einiges klarer.
                      Ich dachte das die PG Datenbank Schuld ist an diesem automatischen quoten.
                      Das aber der pgAdmin ||| dies macht, dachte ich nicht.
                      Und bei meinen ersten Versuchen mit unterschiedlichen Migrations Wizards ist das dann vermutlich auch geschehen.

                      Schreib Dir die Create-Table-Statements selbst und das Problem ist weg.

                      CREATE TABLE test (
                          LanguageID integer,
                          foo integer,
                          Bar integer,
                          BAZ integer
                      );

                      SELECT lAnGuAgEiD,fOO,bAr,baz FROM test;

                      
                      >   
                      > Keine Quotes, keine Probleme.  
                        
                      Das werde ich ausprobieren und das ist sicher ein Weg. Mit einem Tool kann ich auch einen Dump erzeugen. Vielleicht kann ich dann auch hier die doppelten Anführungszeichen rausnehmen.  
                        
                      Nochmals danke.  
                        
                      vielen Dank und viele Grüße  
                      hawk
                      
        2. Hallo Alexander,

          Die andere Hälfte des Problems ist, dass Du PDO::CASE_XXX offenbar nicht kennst. (Am Rande: Perls DBI nennt das FetchHashKeyName.) Damit bekommst Du DB-unabhängig immer Bit für Bit die selben Spaltennamen.

          Ich habe das nun mal versucht mit

          // Set the case in which to return column_names.
          $DBO->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);

          Das ist doch dann aber nichts anderes, als wenn ich gleich alle Spaltennamen in Kleinbuchstaben schreibe.

          Und an der Problematik das meine ganzen Indentifier die ich in Groß-Kleinschreibweise habe und diese so nicht verwendet werden könne, ändert dies nichts.

          function ...{
          ...
          return $foundroot['MyDirectoryPath'];

          geht nicht.

          ich brauche entweder
          return $foundroot['mydirectorypath'];

          oder aber ich muss überall ein "strtolower()" davor setzen

          vielen Dank und viele Grüße
          hawk

          1. Moin Moin!

            Hallo Alexander,

            Die andere Hälfte des Problems ist, dass Du PDO::CASE_XXX offenbar nicht kennst. (Am Rande: Perls DBI nennt das FetchHashKeyName.) Damit bekommst Du DB-unabhängig immer Bit für Bit die selben Spaltennamen.

            Ich habe das nun mal versucht mit

            // Set the case in which to return column_names.
            $DBO->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);

            Das ist doch dann aber nichts anderes, als wenn ich gleich alle Spaltennamen in Kleinbuchstaben schreibe.

            Doch, das ist etwas anderes. Siehe https://forum.selfhtml.org/?t=203232&m=1374020.

            So wie ich die paar Doku-Fetzen verstehe, sorgt PDO::CASE_LOWER dafür, dass die bei Fetch zurückgegebenen Spaltennamen in Kleinbuchstaben umgesetzt werden. Daraus folgt, dass $foundroot['mydirectorypath'] existieren sollte, $foundroot['MyDirectoryPath'] aber nicht. Exakt das passiert jedenfalls, wenn ich FetchHashKeyName beim DBI auf 'NAME_lc' einstelle.

            Und an der Problematik das meine ganzen Indentifier die ich in Groß-Kleinschreibweise habe und diese so nicht verwendet werden könne, ändert dies nichts.

            Warum nicht? Du mußt einmal die Namen anpassen, dass läßt sich mit einem brauchbaren Editor in ein paar Minuten erschlagen. Danach kannst Du die Namensprobleme komplett vergessen, auch wenn Du auf die nächsten drei RDBMS umstellst.

            Alternativ dazu nutzt Du die PDO-Funktionalität, Objekte einer bestimmte Klasse zu erzeugen. Damit könntest Du entweder eine sehr einfache Klasse bauen, die alle Property-Namen case-insensitiv behandelt (siehe __get/__set/__isset/__unset), oder aber Du baust Dir für Deine Daten mehrere Klassen, die die Daten kapseln und über Methodenaufrufe zur Verfügung stellen. Ersteres erspart Dir Suchen-und-Ersetzen zu dem Preis, dass PHP zur Laufzeit mehr Arbeit hat und Dein System langsamer wird. Bei kleinen Datenmengen wird das nicht weiter stören, bei größeren Datenmengen wirst Du fluchen.

            function ...{
            ...
            return $foundroot['MyDirectoryPath'];

            geht nicht.

            "Geht nicht" kann eine treffende Fehlerbeschreibung für einen Laufroboter sein. Hier, wie auch generell, ist es keine sinnvolle Fehlerbeschreibung.

            ich brauche entweder
            return $foundroot['mydirectorypath'];

            oder aber ich muss überall ein "strtolower()" davor setzen

            Warum willst Du die WERTE in lower case umsetzen?

            Alexander

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            1. Hi Alexander,
              vielen Dank für deine Geduld und Ratschläge :-)

              Warum willst Du die WERTE in lower case umsetzen?

              Das will ich ja eigentlich nicht. Ich habe mich vermutlich nicht klar ausgedrückt.
              Momentan suche ich noch nach der besten Möglichkeit wie mein bisheriger Code auf unterschiedlichen DBs läuft.
              Angenommen ich mache das mit
              $DBO->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);

              oder aber ich wandle alle Identifier beim migrieren von MySQL nach PG in Kleinbuchstaben um.
              Wenn ich nun diese Funktion habe:

              function getDirectoryName($dirkeyname){
              global $DBO;
              $dbSelectDirectories = $DBO->prepare("SELECT DirectoryPath FROM ir_directory WHERE DirectoryKeyName = :dirkeyname");
              $dbSelectDirectories->bindParam(':dirkeyname', $dirkeyname);
              $dbSelectDirectories->execute();
              $found = $dbSelectDirectories->fetch(PDO::FETCH_ASSOC);
              return $found['DirectoryPath'];
              }//end function

              Dann ist der Return Wert leer, weil es diese Spalte in dieser Schreibweise nicht gibt. Ich muss also ändern in;
              $found['directorypath']

              Uund jetzt stellt sich mir halt die Frage was weniger Arbeit macht. Entweder ich lasse alles in der bisherigen Schreibweise mit "Groß- Kleinbuchstaben und maskiere die Spaltennamen mit Hochkomma "".
              Oder aber ich wandle alles in Kleinbuchstaben, was sicher Plattform übergreifend besser wäre. Hier aber hätte ich erheblich mehr Code. Ich habe zwar fast alle SQL Abfragen, Inserts und Updates in eine Datei ausgelagert. Die Spaltennamen aber kommen doch in nahezu allen PHP Dateien vor. Ich müsste also hunderte von Spaltennamen manuell suchen und ersetzen.

              vielen Dank und viele Grüße
              hawk

              1. Moin Moin!

                Hi Alexander,
                vielen Dank für deine Geduld und Ratschläge :-)

                Warum willst Du die WERTE in lower case umsetzen?

                Das will ich ja eigentlich nicht. Ich habe mich vermutlich nicht klar ausgedrückt.
                Momentan suche ich noch nach der besten Möglichkeit wie mein bisheriger Code auf unterschiedlichen DBs läuft.

                https://forum.selfhtml.org/?t=203232&m=1373823, https://forum.selfhtml.org/?t=203232&m=1374020

                Angenommen ich mache das mit
                $DBO->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);

                oder aber ich wandle alle Identifier beim migrieren von MySQL nach PG in Kleinbuchstaben um.
                Wenn ich nun diese Funktion habe:

                function getDirectoryName($dirkeyname){

                global $DBO;
                $dbSelectDirectories = $DBO->prepare("SELECT DirectoryPath FROM ir_directory WHERE DirectoryKeyName = :dirkeyname");
                $dbSelectDirectories->bindParam(':dirkeyname', $dirkeyname);
                $dbSelectDirectories->execute();
                $found = $dbSelectDirectories->fetch(PDO::FETCH_ASSOC);
                return $found['DirectoryPath'];
                }//end function

                
                >   
                > Dann ist der Return Wert leer, weil es diese Spalte in dieser Schreibweise nicht gibt. Ich muss also ändern in;  
                > `$found['directorypath']`{:.language-php}  
                  
                Nicht zwingend. Du kannst auch dafür sorgen, dass das $found eine Instanz einer Klasse mit case insensitiven Properties wird. Das geht über \_\_set / \_\_get / \_\_isset / \_\_unset und PDO::FETCH\_CLASS.  
                  
                Damit kannst Du die alten Namen beibehalten, PHP ruft die "magischen" Methoden auf und schreibt die Namen zur Laufzeit um (in lower oder upper case). Das bremst, wie sehr wird Dir ein Benchmark zeigen. Vermutlich wird der Umweg PHP nicht sonderlich viel Arbeit machen.  
                  
                
                > Uund jetzt stellt sich mir halt die Frage was weniger Arbeit macht. Entweder ich lasse alles in der bisherigen Schreibweise mit "Groß- Kleinbuchstaben und maskiere die Spaltennamen mit Hochkomma "".  
                  
                Und auf Dauer hast Du damit sehr viel Arbeit.  
                  
                
                > Oder aber ich wandle alles in Kleinbuchstaben, was sicher Plattform übergreifend besser wäre.  
                  
                Richtig.  
                  
                
                > Hier aber hätte ich erheblich mehr Code.  
                  
                Nö, wieso? Du änderst ein paar Bits im bestehenden Code von 0 auf 1 und hast damit alles in Kleinbuchstaben, alternativ änderst Du die Bits von 1 auf 0 und hast damit alles in Großbuchstaben. Der Code wird nicht ein Bit länger, abgesehen von den paar Zeichen, die einmalig PDO::CASE\_XXX setzen.  
                  
                
                > Ich habe zwar fast alle SQL Abfragen, Inserts und Updates in eine Datei ausgelagert. Die Spaltennamen aber kommen doch in nahezu allen PHP Dateien vor.  
                  
                Warum? Deine Beispielfunktion sorgt doch schon dafür, dass Du DirectoryPath nur ein einziges Mal ersetzen mußt. Es sei denn, Du nutzt sie nicht konsequent.  
                  
                
                > Ich müsste also hunderte von Spaltennamen manuell suchen und ersetzen.  
                  
                Nein, nicht manuell. Die DB kennst alle Spaltennamen. Baue eine Funktion, die Dir alle Deine Tabellen zusammensammelt. Baue eine Schleife, die für jede dieser Tabellen die Spaltennamen sammelt. Baue eine Funktion, die für jeden Spaltennamen in allen Quelltexten den Spaltennamen im mixed case sucht und durch lower case ersetzt -- nicht notwendigerweise sofort, sondern z.B. durch Erzeugen eines Hilfsscripts (z.B. mit find/xargs/sed).  
                  
                Alexander
                
                -- 
                Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".