Seguro
query.SQL.Text := 'select * from table_name where name=:Name';
Este código es seguro porque está utilizando parámetros.
Los parámetros siempre están a salvo de la inyección de SQL.
Inseguro
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
No es seguro porque el nombre de usuario podría ser name; Drop table_name;
Resultando en la ejecución de la siguiente consulta.
select * from table_name where name=name; Drop table_name;
También inseguro
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Porque si el nombre de usuario es ' or (1=1); Drop Table_name; --
Dará como resultado la siguiente consulta:
select * from table_name where name='' or (1=1); Drop Table_name; -- '
Pero este código es seguro
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Porque IntToStr()
solo aceptará números enteros, por lo que no se puede inyectar código SQL en la cadena de consulta de esta manera, solo números (que es exactamente lo que desea y, por lo tanto, está permitido)
Pero quiero hacer cosas que no se pueden hacer con parámetros
Los parámetros solo se pueden utilizar para valores. No pueden reemplazar nombres de campos o nombres de tablas. Entonces, si desea ejecutar esta consulta
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
La primera consulta falla porque no puede usar parámetros para los nombres de tablas o campos.
La segunda consulta no es segura, pero es la única manera de hacerlo.
¿Cómo mantenerse a salvo?
Tienes que comprobar la cadena tablename
contra una lista de nombres aprobados.
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;
...
Esa es la única manera de hacer esto, que yo sepa.
Por cierto, tu código original tiene un error:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Debería ser
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
No puedes tener dos where
's en una (sub)consulta