Не могу найти поле в таблице - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть таблица, содержащая поле 'стоимость', когда я пытаюсь извлечь ее значение из таблицы, я получаю сообщение об ошибке, в котором говорится, что поле не найдено.

 function TSQLs.Get(value,room,hotel: string): string;
begin
  with Databasehub.DataModule1 do
  begin
    ADOQuery1.SQL.Clear;
    ADOTable1.TableName:='TblRoom';
    ADOQuery1.SQL.Add('SELECT "'+value+'" FROM TblRoom WHERE RoomType="' + Room + '" AND HotelName 
    ="'+Hotel+'"');
    DataSource1.DataSet:=ADOQuery1;
    ADOQuery1.Open;
    if (ADOQuery1.RecordCount = 1) then
    begin
      Result := ADOQuery1.FieldByName(value).AsString;
    end;
  end;
end;

Database table I'm extracting the value from Table its linked to

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

В операторе SQL не заключайте имена полей в двойные кавычки. Если в имени поля есть пробелы (или другие специальные символы, или зарезервированные имена), используйте вместо этого квадратные скобки. И так как имя вашего поля предоставляется вводом string, убедитесь, что его санировали, прежде чем использовать, чтобы избежать любых атак SQL Injection.

Кроме того, вы должны использовать одинарные кавычки вместо двойных - кавычки вокруг строковых литералов, которые используются в операторах SQL:

if Pos(';', value) > 0 or Pos(',', value) > 0 then raise ...;
ADOQuery1.SQL.Text := 'SELECT [' + value + '] FROM TblRoom WHERE RoomType=' + QuotedStr(Room) + ' AND HotelName = ' + QuotedStr(Hotel);
ADOQuery1.Open;
...

Более безопасным вариантом использования литералов является использование параметров вместо этого (как показывает @ whosrdaddy's answer ), за исключением того, что Имена полей в предложении SELECT не могут быть параметризованы, поэтому часть SQL все равно должна будет использовать конкатенацию строк (после очистки строки):

if Pos(';', value) > 0 or Pos(',', value) > 0 then raise ...;
ADOQuery1.ParamCheck := True;
ADOQuery1.SQL.Text := 'SELECT [' + value + '] FROM TblRoom WHERE RoomType=:Room AND HotelName=:Hotel';
ADOQuery1.Parameters.ParamByName('Room').Value := room;
ADOQuery1.Parameters.ParamByName('Hotel').Value := hotel;
ADOQuery1.Open;
...
1 голос
/ 10 апреля 2020

Прежде всего, обрабатывайте значения в вашей программе как тип в базе данных. Стоимость должна быть определена как тип валюты в вашей БД Access, Delphi также имеет тип валюты, используйте ее как можно дольше и только во время представления, используйте преобразование в текст (или используйте элемент управления, который может обрабатывать собственный тип) ). Также убедитесь, что вы всегда используете параметры в своих запросах, иначе вы уязвимы для SQL инъекций , так как в качестве бонуса это делает ваши запросы более читабельными и позволяет избежать проблем, таких как кавычки в именах и т. Д. c .. .

Вот пример параметризованного запроса и как создать запрос на лету

function TSQLs.GetCost(const Room : string; const Hotel: string): Currency;

var
  Qry : TADOQuery;
begin
 Qry := TADOQuery.Create(nil);
 try
  Qry.Connection := Databasehub.DataModule1.AdoConnection; // assign your TADOconnection here
  Qry.ParamCheck := True; // parse parameters
  Qry.SQL.Text :='SELECT Cost FROM TblRoom WHERE RoomType=:Room AND HotelName=:Hotel'; 
  Qry.Parameters.ParamByName('Room').Value := Room;
  Qry.Parameters.ParamByName('Room').DataType := ftString;
  Qry.Parameters.ParamByName('Hotel').Value := Hotel;
  Qry.Parameters.ParamByName('Hotel').DataType := ftString;
  Qry.Active := True; // Qry.Open is also fine here
  if not Qry.EOF then // don't rely on recordcount here as it could be 0 when using dynamic cursors for example
    Result := Qry.FieldByName('Cost').AsCurrency;
 finally
  Qry.Free;
 end;
end;
...