Ich bin sehr neu in der Arbeit mit Datenbanken. Jetzt kann ich schreiben SELECT
, UPDATE
, DELETE
, und INSERT
Befehle. Aber ich habe viele Foren gesehen, in denen wir lieber schreiben:
SELECT empSalary from employee where salary = @salary
...anstatt:
SELECT empSalary from employee where salary = txtSalary.Text
Warum bevorzugen wir immer Parameter und wie würde ich sie verwenden?
Ich wollte die Verwendung und die Vorteile der ersten Methode kennen. Ich habe sogar von SQL Injection gehört, aber ich verstehe es nicht ganz. Ich weiß nicht einmal, ob SQL Injection mit meiner Frage zusammenhängt.
sql
sql-server
sql-injection
Sandig
quelle
quelle
Antworten:
Durch die Verwendung von Parametern können SQL Injection-Angriffe verhindert werden, wenn die Datenbank in Verbindung mit einer Programmschnittstelle wie einem Desktop-Programm oder einer Website verwendet wird.
In Ihrem Beispiel kann ein Benutzer SQL-Code direkt in Ihrer Datenbank ausführen, indem er Anweisungen in erstellt
txtSalary
.Wenn sie beispielsweise schreiben würden
0 OR 1=1
, wäre das ausgeführte SQLwobei alle empSalaries zurückgegeben würden.
Außerdem könnte ein Benutzer weitaus schlechtere Befehle für Ihre Datenbank ausführen, einschließlich des Löschens, wenn er Folgendes geschrieben hat
0; Drop Table employee
:Die Tabelle
employee
würde dann gelöscht.In Ihrem Fall scheint es, als würden Sie .NET verwenden. Die Verwendung von Parametern ist so einfach wie:
C #
VB.NET
Bearbeiten 2016-4-25:
Gemäß dem Kommentar von George Stocker habe ich den Beispielcode so geändert, dass er nicht verwendet wird
AddWithValue
. Außerdem wird allgemein empfohlen,IDisposable
s inusing
Anweisungen einzuschließen .quelle
Insert Into table (Col1, Col2) Values (@Col1, @Col2)
. In Ihrem Code würden Sie mehrereAddWithValue
s hinzufügen .parameter.Value = someValue
.Sie haben Recht, dies hängt mit der SQL-Injection zusammen , einer Sicherheitsanfälligkeit, die es einem Malicioius-Benutzer ermöglicht, beliebige Anweisungen für Ihre Datenbank auszuführen. Dieser alte Lieblings- XKCD-Comic veranschaulicht das Konzept:
Wenn Sie in Ihrem Beispiel nur Folgendes verwenden:
Sie sind offen für SQL-Injection. Angenommen, jemand gibt txtSalary ein:
Wenn Sie diese Abfrage ausführen, führt sie ein
SELECT
und einUPDATE
oderDROP
oder was auch immer sie wollten aus. Das--
am Ende kommentiert einfach den Rest Ihrer Abfrage aus, was für den Angriff nützlich wäre, wenn Sie danach etwas verketten würdentxtSalary.Text
.Der richtige Weg ist die Verwendung parametrisierter Abfragen, z. B. (C #):
Damit können Sie die Abfrage sicher ausführen.
Informationen zum Vermeiden von SQL-Injection in mehreren anderen Sprachen finden Sie unter bobby-tables.com , einer Website, die von einem SO-Benutzer verwaltet wird .
quelle
Zusätzlich zu anderen Antworten muss hinzugefügt werden, dass Parameter nicht nur dazu beitragen, die SQL-Injektion zu verhindern, sondern auch die Leistung von Abfragen verbessern können . SQL Server-Caching parametrisierte Abfragepläne und Wiederverwendung bei wiederholter Ausführung von Abfragen. Wenn Sie Ihre Abfrage nicht parametrisiert haben, würde der SQL Server bei jeder Abfrageausführung (mit einigen Ausschlüssen) einen neuen Plan erstellen, wenn der Text der Abfrage unterschiedlich wäre.
Weitere Informationen zum Zwischenspeichern von Abfrageplänen
quelle
Zwei Jahre nach meinem ersten Versuch rezidiviere ich ...
Warum bevorzugen wir Parameter? SQL-Injection ist natürlich ein großer Grund, aber könnte es sein, dass wir uns insgeheim danach sehnen, wieder zu SQL als Sprache zurückzukehren . SQL in String-Literalen ist bereits eine seltsame kulturelle Praxis, aber zumindest können Sie Ihre Anfrage kopieren und in das Management Studio einfügen. SQL, das dynamisch mit Bedingungen und Kontrollstrukturen in der Hostsprache erstellt wurde, wenn SQL über Bedingungen und Kontrollstrukturen verfügt, ist nur eine Barbarei der Stufe 0. Sie müssen Ihre App im Debug oder mit einem Trace ausführen, um zu sehen, welche SQL sie generiert.
Hören Sie nicht nur mit Parametern auf. Gehen Sie den ganzen Weg und verwenden Sie QueryFirst (Haftungsausschluss: den ich geschrieben habe). Ihr SQL befindet sich in einer SQL-Datei. Sie bearbeiten es im fabelhaften TSQL-Editorfenster mit Syntaxüberprüfung und Intellisense für Ihre Tabellen und Spalten. Sie können Testdaten im Bereich für spezielle Kommentare zuweisen und auf "Wiedergabe" klicken, um Ihre Abfrage direkt im Fenster auszuführen. Das Erstellen eines Parameters ist so einfach wie das Einfügen von "@myParam" in Ihre SQL. Bei jedem Speichern generiert QueryFirst dann den C # -Wrapper für Ihre Abfrage. Ihre Parameter werden stark typisiert als Argumente für die Execute () -Methoden angezeigt. Ihre Ergebnisse werden in einer IEnumerable oder Liste stark typisierter POCOs zurückgegeben, den Typen, die aus dem von Ihrer Abfrage zurückgegebenen tatsächlichen Schema generiert wurden. Wenn Ihre Abfrage nicht ausgeführt wird, wird Ihre App nicht kompiliert. Wenn sich Ihr Datenbankschema ändert und Ihre Abfrage ausgeführt wird, aber einige Spalten verschwinden, zeigt der Kompilierungsfehler auf die Zeile in Ihrem Codedas versucht, auf die fehlenden Daten zuzugreifen. Und es gibt zahlreiche weitere Vorteile. Warum möchten Sie auf andere Weise auf Daten zugreifen?
quelle
Wenn in SQL ein Wort ein @ -Zeichen enthält, bedeutet dies, dass es eine Variable ist. Wir verwenden diese Variable, um den Wert darin festzulegen und sie im Zahlenbereich desselben SQL-Skripts zu verwenden, da sie nur auf das einzelne Skript beschränkt ist, während Sie viele Variablen deklarieren können vom gleichen Typ und Namen auf vielen Skripten. Wir verwenden diese Variable in gespeicherten Prozeduren, da gespeicherte Prozeduren vorkompilierte Abfragen sind und wir Werte in dieser Variablen von Skript, Desktop und Websites übergeben können. Weitere Informationen finden Sie unter Deklarieren lokaler Variablen , gespeicherte SQL-Prozeduren und SQL-Injektionen .
Lesen Sie auch Schutz vor SQL-Injection. Hier erfahren Sie, wie Sie Ihre Datenbank schützen können.
Hoffe es hilft dir auch jede Frage zu verstehen, kommentiere mich.
quelle
Andere Antworten behandeln, warum Parameter wichtig sind, aber es gibt einen Nachteil! In .net gibt es verschiedene Methoden zum Erstellen von Parametern (Add, AddWithValue), bei denen Sie sich jedoch unnötigerweise um den Parameternamen kümmern müssen, und alle beeinträchtigen die Lesbarkeit von SQL im Code. Wenn Sie versuchen, über SQL zu meditieren, müssen Sie oben oder unten herumjagen, um zu sehen, welcher Wert im Parameter verwendet wurde.
Ich behaupte demütig, dass meine kleine SqlBuilder-Klasse die eleganteste Art ist, parametrisierte Abfragen zu schreiben . Ihr Code wird so aussehen ...
C #
Ihr Code wird kürzer und viel besser lesbar sein. Sie brauchen nicht einmal zusätzliche Zeilen, und wenn Sie zurücklesen, müssen Sie nicht nach dem Wert von Parametern suchen. Die Klasse, die Sie brauchen, ist hier ...
quelle
AddWithValue
kann dies zu impliziten Konvertierungsproblemen führen.Alte Post, wollte aber sicherstellen, dass Neuankömmlinge über gespeicherte Verfahren informiert sind .
Mein 10 ¢ Wert hier ist, dass, wenn Sie Ihre SQL-Anweisung als gespeicherte Prozedur schreiben können , dies meiner Ansicht nach der optimale Ansatz ist. Ich IMMER verwenden gespeicherte Prozeduren und nie Schleife durch Aufzeichnungen in meinem Haupt - Code. Zum Beispiel :
SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class
.Wenn Sie gespeicherte Prozeduren verwenden, können Sie den Benutzer nur auf die EXECUTE- Berechtigung beschränken, wodurch Sicherheitsrisiken verringert werden .
Ihre gespeicherte Prozedur ist von Natur aus paramerisiert, und Sie können Eingabe- und Ausgabeparameter angeben.
Auf die gespeicherte Prozedur (wenn sie Daten über eine
SELECT
Anweisung zurückgibt ) kann genauso zugegriffen und gelesen werden wie über eine reguläreSELECT
Anweisung in Ihrem Code.Es läuft auch schneller, da es auf dem SQL Server kompiliert wird.
Habe ich auch erwähnt, dass Sie mehrere Schritte ausführen können, z. B.
update
eine Tabelle, Werte auf einem anderen DB-Server überprüfen und dann nach Abschluss Daten an den Client zurückgeben können, alle auf demselben Server und ohne Interaktion mit dem Client. Das ist also VIEL schneller als das Codieren dieser Logik in Ihrem Code.quelle