Как включить целочисленное значение в оператор SQL (удалить) в delphi

В базе данных DoctorID представляет собой целочисленный столбец. Ни одна из отредактированных строк кода "//" не работает. Я был бы очень признателен, если бы кто-нибудь показал мне, как правильно указывать целочисленные значения в операторе SQL.

procedure TForm1.btnDeleteDocClick(Sender: TObject);
var
  iID : Integer;
begin
  iID := StrToInt (InputBox('Delete Doctor','Please enter in your Doctor ID',''));
  with dmHospital do
  begin
    qryDoctors.SQL.Clear;
    //qryDoctors.SQL.Add('DELETE FROM Doctors WHERE DoctorID = iID ' ) ;
    //qryDoctors.SQL.Add('DELETE FROM Doctors WHERE DoctorID = ' + QuotedStr(iID));
    qryDoctors.ExecSQL;
    qryDoctors.SQL.Clear;
    qryDoctors.SQL.Add('SELECT * FROM Doctors');
    qryDoctors.Open;
  end;
end;

person Ocean Knight    schedule 23.08.2016    source источник
comment
Я не знаю, какие компоненты базы данных вы используете, но поищите, как использовать параметры в ваших операторах SQL. Обычно вы пишете :Param01 в своем предложении, а затем каким-то образом передаете значение   -  person rgoliveira    schedule 23.08.2016
comment
InputBox() возвращает значение параметра ADefault, если пользователь отменяет диалог. В данном случае это пустая строка. Или вместо этого используйте InputQuery(), который возвращает Boolean, указывающий, был ли диалог принят или отменен. Но пользователь по-прежнему может ввести пустое значение. В любом случае перед подготовкой SQL-запроса следует проверить наличие недопустимых входных данных.   -  person Remy Lebeau    schedule 23.08.2016


Ответы (1)


Проблема с

qryDoctors.SQL.Add('DELETE FROM Doctors WHERE DoctorID = iID ' )

заключается в том, что он не вводит значение переменной iID в оператор DELETE, как вы, очевидно, поняли.

В равной степени проблема с

qryDoctors.SQL.Add('DELETE FROM Doctors WHERE DoctorID = ' + QuotedStr(iID))

заключается в том, что он окружает значение iID кавычками, так что механизм Sql, выполняющий оператор DELETE, на самом деле видит что-то вроде

DELETE FROM Doctors WHERE DoctorID = '99'

но DoctorID - это целочисленный столбец, а не строковый.

Итак, поскольку ваш столбец идентификаторов является столбцом целочисленного типа, попробуйте вместо этого (но см. Ниже об опасностях Sql Injection):

qryDoctors.SQL.Add('DELETE FROM Doctors WHERE DoctorID = ' + iID);

Айоу, вам не нужны кавычки вокруг целочисленных значений.

Параметризованная версия вашего оператора DELETE будет лучшим решением:

qryDoctors.SQL.Text := 'DELETE FROM Doctors WHERE DoctorID = :DoctorID';
qryDoctors.ParamByName('DoctorID').Value := StrToInt(iID);

Одна из причин, по которой это лучше, заключается в том, что он невосприимчив к Sql Injection (см. https://en.wikipedia.org/wiki/SQL_injection), в то время как ваш способ сделать это, позволяя пользователю указать часть SQL с помощью InputQuery, а затем объединить его с другим текстом DELETE, не подходит. На самом деле объединение пользовательского ввода в оператор SQL — это именно то, что позволяет использовать Sql Injection — например, злоумышленник может добавить другой оператор (или больше) в конец того, который вы вводите. здание, например DROP TABLE Employee (или хуже). Возможность для этой пользовательской подрывной версии инструкции Sql никогда не возникает, когда запрос параметризован.

Fwiw, причина, по которой мне лично не нравится использовать свойство Value TParameter, заключается в том, что это вариант, поэтому подрывает ввод данных для указанного значения.

Кстати, iID — не очень хорошее имя для переменной, которая на самом деле является строкой. Префикс «i» обычно заставляет читателей ожидать целое число.

person MartynA    schedule 23.08.2016
comment
qryDoctors.SQL.Add('DELETE FROM Doctors WHERE DoctorID = ' + iID); Это дыра для SQL-инъекций. - person Johan; 23.08.2016
comment
@Johan: я собирался упомянуть Sql Injection, но не смог удержаться. Я добавлю упоминание об этом через месяц, спасибо. - person MartynA; 23.08.2016
comment
@Johan: Готово, и, кстати, ваш худший, чем бесполезный комментарий к другому ответу был совершенно справедливым. - person MartynA; 23.08.2016
comment
@MartynA: я исправил часть iID Integer, я играл с разными идеями и забыл вернуть ее обратно. Я пробовал: ` qryDoctors.SQL.Text := 'УДАЛИТЬ ИЗ "Врачей", ГДЕ DoctorID = :DoctorID'; qryDoctors.ParamByName('DoctorID').AsInteger := iID; ` Но он говорит, что 'TParameter' не содержит члена с именем 'AsInteger'. Я не слишком беспокоюсь о внедрении SQL, но спасибо, что напомнили мне. - person Ocean Knight; 23.08.2016
comment
@OceanKnight: Извините, я пропустил это, это часть кода, который кто-то добавил. В любом случае сообщение об ошибке правильное: замените AsString на Value. - person MartynA; 23.08.2016
comment
Я не слишком беспокоюсь о SQL-инъекциях. Но в дополнение к безопасности, параметризованные запросы также намного быстрее, потому что БД может кэшировать параметризованные запросы и не может кэшировать объединенные запросы. - person Johan; 23.08.2016