Wie verwende ich in MySQL eine C++ Funkion?
-
mysql+c++ schrieb:
nixnutz schrieb:
Oder willst Du wirklich von einem in der MySQL ausgeführten SQL-Kommando auf ein C++-Programm zugreifen, um in diesem C++-Programm eine Aktion auszulösen?
Mein Problem ist bereits gelöst.
Mein erster Lösungsansatz war, aus einer Procedur (in MySQL) eine C++ Funktion aufzurufen. Das geht mit MySQL nicht (laut Unix-Tom) aber mit beispw. MSSQL geht das und macht auch Sinn.Du kannst den MySQL-Server beliebig erweitern. Beispielsweise über eine UDF, http://dev.mysql.com/doc/refman/5.1/en/adding-functions.html und http://dev.mysql.com/doc/refman/5.1/en/adding-udf.html . Die UDF ist eine C/C++ Funktion deiner Wahl.
mysql+c++ schrieb:
Verliere nicht das Ziel aus den Augen... das auflösen von einer Variable in MySQL!
Und wie passt da C++ ins Bild? Wo kommt denn der Wert für Variable her?
Wenn Du ausschließlich mit SQL arbeiten willst, dann hast Du ja gefunden wie Du in der MySQL auf der SQL-Ebene mit SET eine Variable definierst und über den Umweg von Prepared Statements auch auf der SQL-Ebene in einem SQL-Kommando verwendest.
Ulf
-
Das man den MySQL-Server beliebig erweitern kann, habe ich damals auch gefunden. Aber für meinen Anwendungszweck total umständlich und den Aufwand nicht wert.
Woher die Werte kommen habe ich eigentlich auch schon gesagt:
mysql+c++ schrieb:
Meine Log-Tabelle liefert nicht nur Tabellenname sondern auch Spaltenname, Werte usw.
C++ passte damals so ins Bild das es die Select Anweisung als Zeichenkette + Variable übergeben bekommt und dann die komplette SQL-Anweisung als Zeichenkette zurückgibt.
Also so hier:cpp_function( "Select * from ", variable_fuer_tabelle );
In c++ würde die Funktion so aussehen:
std::string cpp_function ( std::string sql1, std::string sql2 ) { return sql1 + sql2; }
Wie ich dann die Zeichenkette ausführen wollte, war dann der nächste zu überlegende Schritt. Beziehungsweise habe ich mir damals überhaupt keine Gedanken gemacht. Aber nun habe ich das ohne Umwege geschafft. Warum ohne Umwege? Siehe dazu:
http://de.wikipedia.org/wiki/Prepared_StatementSelbst wenn das mit C++ funktioniert hätte, hätte ich dennoch die Zeichenkette mit PREPARE und EXECUTE verwenden müssen. Die Schwächen meines Lösungsansatzes sind mir im Nachhinein klar geworden. (Das Bedeutet aber nicht das es Sinnlos ist von MySQL auf C++-Funktion zuzugreifen!)
Das Stichwort von 'hustbaer': "dynamic SQL" ist hier entscheidend!
Aber das habe ich schon alles selber herausbekommenProblematik verstanden?
-
@mysql+c++:
Ich hab aber auch erst nach deinem "CONCAT/PREPARE/EXECUTE" Posting verstanden was du eigentlich willst.
Die AussageIch verstehe die ursprüngliche Frage nicht. Den Antworten nach zu urteilen geht es anderen nicht viel besser.
kann ich also unterschreiben.
Lern dich besser auszudrücken. Und vor allem: beschreibe was du machen möchtest, nicht wie du es angehen willst.
Das ist auch einer der Gründe, warum immer wieder und wieder die Antwort "das macht keinen Sinn" kommt: weil Leute ihren halbgaren Lösungsansatz beschreiben, für ein Problem dass sie oft nicht ausreichend verstehen, ohne dabei aber das Problem zu beschreiben.
Ich gebe dir zwar Recht wenn du schreibst dass es öd ist wenn Leute kein Feedback geben.
Was die restlichen Dinge angeht eher nicht.
-
mysql+c++ schrieb:
Das man den MySQL-Server beliebig erweitern kann, habe ich damals auch gefunden. Aber für meinen Anwendungszweck total umständlich und den Aufwand nicht wert.
Naja, und das hat mich auch aus der Bahn geworfen: was macht er da...
mysql+c++ schrieb:
Woher die Werte kommen habe ich eigentlich auch schon gesagt:
mysql+c++ schrieb:
Meine Log-Tabelle liefert nicht nur Tabellenname sondern auch Spaltenname, Werte usw.
Hmm, was mir dabei nicht klar war ist, ob Du auf der SQL-Ebene im Datenbankserver etwas erreichen möchtest oder...
mysql+c++ schrieb:
C++ passte damals so ins Bild das es die Select Anweisung als Zeichenkette + Variable übergeben bekommt und dann die komplette SQL-Anweisung als Zeichenkette zurückgibt.
Also so hier:cpp_function( "Select * from ", variable_fuer_tabelle );
innerhalb einer Anwendung, innerhalb eines Clients.
mysql+c++ schrieb:
In c++ würde die Funktion so aussehen:
std::string cpp_function ( std::string sql1, std::string sql2 ) { return sql1 + sql2; }
Wie ich dann die Zeichenkette ausführen wollte, war dann der nächste zu überlegende Schritt.
Da passt die Antwort rein, daß Du den MySQL Connector/C++ verwenden könntest. Oder MySQL++ oder die C-API mit "etwas" Casting.
mysql+c++ schrieb:
Beziehungsweise habe ich mir damals überhaupt keine Gedanken gemacht. Aber nun habe ich das ohne Umwege geschafft. Warum ohne Umwege? Siehe dazu:
http://de.wikipedia.org/wiki/Prepared_StatementSelbst wenn das mit C++ funktioniert hätte, hätte ich dennoch die Zeichenkette mit PREPARE und EXECUTE verwenden müssen.
Stop - ich komme nicht mit. Springst Du hier zwischen Client und Server hin und her? Laß mich versuchen, dein Problem mit meinen Worten zu wiederholen.
Du hast irgendwo in der Datenbank eine Tabelle, nenne sie "Log". Diese Tabelle "Log" enthält Spalten in denen der Name anderer Tabellen enthalten ist. Beispielsweise steht in der Tabelle "Log":
id wert1 name_anderer_tabelle
1 100 "tabelle2"
2 24 "tabelle3"Du möchtest die Tabelle "Log" auslesen und die gefundenen Werte verwenden, um Anfragen an die in der Tabelle "Log" in der Spalte "name_anderer_tabelle" gespeicherten Tabellen zu stellen.
Es sind also folgende Schritte auszuführen:
- Lese "Log" aus
- Erstelle neue Anfrage aus Werten von "Log"
- Sende neue Anfrage
Wenn ich diese Aufgabe lösen sollte, dann würde ich entweder ein Clientprogramm schreiben, welches die gewünschte Operation ausführt oder ich belasse die Logik auf dem Server, auf der SQL-Ebene, beispielsweise in einer Stored Procedure.
Mit anderen Worten: ich mache 1-3 entweder komplett auf dem Client oder komplett auf dem Server. Jetzt dämmert mir langsam, daß Du alles auf dem Server machen wolltest, aber weil Dir ein kleines Stückchen fehlte (CONCAT, dynamic SQL), Du nach 1) für 2) auf den Client wechseln wolltest.
Mir würde es nie in den Sinn kommen hier zu mixen und einen Wechsel der Ausführungsebene vorzunehmen. Mit wäre es viel zu "teuer", einen Kontextwechsel zu vollziehen. Ich möchte nicht wissen wie rechenintensiv es ist externes Programm aufzurufen und dies einen Teil der Arbeit übernehmen zu lassen. Selbst wenn der Programmstart "billig" ist, beispielsweise, weil die MySQL UDF in den MySQL Server einkompiliert ist, erfolgt immer noch ein Kontextwechsel in einen Benutzer-Bereich (UDF = *user* defined function), also in einen Bereich dem ich als Datenbank nicht vertrauen darf.
Zudem würde ich mich zwei Mal fragen ob ich Logik an zwei Stellen ablegen will, weil dies bedeutet, daß ich zwei Stellen warten muss. Die Vorstellung, daß das jemand machen will hat bei mir ausgelöst.
mysql+c++ schrieb:
Beziehungsweise habe ich mir damals überhaupt keine Gedanken gemacht. Aber nun habe ich das ohne Umwege geschafft. Warum ohne Umwege? Siehe dazu:
http://de.wikipedia.org/wiki/Prepared_StatementSelbst wenn das mit C++ funktioniert hätte, hätte ich dennoch die Zeichenkette mit PREPARE und EXECUTE verwenden müssen.
Das bezieht sich wieder auf die Situation in der Du einen Teil von 1-3 auf dem Client machst und einen Teil davon auf dem Server. Was Du schreibst ist richtig, wenn Du die Konkatenation (das Verbinden) der Zeichenketten - 2) - auf dem Client machst und den Rest auf dem Server.
Wenn Du alle Schritte auf dem Client machst, dann ist es nicht zwingend notwendig Prepared Statements zu benutzen. Bei Ausführung aller Schritte auf dem Client, kannst Du auch ein "normales" Statement verwenden.
<code>
[...]
stmt = con->createStatement();
stmt->execute("USE " EXAMPLE_DB);
[...]
</code>
http://dev.mysql.com/doc/refman/6.0/en/connector-cpp-examples-query.htmlDas SQL-Kommando, welches Du derartig an den Server sendest, sollte selbstverständlich gültig sein, damit es tut was Du willst. Gegebenenfalls sind die Zeichenketten, die im SQL-Kommando verwendet werden zu escapen. "Schadhafte" Zeichenketten, die im Extremfall SQL-Injection ermöglichen, sind von Dir zu entfernen. Die Datenbank wird genau das ausführen, was Du ihr sagst. Wenn Du ihr ein defektes SQL-Kommando sendet, wird die Antwort von MySQL entsprechend ausfallen.
Bei der Verwendung von Prepared Statements in einer rein client-basierten Lösung ist weiter zu differenzieren: arbeitet der Client mit einer Prepared-Statement Emulation oder verwendet er die Prepared Statements des MySQL-Server, verwendest Du die Client-API für Prepared Statements oder die SQL-Syntax mit PREPARE und EXECUTE.
- Client-basierte Lösung, Prepared Statements (PS) des MySQL-Servers, PS mittels API
<code>
prep_stmt = con->prepareStatement("INSERT INTO test(id, label) VALUES (?, ?)");prep_stmt->setInt(1, 1);
prep_stmt->setString(2, "a");
prep_stmt->execute();
</code>
http://dev.mysql.com/doc/refman/6.0/en/connector-cpp-examples-prepared-statements.htmlHarken für deine Aufgabenstellung: Du kannst keinen Tabellennamen binden. Prepared Statements trennen variable Werte von gleichbleibenden SQL-Kommandos. Sie parametrisieren SQL-Kommandos.
- Client-basierte Lösung, Prepared Statement Emulation, PS mittels API
Andere Programmiersprache, aber egal für die Grundsatzdiskussion:
http:://php.net/pdoPDO kann Prepared Statements emulieren, um diese über eine formalisierte API bereitzustellen. Die Emulation erstellt SQL auf dem Client, für Dich unsichtbar, und führt ein ordnungsgemäßes escapen der Werte durch. Es wird ein normales Statement ausgeführt. Das ist im Prinzip wie http://dev.mysql.com/doc/refman/6.0/en/connector-cpp-examples-query.html (siehe oben), nur daß in der Emulation ordentlich escaped wird, um SQL-Injection zu unterbinden.
- Client-basierte Lösung, PREPARE und EXECUTE
Es löst deine Aufgabe - mehr nicht. Wenn es keinen triftigen Grund gibt, diese Variante zu wählen verzichtest Du auf das, wonach 99% der PS-Anwender lechtzen: Trennung von (potentiell vergifteten) Daten und SQL-Kommando auf der Leitung, um die Aufgabe des Bereinigens der Daten zu verlagern und ggf. Verringerung des Netzwerktraffics, der entsteht wenn bei wiederholter Ausführung nur die Daten und nicht das Kommando ausgeführt wird.
Kurz: bei einer ausschließlich client-basierten Lösung des Problems ist es nicht zwingend notwendig Prepared Statements zu verwenden. Schon gar nicht bist Du gezwungen PREPARE/EXECUTE einzusetzen. Es ist eine Möglichkeit von vielen.
mysql+c++ schrieb:
Beziehungsweise habe ich mir damals überhaupt keine Gedanken gemacht. Aber nun habe ich das ohne Umwege geschafft. Warum ohne Umwege? Siehe dazu:
http://de.wikipedia.org/wiki/Prepared_StatementSelbst wenn das mit C++ funktioniert hätte, hätte ich dennoch die Zeichenkette mit PREPARE und EXECUTE verwenden müssen.
Die Verwendung eines Prepared Statements siehst Du nicht als Umweg an, weil Du damit deine rein server-basierte Lösung bekommst. Über die Krücke der Prepared Statements baust Du Dir Dynamic SQL im MySQL Server. Das ist Dreck ! Wer Prepared Statements nur verwendet, um damit Dynamic SQL zu relalisieren sollte sich darüber im Klaren sein, daß er sie vergewaltigt. Bevor Du wieder einen Anfall bekommst: bis heute gibt es keine andere Möglichkeit eine rein server-basierte (ohne UDF) Lösung für dein Problem zu erstellen.
Was Du eigentlich willst ist EXECUTE IMMEDIATE:
http://forge.mysql.com/worklog/task.php?id=2793Prepared Statements sind dazu da, um SQL-Kommandos zu parametrisieren. Sie trennen das eigentliche Kommando von seinen Daten. Das kann genutzt werden, um die Netzwerklast zu reduzieren, als Tipp an die Datenbank mehr Zeit für die Ausarbeitung eines Ausführungsplans zu investieren, weil mit mehrfacher Ausführung zu rechnen ist, als Ausrede seine Eingabedaten nicht bereinigen zu müssen, weil ja der Parser der Datenbank die Arbeit viel besser erledigen könne und, und, und.
Bis hin zum MySQL spezifischen Effekt, daß ein anderes Kommunikationsprotokoll zwischen Client und Server zum Einsatz kommt, welches mal weniger mal mehr Traffic beim Senden von Resultsets zum Client bewirkt (binary vs. text protocol) und mal mehr mal weniger CPU-Zeit auf dem Server verbrät (Stichwort: string casts).
mysql+c++ schrieb:
Problematik verstanden?
Und, hast Du auch verstanden was Du da vorhattest und was Du jetzt machst, um Dir Dynamic SQL innerhalb einer rein server-basierten Lösung zu basteln.
Ulf
-
hustbaer schrieb:
Ich hab aber auch erst nach deinem "CONCAT/PREPARE/EXECUTE" Posting verstanden was du eigentlich willst.
Kann ja sein .. das du es später verstanden hast. Aber das geht absolut nicht von den Antworten heraus (nicht nur deine). Also das es den anderen auch so geht ist dementsprechend falsch und kann nicht unterschrieben werden. Er hätte sagen sollen das es es nicht versteht und Punkt.
hustbaer schrieb:
Lern dich besser auszudrücken. Und vor allem: beschreibe was du machen möchtest, nicht wie du es angehen willst.
Jeder muss dazu lernen .. da bin ich keine Ausnahme. Ich weiß ja selber das ich in dem Bezug schwächen habe. Aber dennoch habe ich im ersten Beitrag beschrieben was ich eigentlich machen möchte und mein Lösungsansatz war nur die hälfte vom Beitrag:
mysql+c++ schrieb:
Was ich zu lösen versuche ist das auflösen von Variablen in SQL-Anweisungen.
Genauer:
SELECT * FROM variable_fuer_eine_tabelle;Da MySQL nicht die Variable auflöst und nachschaut was sich hinter "variable_fuer_eine_tabelle" verbirgt, bin ich gezwungen das ganze auszulagern. Die SQL-Anweisung einem C++ Programm übergeben und die komplette aufgelöste Zeichenkette zurückzubekommen, ist das Ziel.
hustbaer schrieb:
Das ist auch einer der Gründe, warum immer wieder und wieder die Antwort "das macht keinen Sinn" kommt: weil Leute ihren halbgaren Lösungsansatz beschreiben, für ein Problem dass sie oft nicht ausreichend verstehen, ohne dabei aber das Problem zu beschreiben.
Zu Thema Sinn oder Unsinn habe ich schon dazu was gesagt. Die Leute stehen einfach nicht in der Position das zu entscheiden. Schon gar nicht wenn sie es nicht verstehen. Wieso soll man in der Position sein, zu sagen 'es macht kein Sinn' ohne das eigentliche Problem zu kennen .. weil der Autor selber das ungenügend beschreibt. Dazu habe ich auch schon das PS geschrieben:
mysql+c++ schrieb:
PS: Viele Leute spielen sich als die großen Macker, wenn die auf ein Beitrag antworten. Es stimmt schon das viele Thread-Autoren unerfahren und ungenau sind. Aber das gibt ihn nicht das Recht darüber zur urteilen, ob es Sinn macht oder nicht. Und das sowieso.. wenn man die Frage nicht Verstanden hat oder der Autor selber die Frage ungenau geschrieben hat. Stattdessen sollte man Fragen 'was derjenige genau machen möchte, eventuell gibt es ja auch einen anderen Lösungsweg'.
Es kann und darf nicht darüber gerichtet werden ob es Sinn macht. Denn der Thread-Autor hat sich ja etwas dabei gedacht um sein Problem zu lösen. Das sein Lösungsansatz falsch ist, ist natürlich möglich. Aber das kann man nur herausbekommen wenn man die oben genannte Frage stehlt und sich weiter darüber unterhält.
Das wollte ich nur mal gesagt haben!Und keiner hat über das eigentliche Problem unterhalten.
Da du jetzt mittlerweile alles verstanden hast und immer noch der Meinung bist das ich den ersten Beitrag ungenügend beschrieben habe. Dann kannst du mal die Frage selber Formulieren .. ich muss ja auch dazu lernen. Schreibe einfach wie du es gemacht hättest. Natürlich musst du meinen Lösungsansatz mit einbauen bzw. vorschlagen.
-
dein Fehler war, dass du dein Problem falsch beschrieben hast... so hat man es auch falsch verstanden und den Sinn nicht entdeckt... ich dachte bei deinem ersten Posting, du willst aus SQL heraus C++-Funktionen aufrufen... und das macht wirklich keinen Sinn... und ja, einige hier sind durchaus in der Lage, den Sinn einer Sache anzuzweifeln auch wenn der Fragesteller von der Sinnhaftigkeit überzeugt ist... nennt man gemeinhin "Erfahrung"
Hättest du einfach geschrieben, du willst wissen, wie man Variablen in SQL-Anweisungen verwendet wär die Sache deutlich klarer gewesen...
-
zwutz schrieb:
ich dachte bei deinem ersten Posting, du willst aus SQL heraus C++-Funktionen aufrufen... und das macht wirklich keinen Sinn...
Das ist auch das was ich ursprünglich wollte. Also habe ich mich richtig ausgedrückt. Und das macht SINN! Noch nie einen eigenen Passwort-Algorithmus geschrieben? Das ist ein sehr bekanntes Beispiel .. das die Passwörter mit einen eigenen Algorithmus verschlüsselt und in die Datenbank gespeichert werden (und nicht unbedingt vorher verschlüsselt werden, den dieser Anwendungsfall ist nicht immer möglich).
zwutz schrieb:
und ja, einige hier sind durchaus in der Lage, den Sinn einer Sache anzuzweifeln auch wenn der Fragesteller von der Sinnhaftigkeit überzeugt ist... nennt man gemeinhin "Erfahrung"
Erfahrung hin oder her ... es geht einfach nicht. Denn man zweifelt über das was man verstanden hat ... und man hat einfach nicht das verstanden was der Fragesteller gemeint hat. Aus diesem Grund sollte man Fragen bevor man voreilige Schlüsse zieht. Das ist genau wie mit Vorurteile .. als würde ich meinen Kindern erklären das man das nicht machen sollte. Nicht erst losschießen und dann sich darüber Unterhalten. Sondern davor! Das ist ein Grundsatz den jeder einhalten sollte.
Den Fragesteller nützt es über nichts wenn einer sagt es macht kein Sinn. Es sollte lieber entgegenkommen und fragen. Die Frage habe ich schon so oft zitiert:
'was derjenige genau machen möchte, eventuell gibt es ja auch einen anderen Lösungsweg'.zwutz schrieb:
Hättest du einfach geschrieben, du willst wissen, wie man Variablen in SQL-Anweisungen verwendet wär die Sache deutlich klarer gewesen...
Ich habe geschrieben, das ich wissen will wie ich eine Variable auflöse und das ist ja 'verwenden'. Damit ist alles klar.
-
@nixnutz: upps, hab dein Beitrag übersehen. Da ich zu der zeit meinen eigenen Beitrag geschrieben habe :). Werde demnächst darauf antworten, erstmal muss das Essen vorbereitet werden. Dann gegessen usw.
-
@nixnutz:
Ich wollte und möchte immer noch alles auf der SQL-Ebene erledigen.
Um das mit deine Übersicht zu erklären:- Lese "Log" aus
- Erstelle neue Anfrage aus Werten von "Log"
- Sende neue Anfrage
Der Gedanke war so (das geschieht alles aus einer Stored Procedures):
1. auf SQL
2. mittels C++ Funktion, da ich die Variablen nicht auflösen konnte.
3. auf dem SQL in der ProzedurEin Client wird also nicht gebraucht.
nixnutz schrieb:
Da passt die Antwort rein, daß Du den MySQL Connector/C++ verwenden könntest. Oder MySQL++ oder die C-API mit "etwas" Casting.
Achso. Das ist der Grund warum mir das angeboten wurde. Dadurch wurde aber leider ein schritt übersprungen und dadurch wird mein Problem nicht gelöst. Vor allem weil ich auch noch das Ergebnis der SQL-Anweisung brauche.
nixnutz schrieb:
Mit anderen Worten: ich mache 1-3 entweder komplett auf dem Client oder komplett auf dem Server. Jetzt dämmert mir langsam, daß Du alles auf dem Server machen wolltest, aber weil Dir ein kleines Stückchen fehlte (CONCAT, dynamic SQL), Du nach 1) für 2) auf den Client wechseln wolltest.
Genau .. ich wollte alles auf dem Server machen. Da ich aber das ganze nicht auflösen konnte wollte ich die Auflösung c++ überlassen, aber ich wollte dennoch die SQL-Anweisung auf der SQL-Ebene ausführen. Zu dieser Zeit habe ich mir aber über das wie noch keine Gedanken gemacht. Da ja noch ein Problem davor stand.
nixnutz schrieb:
Die Verwendung eines Prepared Statements siehst Du nicht als Umweg an, weil Du damit deine rein server-basierte Lösung bekommst. Über die Krücke der Prepared Statements baust Du Dir Dynamic SQL im MySQL Server. Das ist Dreck ! Wer Prepared Statements nur verwendet, um damit Dynamic SQL zu relalisieren sollte sich darüber im Klaren sein, daß er sie vergewaltigt. Bevor Du wieder einen Anfall bekommst: bis heute gibt es keine andere Möglichkeit eine rein server-basierte (ohne UDF) Lösung für dein Problem zu erstellen.
Was würdest du Vorschlagen? Es gibt doch keine andere Möglichkeit. Also muss ich den Geschwindigkeitsnachteil hinnehmen, oder etwa nicht?
nixnutz schrieb:
Was Du eigentlich willst ist EXECUTE IMMEDIATE:
EXECUTE IMMEDIATE kann doch nicht in Stored Procedures verwendet werden .. ? Also kann ich das auch verwenden, oder etwa doch?
nixnutz schrieb:
Und, hast Du auch verstanden was Du da vorhattest und was Du jetzt machst, um Dir Dynamic SQL innerhalb einer rein server-basierten Lösung zu basteln.
Ich glaube im Prinzip habe ich das verstanden. Einige Sachen sind bestimmt noch nicht ganz verinnerlicht ..
nixnutz schrieb:
Wenn Du alle Schritte auf dem Client machst, dann ist es nicht zwingend notwendig Prepared Statements zu benutzen. Bei Ausführung aller Schritte auf dem Client, kannst Du auch ein "normales" Statement verwenden.
Hier meinst du sicherlich "Beim Ausführen aller Schritte auf dem Server ..." ..?
Ich mach ja auch alles auf dem Server ein Escapen ist nur bei Werten notwendig.PS: Ich weiß, von wegen 'Am Nachmittag werde ich antworten'! Immer diese leeren Versprechungen ...
-
Beschreib einfach das, was du ursprünglich lösen willst, und nicht eine Idee die du hattest wie man es vielleicht lösen könnte. Speziell wenn diese Idee recht seltsam ("eigenwillig"), und noch dazu undurchführbar ist, werden die Leute reichlich verwirrt sein, und u.U. nicht wissen können was du eigentlich wolltest.
BTW: zu behaupten dass dich die meisten schon richtig verstanden haben bringt dich nicht weiter. Offensichtlich hast du in deiner Fragestellung etwas gröber falsch gemacht, denn die Sache die du eigentlich beantwortet haben wolltest ist so einfach, dass in kürzester Zeit eine passende Antwort hätte kommen müssen.
-
mysql+c++ schrieb:
@nixnutz:
Ich wollte und möchte immer noch alles auf der SQL-Ebene erledigen.Ja, das habe ich inzwischen kapiert.
mysql+c++ schrieb:
Um das mit deine Übersicht zu erklären:
- Lese "Log" aus
- Erstelle neue Anfrage aus Werten von "Log"
- Sende neue Anfrage
Der Gedanke war so (das geschieht alles aus einer Stored Procedures):
1. auf SQL
2. mittels C++ Funktion, da ich die Variablen nicht auflösen konnte.
3. auf dem SQL in der ProzedurEin Client wird also nicht gebraucht.
Hmm, ja... Die C++-Funktion muß ja auch irgendwo liegen. Selbst wenn sie durch den Server bereitgestellt wird, muß der Server aus dem SQL-Kontext in den Kontext einer externen C++-Funktion wechseln und das dürfte "teuer" sein.
mysql+c++ schrieb:
nixnutz schrieb:
Die Verwendung eines Prepared Statements siehst Du nicht als Umweg an, weil Du damit deine rein server-basierte Lösung bekommst. Über die Krücke der Prepared Statements baust Du Dir Dynamic SQL im MySQL Server. Das ist Dreck ! Wer Prepared Statements nur verwendet, um damit Dynamic SQL zu relalisieren sollte sich darüber im Klaren sein, daß er sie vergewaltigt. Bevor Du wieder einen Anfall bekommst: bis heute gibt es keine andere Möglichkeit eine rein server-basierte (ohne UDF) Lösung für dein Problem zu erstellen.
Was würdest du Vorschlagen? Es gibt doch keine andere Möglichkeit. Also muss
ich den Geschwindigkeitsnachteil hinnehmen, oder etwa nicht?Du willst Dynamic SQL. Stand heute geht das nur über den Umweg PREPARE + EXECUTE, weil MySQL dir bislang keinen Ausdruck anbietet mit dem Du in einem Schritt Dynamic SQL bekommst. Das große Warten auf EXECUTE IMMEDIATE...
Alles was ich sagen will ist, daß man Dynamic SQL nicht grundsätzlich mit Prepared Statements verbinden muss. Daß Du PS benutzen musst bei MySQL, halte ich für einen MySQL-spezifischen Hack. PS an sich haben nichts mit Dynamic SQL zu tun.
Wie die Performance von einem zukünftigen EXECUTE IMMEDIATE mit im Vergleich zu der des aktuell notwendigen PREPARE + EXECUTE "Hacks" ausfallen wird, mag ich nicht zu beurteilen. Ich bin kein Hellseher.
Vielleicht einer der größten Pferdefüsse bei PS mit Stand heute ist, daß PS natürlich Ressourcen allokieren (und blockieren) und die lieben Benutzer gerne vergessen die belegten Ressourcen so schnell wie möglich freizugeben, weil die Freigabe ja sowieso irgendwann implizit von der Datenbank gemacht wird...
mysql+c++ schrieb:
nixnutz schrieb:
Was Du eigentlich willst ist EXECUTE IMMEDIATE:
EXECUTE IMMEDIATE kann doch nicht in Stored Procedures verwendet werden .. ? Also kann ich das auch verwenden, oder etwa doch?
http://forge.mysql.com/worklog/task.php?id=2793 , erster Satz:
"Introduce a convenient syntax for Dynamic SQL in stored procedures:"Status des geplanten Features: "Affects: Server-6.x — Status: In-Design — Priority: Medium"
mysql+c++ schrieb:
nixnutz schrieb:
Wenn Du alle Schritte auf dem Client machst, dann ist es nicht zwingend notwendig Prepared Statements zu benutzen. Bei Ausführung aller Schritte auf dem Client, kannst Du auch ein "normales" Statement verwenden.
Hier meinst du sicherlich "Beim Ausführen aller Schritte auf dem Server ..." ..?
Nein. Übertrage das Beispiel vom letzten Posting mit '"USE " EXAMPLE_DB' auf 2) und Du hast es.
mysql+c++ schrieb:
Ich mach ja auch alles auf dem Server ein Escapen ist nur bei Werten notwendig.
Es kommt darauf an. Grundsätzlich bist Du als Entwickler dafür zuständig Eingabedaten zu bereinigen, damit kein Unfug passiert. Wenn Du mit Prepared Statements arbeitest und Du entweder eine PS-API verwendet, die direkt auf die PS von MySQL zurückgeht (keine Emulation!) oder Du auf der SQL-Ebene im Server bleibst brauchst Du Werte nicht zu escapen, weil dies implizit gemacht wird.
Du musst die Fälle wieder aufspalten, am Ende ist auch dein Fall aufgeführt:
a) Client-Applikation (MULTI_STATEMENT-Option aktiviert) ohne Prepared Statements
meindatum = "; DELETE FROM t1; ";
meinsql = "SELECT * FROM TABLE t1" + [meindatum] + "WHERE t1.c1 = 1"
--> SQL-Injection bei Ausführungb) Client-Applikation (MULTI_STATEMENT-Option deaktiviert = VOREINSTELLUNG(!)) ohne Prepared Statements
meindatum = "; DELETE FROM t1; ";
meinsql = "SELECT * FROM TABLE t1" + [meindatum] + "WHERE t1.c1 = 1"
--> Syntaxfehler bei Ausführungc) Client Applikation mit Prepared Statements über API:
meinsql = "SELECT * FROM TABLE t1 ? WHERE t1.c1 = 1"
--> Syntaxfehler beim Vorbereitenmeindatum = ", t2";
meinsql = "SELECT * FROM TABLE t1 " + meindatum + " WHERE t1.c1 = ?"
---> Syntax gültig, lässt sich vorbereiten
---> bind(1, "mein_; DROP TABLE t1;")
---> Ausführung klappt, weil dank PS-API implizit escaped wurde, keine Injectiond) Dein Fall, Stored Procedure mit Prepared Statement für Dynamic SQL
Es ist deine Aufgabe Eingabedaten zu bereinigen! Das wird Dir natürlich nie passieren...
SET @meindatum = ", geheime_spalte";
SET @meinsql = CONCAT("SELECT c1 ", @meindatum, " FROM t1");
PREPARE stmt1 FROM @meinsql;
EXECUTE stmt1;... und das natürlich auch nicht, weil...
CREATE TABLE t2(c1 VARCHAR(64));
INSERT INTO t2(c1) VALUES (", geheime_spalte");
SELECT c1 FROM t2 INTO @meindatum;
SET @meinsql = CONCAT("SELECT c1 ", @meindatum, " FROM t1");
PREPARE stmt1 FROM @meinsql ;
EXECUTE stmt1;... Du selbstverständlich darauf achtest keinem Eingabedatum zu vertrauen - auch nicht dem aus deiner Tabelle t2 - und Du sofort reagieren würdest.
Aber das schweift ab, Deine Frage bezog sich auf das Escapen:
CREATE TABLE t1(c1 INT, c2 CHAR(1))
INSERT INTO t1(c1, c2) VALUES (1, "a");
PREPARE stmt1 FROM "SELECT * FROM t1 WHERE c2 = ?";SET @meindatum = "a";
EXECUTE stmt1 USING @meindatum -> ErgebnisSET @meindatum = '"a"';
EXECUTE stmt USING @meindatum -> kein Ergebnis (korrekt)SET @meindatum = '"a"; DELETE FROM t1'
EXECUTE stmt USING @meindatum -> kein Ergebnis (korrekt)Warum ergebene die letzten beiden weder einen Fehler noch eine SQL-Injection? Weil die Datenbank weiß, daß Du Werte einfügen willst und schlau genug ist das notwendige "escaping" implizit zu machen, damit keine Probleme auftreten.
Ulf
-
Jo, Parameter verwenden ist natürlich viel besser als Strings escapen.
-
@hustbaer: geht klar das werde ich berücksichtigen
@nixnutz:nixnutz schrieb:
Es kommt darauf an. Grundsätzlich bist Du als Entwickler dafür zuständig Eingabedaten zu bereinigen, damit kein Unfug passiert. Wenn Du mit Prepared Statements arbeitest und Du entweder eine PS-API verwendet, die direkt auf die PS von MySQL zurückgeht (keine Emulation!) oder Du auf der SQL-Ebene im Server bleibst brauchst Du Werte nicht zu escapen, weil dies implizit gemacht wird.
Ja. Bei meiner Log Tabelle wurde beim Eintragen jetzt alles überprüft. Solche extreme wie "DROP table1" gibt es bei mir sowieso nicht und kann es auch nicht geben.
nixnutz schrieb:
Nein. Übertrage das Beispiel vom letzten Posting mit '"USE " EXAMPLE_DB' auf 2) und Du hast es.
geht klar.
Da wir gerade dabei sind. Ich hänge gerade an einem anderen Problem. Was aber sehr ähnlich ist. Erstmal ein paar Worte im Voraus:
Ich habe ja eine Log-Tabelle ... die wird mit Hilfe von Triggern gefüllt. Nun möchte ich die Trigger mit einer Prozedur erstellen. Wie ist das am besten zu realisieren? Einen Ansatz lass ich jetzt einfach mal weg.
-
Wenn du mit "Prozedur" eine "stored procedure" meinst, dann kommt IMO auch nur dynamic SQL in Frage. Weil vermutlich ein Teil der hier variabel sein muss der Prozedur-Name ist, und den kann man auch nicht als "?-Parameter" übergeben.
-
hustbaer schrieb:
Wenn du mit "Prozedur" eine "stored procedure" meinst, dann kommt IMO auch nur dynamic SQL in Frage.
Ja meine ich. Es soll auch wieder alles auf der SQL-Ebene geschehen.
hustbaer schrieb:
Weil vermutlich ein Teil der hier variabel sein muss der Prozedur-Name ist, und den kann man auch nicht als "?-Parameter" übergeben.
Ich habe eine einzige Prozedur die den SQL Befehl zusammenstellt. Hier zu Info noch:
Ja, ein Teil ist wieder Variable. Aber wenn ich Prepare Statement benutze, dann kommt die Meldung: "This command is not supported in the prepared statement protocol yet"
-
Er. Ich meinte natürlich der Trigger-Name wird wohl variabel sein müssen (nicht der Name der stored procedure), sorry
-
hustbaer schrieb:
Er. Ich meinte natürlich der Trigger-Name wird wohl variabel sein müssen (nicht der Name der stored procedure), sorry
Genau .. der Trigger-Name wird aus Präfix + Tabellen-Name erstellt. Bezugsquelle ist hier auch INFORMATION_SCHEMA.
Hast du eine Idee wie das gemacht werden könnte? Den Namen und SQL-Befehl habe ich schon fertig. Nur das abfeuern fehlt.
-
mysql+c++ schrieb:
hustbaer schrieb:
Er. Ich meinte natürlich der Trigger-Name wird wohl variabel sein müssen (nicht der Name der stored procedure), sorry
Genau .. der Trigger-Name wird aus Präfix + Tabellen-Name erstellt. Bezugsquelle ist hier auch INFORMATION_SCHEMA.
Hast du eine Idee wie das gemacht werden könnte? Den Namen und SQL-Befehl habe ich schon fertig. Nur das abfeuern fehlt.Nö.
MySQL unterstützt dynamic SQL anscheinend nicht wirklich. Zumindest hab' ich nixe zu dem Thema gefunden, ausser eben die prepared statements. Kenne mich mit MySQL auch nicht so toll aus. Nimm SQL Server Express
-
hustbaer schrieb:
Nö.
MySQL unterstützt dynamic SQL anscheinend nicht wirklich. Zumindest hab' ich nixe zu dem Thema gefunden, ausser eben die prepared statements. Kenne mich mit MySQL auch nicht so toll aus. Nimm SQL Server ExpressHehe .. nimm einfach eine andere Datenbank ist einfach gesagt.