Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Safe</strong> </p> <pre><code>query.SQL.Text := 'select * from table_name where name=:Name'; </code></pre> <p>This code is safe because you are using parameters.<br> Parameters are always safe from SQL-injection.</p> <p><strong>Unsafe</strong></p> <pre><code>var Username: string; ... query.SQL.Text := 'select * from table_name where name='+ UserName; </code></pre> <p>Is unsafe because Username could be <code>name; Drop table_name;</code> Resulting in the following query being executed.</p> <pre><code>select * from table_name where name=name; Drop table_name; </code></pre> <p>Also <strong>Unsafe</strong></p> <pre><code>var Username: string; ... query.SQL.Text := 'select * from table_name where name='''+ UserName+''''; </code></pre> <p>Because it if username is <code>' or (1=1); Drop Table_name; --</code> It will result in the following query:</p> <pre><code>select * from table_name where name='' or (1=1); Drop Table_name; -- ' </code></pre> <p><strong>But this code is safe</strong></p> <pre><code>var id: integer; ... query.SQL.Text := 'select * from table_name where id='+IntToStr(id); </code></pre> <p>Because <code>IntToStr()</code> will only accept integers so no SQL code can be injected into the query string this way, only numbers <em>(which is exactly what you want and thus allowed)</em></p> <p><strong>But I want to do stuff that can't be done with parameters</strong></p> <p>Parameters can only be used for values. They cannot replace field names or table names. So if you want to execute this query</p> <pre><code>query:= 'SELECT * FROM :dynamic_table '; {doesn't work} query:= 'SELECT * FROM '+tableName; {works, but is unsafe} </code></pre> <p>The first query fails because you cannot use parameters for table or field names.<br> The second query is unsafe but is the only way this this can be done.<br> How to you stay safe? </p> <p>You have to check the string <code>tablename</code> against a list of approved names. </p> <pre><code>Const ApprovedTables: array[0..1] of string = ('table1','table2'); procedure DoQuery(tablename: string); var i: integer; Approved: boolean; query: string; begin Approved:= false; for i:= lo(ApprovedTables) to hi(ApprovedTables) do begin Approved:= Approved or (lowercase(tablename) = ApprovedTables[i]); end; {for i} if not Approved then exit; query:= 'SELECT * FROM '+tablename; ... </code></pre> <p>That's the only way to do this, that I know of.</p> <p><strong>BTW Your original code has an error:</strong></p> <pre><code>query.SQL.Text := 'select * from table_name where name=:Name where id=:ID'; </code></pre> <p>Should be </p> <pre><code>query.SQL.Text := 'select * from table_name where name=:Name and id=:ID'; </code></pre> <p>You cannot have two <code>where</code>'s in one (sub)query</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload