在SQL语句中使用变量时编译器错误

时间:2016-07-08 21:34:06

标签: delphi delphi-7

我正在尝试编写一个登录过程,但在尝试执行包含将来自用户输入的变量的SQL语句时,我遇到了问题。

以下是它的外观:

Var 
  SS,temp,fn,sn: string;
Begin 
  ADO := TDBClass.Create('ICAdatabase.mdb');

  SS:= 'SELECT * FROM Agents Where aName = '  '  ' + fn + ' ' '  And aSurname = ' ' ' + sn +  ' ' ' ';

  Temp := Ado.processquery(SS);
End;

当我尝试使用这样的变量时,我得到了"缺少运算符"或"分号错误"或"未终止的字符串"。这是为什么?

2 个答案:

答案 0 :(得分:5)

您的引号字符在它们之间有额外的空格,您需要删除它们。 ' ' '的解析方式与'''不同:

SS := 'SELECT * FROM Agents Where aName = ''' + fn + ''' And aSurname = ''' + sn + '''';

或者,使用#39代替''

SS := 'SELECT * FROM Agents Where aName = '#39 + fn + #39' And aSurname = '#39 + sn + #39;

或者改为使用QuotedStr()AnsiQuotedStr()

SS := 'SELECT * FROM Agents Where aName = ' + QuotedStr(fn) + ' And aSurname = ' + QuotedStr(sn);

SS := 'SELECT * FROM Agents Where aName = ' + AnsiQuotedStr(fn, #39) + ' And aSurname = ' + AnsiQuotedStr(sn, #39);

此外,在旁注中,您正在泄露ADO个对象,并且在使用它时您不是Free

话虽如此,你真的应该停止手动构建SQL语句。请改用参数化查询(更快更安全)。我不知道TDBClass是什么,但以下是使用TADOQuery的示例:

var 
  fn, sn, temp: string;
Begin 
  fn := ...;
  sn := ...;

  Conn := TADOConnection.Create(nil);
  try
    Conn.ConnectionString := ...;

    ADO := TADOQuery.Create(nil);
    try
      ADO.Connection := Conn;

      ADO.SQL.Text := 'SELECT * FROM Agents Where aName = :AgentName And aSurname = :AgentSurname';

      ADO.Parameters.ParamValues['AgentName'] := fn;
      ADO.Parameters.ParamValues['AgentSurname'] := sn;

      ADO.Open;
      try
        if not (ADO.Bof and ADO.Eof) then
        begin
          // use ADO.Fields values as needed...
          Temp := ...;
        end;
      finally
        ADO.Close;
      end;
    finally
      ADO.Free;
    end;
  finally
    Conn.Free;
  end;
end;

答案 1 :(得分:4)

因为您的代码完全不正确。您需要正确引用变量。我不会告诉你错误的方法(通过加倍每一个引用)导致一团糟。我会告诉你一个更好的方法来解决你提出的直接问题,然后告诉你正确的方法。

至少使用QuotedStr - 我不确定ADO.ProcessQuery做什么或TDBClass是什么,所以我无法解决这一问题。您应该使用TADOQuery代替。您必须非常了解需要引用和不需要引用的内容,并自行完成所有必要的数据类型转换。例如,字符串值被引用,数字不被引用,日期值必须手动转换为数据库期望和引用的格式。

Var 
  SS,temp,fn,sn: string;
Begin 
  ADO := TDBClass.Create('ICAdatabase.mdb');
  SS:= 'SELECT * FROM Agents Where aName = '+ QuotedStr(fn) + 
       ' And aSurname = ' + QuotedStr(sn);
  Temp := Ado.processquery(SS);
End;

正确的方法是使用TADOQuery和参数。在现实世界的例子中,上面的代码看起来更像是这样:

ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM Agents WHERE aName = :Name';
ADOQuery1.SQL.Add('AND aSurname = :Surname');
ADOQuery1.Params.ParamByName('Name').Value := SS;
ADOQuery1.Params.ParamByName('Surname').Value := SN;
ADOQuery1.Open;

这可以防止引用参数,转换类型(例如,直接使用TDateTime),转换数字和记住不引用它们等所有问题,还可以防止SQL注入,使您的数据容易受到恶意软件攻击或恶意用户。