Gibt es eine Alternative zu SQL Strings im Prorammcode?

Alibi086

Mitglied
Hi Folks !

Ich habe mal eine Fragean euch. Gibt es eigentlich eine Möglichkeit, diese SQL String zu umgehen und das irgendwie anders in seinem Programmcode umzusetzen bzw. sind diese SQL Strings überhaupt eine gute Wahl, oder sollte man sie vermeiden? Hier ein Beispiel:

Code:
Dim strSql as String

strSql = "SELECT tab1.FeldA, tab2.FeldA, tab2.FeldB " & _
         "FROM tab1 INNER JOIN tab2 " & _
         "ON tab1.FeldX = tab2.FeldX"

Der Syntax ist hier VB. Wie ist so etwas zu bewerten und sollte man das evtl. anders gestalten?

Greetz
Felix
 
M

maki

Gast
Vielleicht sollte man bei VB spezifischen Fragen nicht in einem Javaforum fragen?

Sorry, aber was erwartest du hier für antworten?
 

Alibi086

Mitglied
Es ist doch völlig egal, um welche Sprache es hier geht (es handelte sich bei meinem Post lediglich um ein exemplarisches Ausgangsbeispiel), sondern um den technisch möglichen / unmöglichen Sachverhalt.
 

AmunRa

Gesperrter Benutzer
Ja man sollte reine SQL-Strings vermeiden und eher auf so was wie PreparedStatements oder ähnliches setzen.

(Gilt aber nur im allgemeinen Fall und nicht in irgendwelchen speziellen)

PreparedStatements gibts eigentlich in fast jeder Sprache.
 

MasterK

Mitglied
Das ist nur deine Meinung ;)

Nein. Denn wilde zusammengehackte SQL Statements habe ich bisher in allen möglichen Sprachen gesehen. VB, Java, C, C++, C#, Python, ECMAScript usw.

OR-Mapper sind idR nicht wirklich die Lösung für diese Frage. Einen wilden Join über dutzende Tabellen will keiner aufdröseln um ihn mittels JPA zu ersetzen. PreparedStatements helfen den Wildwuchs zu bekämpfen. Aber das ist, wie schon gesagt wurde, absolut nichts Java-spezifisches.

Daher ist die Frage in der Form absolut legitim.
 

faetzminator

Gesperrter Benutzer
Es geht doch gar nicht darum, dass diese Query ein Join beinhaltet? Sondern dass sie nicht 1:1 so im Quellcode stehen soll. Und das kann man mit den oben geposteten Tools durchaus erreichen.
 

Evil-Devil

Top Contributor
Spätestens bei den Joins steht das SQL wieder direkt im Source.

ActiveSet, JPA und Co sind ja schön und gut für das einzelne Objekt oder eine Liste der Objekte, aber bei Joins ist die Optimierung in sehr vielen Fällen alles andere als optimal. Vor allem bei jenen Joins die über drei und mehr Tabellen gehen.
 

turtle

Top Contributor
:confused:

Häh, verstehe ich nicht. Ich kann doch ein Prepared-Statement komplett mit Joins über n Tabellen schreiben, da steht nix im Source.

Ich stimme zu was Optimierungen angeht, daher bevorzuge ich myBATIS
 

Evil-Devil

Top Contributor
ich kenne die Prepared Statements an sich nur von MySQLi in PHP und hab mir vorher extra die JPA angeschaut.

Sowohl in PHP als auch in JPA erschließt sich mit der Sinn nur schlecht. Bei Java würde ich zustimmen das durch die einmalige Laufzeit Erzeugung ein Vorteil entsteht. Dieser wäre bei PHP nicht gegeben. Denn das Prepared Statement wird jedes Mal neu erzeugt.

Denn wann benutzt man ein einzelnes Statement mehr als einmal pro Seite?

Vielleicht kann mich jemand erleuchten?
 

schalentier

Gesperrter Benutzer
Also zumindest Hibernate (als JPA) schickt immer Prepared Statements zur Datenbank. Das kann man meines Wissen nach, auch nicht abschalten.

Der Sinn ist, dass die DB dann gleiche Statements erkennt und nur noch die Variablen binden muss. D.h. das Parsen des Statements passiert nur noch einmal. Ob daraus tatsaechlich ein messbarer Performancegewinn entstehen kann, haengt von der Groesse, der Komplexitaet und der Anzahl der Statements ab.
 

Evil-Devil

Top Contributor
Ja ok. Das leuchtet mir ein, allerdings scheint das stark vom DBMS abhängig zu sein.

Wir verwenden hier MySQL und das kann zb. bis 5.1.x den Cache nicht über Prepared Statements nutzen.


D.h. ein wirklicher Performance Gewinn kann erst bei ausreichend hoher Frequenz erzielt bzw. bemerkt werden. Sehe ich das richtig?
 

turtle

Top Contributor
Ich sehe den grossen Vorteil von Prepared-Statements darin, dass die Applikation immun gegen SQL-Injection Angriffe ist.
 

AmunRa

Gesperrter Benutzer
Ich dachte auch immer das PreparedStatements die Möglichkeit von SQLInjection unterbindet oder bin ich da falsch informiert?


Edit:
Ich sehe den grossen Vorteil von Prepared-Statements darin, dass die Applikation immun gegen SQL-Injection Angriffe ist.

Damit hat sich meine Frage erübrigt.
 

MrWhite

Bekanntes Mitglied
Mein Gott, alle gleich so konkret.

OP hat gesagt.:
Es ist doch völlig egal, um welche Sprache es hier geht (es handelte sich bei meinem Post lediglich um ein exemplarisches Ausgangsbeispiel), sondern um den technisch möglichen / unmöglichen Sachverhalt.

Geht auch allgemeiner.

Ich poste hier einfach mal ein paar Links vom guten alten Martin Fowler:

P of EAA: Table Data Gateway
P of EAA: Row Data Gateway
P of EAA: Data Mapper
P of EAA: Active Record

Jetzt lies dann durch, dann biste heller. Ist *fast* universell anwendbar, *fast* sprachunabhängig.
 
Zuletzt bearbeitet:

Evil-Devil

Top Contributor
Ich sehe den grossen Vorteil von Prepared-Statements darin, dass die Applikation immun gegen SQL-Injection Angriffe ist.

Gibt es unter Java sowas wie mysql_real_escape() nicht? Ansonsten noch die GET/POST/COOKIE Daten escapen und prüfen und es wird zu keiner SQL Injection kommen.

Das Prepared Statements zu 100% gegen SQL Injection helfen sollen kann ich mir nur sehr schwer vorstellen, will es aber mal glauben.
 

turtle

Top Contributor
Gibt es unter Java sowas wie mysql_real_escape() nicht?

Nein, braucht man auch nicht, weil Prepared-Statements zu 100% SQL Injection sicher sind ;)

Daneben halte ich das Escapen von SQL-Strings für einen Code-Smell. Man kann sich leider nicht sicher sein, ob ALLE SQL-Commands geeignet escaped werden und wenn nicht hat man ein GROSSES Sicherheitsproblem. Leider findet man diese erst zur Laufzeit und nicht durch einfaches Code-Review.
 

Evil-Devil

Top Contributor
Daneben halte ich das Escapen von SQL-Strings für einen Code-Smell. Man kann sich leider nicht sicher sein, ob ALLE SQL-Commands geeignet escaped werden und wenn nicht hat man ein GROSSES Sicherheitsproblem. Leider findet man diese erst zur Laufzeit und nicht durch einfaches Code-Review.

Ob geeignet oder nicht ist bei Typenlosen Sprachen wie PHP eine Frage des Aufwands. Wenn man erwartet das eine Variable eine Zahl und nicht ein String ist, dann kann man sie entsprechend escapen und übergeben.

zb.

PHP:
$val = isset($_REQUEST['val']) && isNumeric($_REQUEST['val']) ? $_REQUEST['val'] : null;

// bei NULL abrechen....
// ...

$queryString = "select mycolumn from mytable where mycolumn = ".sqlEscape($val);

sqlEscape würde nun noch auf Numeric und String prüfen und bei einem String diesen für SQL entsprechend escapen.
Das man die Request Variablen noch mehr prüfen und manipulierne kann wie zb. Slashes hinzufügen oder entfernen ist mir klar, aber sollte jetzt nicht Bestandteil des Beispiels sein und wird erst bei LIKE Abfragen interessant.

Für mich kann ich also festhalten, Prepared Statements sind bei Java in erster Linie als Injection Schutz zu sehen und danach als Performance Gewinn.

Allerdings würde es mich interessieren wann der Injection Schutz auftritt. Prüft JPA auf eine mögliche Injection oder wie läuft das ab? Weil wenn man nur Blind Variablen übergibt kann imho weiterhin eine Injection auftreten.
 

XHelp

Top Contributor
Das Prepared Statements zu 100% gegen SQL Injection helfen sollen kann ich mir nur sehr schwer vorstellen
Zu 100% kannst du dich gegen SQL Injection absichern, in dem du auf die Verwendung von SQL verzichtest.
Aber PreparedStatements hilft besser gegen Injection als "vllt irgendwo irgendwann irgendwelche Daten mal unnütziger weise escapen oder dann ja vllt doch irgendwo vergessen, aber k.a. mehr wo, der Code ist mir jetzt zu lang"

P.S. Oh... es gab ja eine zweite Seite... :oops:
 
G

Gast2

Gast
Nur mal so am Rande: Guckt euch mal alle Threads von diesem Flix2000 an und ob er nochmal antwortet. Ich würde sagen das er mit sehr großer Wahrscheinlichkeit ein Troll ist...
 

turtle

Top Contributor
Weil wenn man nur Blind Variablen übergibt kann imho weiterhin eine Injection auftreten

Nein, eben nicht.

Es werden ja keine Variablen in den SQL-Befehl irgendwie reingemixt, sondern es werden Variablen-werte an die Parameter gebunden.

Also wenn Dein SQL-Statement
SQL:
select name, telefon from kunde where name=?
und beim Aufruf bindest Du den Parameter
Java:
preparedStatement.setString(1, "'1'; drop table kunde;");
wird das dennoch NICHT die Tabelle löschen.
 

Evil-Devil

Top Contributor
Also muss man für nahezu jeden möglichen Parameterwert ein prepared Statement erzeugen oder wie läuft das zb. in einem Freitext Suchformular dann ab?

zb.:
[sql]
select vorname, nachname, strasse, hausnummer, ort
from adressaten
where vorname like '%evil%'
or nachname like '%devil%'
or ort like '%java-forum%'
[/sql]

Wie würde sowas mit einem Prepared Statement ausschauen?
 

Evil-Devil

Top Contributor
Ok, dann müsste ich mittels einer SChleife die Variablen 1 bis 3 befüllen, oder?
Entsprechend kann man dann auch dynamisch Queries zusammenkleben?

Also wenn Dein SQL-Statement
SQL:
select name, telefon from kunde where name=?
und beim Aufruf bindest Du den Parameter
Java:
preparedStatement.setString(1, "'1'; drop table kunde;");
wird das dennoch NICHT die Tabelle löschen.
Ok, ein PS führt somit nur EIN Statement aus, anstatt der zwei die du da an sich hättest.
 

Evil-Devil

Top Contributor
Oder einfach 3 setParameter-Aufrufe hintereinander...
ja, wenn die Suche statisch ist.

Versteh ich nicht. Welche 2 Statements?

Das bezog sich auf Turtles Beispiel.
SQL:
select name, telefon from kunde where name=?
Java:
preparedStatement.setString(1, "'1'; drop table kunde;");
wird das dennoch NICHT die Tabelle löschen.

Das sind effektiv 2 Statements. Doch er schreibt ja das Drop Table nicht ausgeführt wird.
 

turtle

Top Contributor
Schau Dir doch mal mein Lieblings-JDBC-Framework an: myBATIS

Damit können unter dem Stichwort Dynamic SQL sehr schön beispielsweise where-Klauseln eingefügt werden wenn bestimmte Inhalte in den zugrundeliegenden Java-Beans gefüllt sind.

Beispielsweise selektiert folgendes Statement all Blogs, wenn kein Titel angegeben wurde oder es gibt nur die Blogs mit dem angegeben Titel zurück.
[XML]<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog">
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
</select>[/XML]
Oder eine in-Klausel:
[XML] <select id="selectPostIn" resultType="Group" parameterType="List">
SELECT ADDRESS, PHONE FROM GROUPS G WHERE ADDRESS in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>[/XML]
Aufruf via
Code:
sqlSession.selectList("Group.selectPostIn", Arrays.asList(new String[] {"T1", "T2"}));
 

Evil-Devil

Top Contributor
@myBatis: SChaue ich mir mal an. Hab zwar noch keine DB unter Java genutzt, was nicht ist kann ja noch werden.

@tfa: Ja, die ist böse nur für einen Angreifer nutzlos. Interessant sind Injections imho überall wo mehrere Statements mit nur einer Abfrage ausgelöst werden können.
 
G

Gast2

Gast
Gibt es unter Java sowas wie mysql_real_escape() nicht? Ansonsten noch die GET/POST/COOKIE Daten escapen und prüfen und es wird zu keiner SQL Injection kommen.

Das Prepared Statements zu 100% gegen SQL Injection helfen sollen kann ich mir nur sehr schwer vorstellen, will es aber mal glauben.

Sind sie... Bind Parameter können NIEMALS den Query aufbrechen. Ein mysql_real_escape() kann dagegen gefährlich werden da sich drauf verlassen wird das schon alle Möglichkeiten den Query zu brechen abgeprüft werden.
 

HimBromBeere

Top Contributor
Ansonsten noch die GET/POST/COOKIE Daten escapen und prüfen und es wird zu keiner SQL Injection kommen.
Prinzipiell richtig, im Detail aber manchmal ganz schön hakelig... das Problem ist weniger das Escapen als vielmehr das Auffinden "böser" Zeichenketten. Denn sowas wie ein einfaches Einführungszeichen oder ein doppeltes kann man auch einfach ASCII-Zeichen kodieren (z.B. %20 für Leerzeichen oder was auch immer). Wie auch immer... das Verwenden von PreparedSatements ist tatsächlich die einzige effektive Methode gegen Injection... habe zumindest bisher noch kein Schlupfloch finden können:D...
 

Evil-Devil

Top Contributor
Prinzipiell richtig, im Detail aber manchmal ganz schön hakelig... das Problem ist weniger das Escapen als vielmehr das Auffinden "böser" Zeichenketten. Denn sowas wie ein einfaches Einführungszeichen oder ein doppeltes kann man auch einfach ASCII-Zeichen kodieren (z.B. %20 für Leerzeichen oder was auch immer). Wie auch immer... das Verwenden von PreparedSatements ist tatsächlich die einzige effektive Methode gegen Injection... habe zumindest bisher noch kein Schlupfloch finden können:D...
Für %20 und Co gibt es Encode und RawEncode. Also kein Argument ;)

@PDO: PDO ist eine Extension die DBMS Zugriffe vereinfacht und abstrahiert. Die Prepared Statements werden für MySQL unter PHP nur über die MySQLi Extension unterstützt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
T Gibt es eine Software die Texte für Skype automartisch (automassage) sendet ? Softwareentwicklung 4
J Gibt es eine Algorithmus dafür??? Softwareentwicklung 5
N gibt es eine RFC die speziell "bug tracking" besch Softwareentwicklung 5
Landei Gibt es hier Haskellers? Softwareentwicklung 10
N Gibt es soetwas wie Codetabellen? Softwareentwicklung 2
M wie funktioniert eine KI mathematisch Softwareentwicklung 6
W Datenhaltung und Darstellung - Hat jemand eine Idee? Softwareentwicklung 41
S Welche Programmiersprache für eine 3D-Software? Softwareentwicklung 6
N Technologie Grundlagen für eine "App" Softwareentwicklung 12
J Suche noch eine Loesung fuer Kommunikation zwischen Webserver und ein Programm Softwareentwicklung 0
U Individualsoftware - eine Gefahr für Kunden oder die günstigere Alternative? Softwareentwicklung 7
T Schützt die GPL auch eine implementierte Idee? Softwareentwicklung 5
I Grundlegende Anforderungen an eine Software Softwareentwicklung 14
O Wie funktioniert eigentlich eine Programmiersprache? Softwareentwicklung 10
D Ist das bereits eine Softwareentwicklung? Softwareentwicklung 3
M Wie tief darf eine Vererbungshierarchie sein? Softwareentwicklung 10
M Eine Tabelle aus mehreren anderen Tabellen erzeugen! Softwareentwicklung 3
Redfrettchen Lieber eine neue oder eine allgemeine Klasse? Softwareentwicklung 2
R Ein Thread für eine Methode Softwareentwicklung 2
1 Wie erstellt man so eine Website? Softwareentwicklung 14
M Eine Instanz übergeben ohne sie neu zu bilden Softwareentwicklung 21
T Klassendiagramm: Kann Attribut eine Liste enthalten? Softwareentwicklung 1
F Ist der Name eines Ojekts eine Eigenschaft Softwareentwicklung 7
K Alternative zu UML ? Softwareentwicklung 6

Ähnliche Java Themen

Neue Themen


Oben