【问题标题】:Delphi - Access violation at address 0051BC48Delphi - 地址 0051BC48 的访问冲突
【发布时间】:2018-07-26 08:29:11
【问题描述】:

我创建了“qry”作为私有变量。一段时间以来,我一直在尝试修复此错误。我正在使用的代码是这样的:

procedure TfrmMaintenance.btnInsertNutsManyClick(Sender: TObject);
begin
  with dmNutsData do

Begin

qry.SQL.Clear;

qry.SQL.Clear;

qry.SQL.Add('INSERT INTO CompnayList (CompanyID, CompanyName, CompanyNumber, CompanyEmail, ') ;

qry.SQL.Add('Values (edtCompID.Text, edtCompName.Text, edtCompNumb.Text, edtCompanyEmail.Text') ;

qry.ExecSQL;

  End;
end;

【问题讨论】:

  • 我建议你展示你的完整代码,包括你定义 qry 变量的部分,以及你创建 qry 对象的部分。你有没有在调试器中运行代码找到异常发生的行?
  • 这是一个关于如何调试 Delphi 程序中的访问冲突的旧堆栈溢出问题。 stackoverflow.com/questions/6214458/…
  • 顺便说一句,您的 INSERT 语句中的意思是“CompnayList”吗?
  • 您究竟在哪里创建 qry 作为私有变量?我在您的代码中的任何地方都没有看到。如果它是 dmNutsData 中的私有变量,那么您根本无法从您的表单 TfrmMaintenance 访问它,如果它是您的表单或该表单单元的私有变量,则不需要 with。发布一个实际的minimal reproducible example 来演示实际问题。您发布的代码不完整。 (而且有点傻 - 你认为连续两次调用 qry.SQL.Clear 会做什么?仔细检查以确保 SQL 确实清晰?)

标签: delphi


【解决方案1】:

这通常意味着以下之一:

  • dmNutsDatanil
  • dmNutsData.qrynil
  • dmNutsData.qry.SQLnil
  • qry 不是 dmNutsData 的成员,但在其他地方声明,并且是 nil

使用您的调试器找出它是什么。单步执行代码并检查值以查看哪个是nil

我强烈建议您不要以这种方式使用with。这样做可能会导致您遇到意外的范围冲突,并且还会使您的程序更难调试。如果您想避免重复写入dmNutsData.qry,请声明一个局部变量并为其分配``dmNutsData.qry`。

最后,您的程序与之前的许多程序一样,容易受到 SQL 注入的影响。不要掉进那个陷阱。使用参数。

【讨论】:

    【解决方案2】:

    除了@DavidHeffernan 的回答中提到的几点之外,您的 INSERT 语句中至少有四个语法错误。任何这些都可能导致您报告的 AV,具体取决于您使用的查询组件的类型,您没有说明,或者至少导致 INSERT 失败。

    在你的 qry.SQL.Add('INSERT INTO CompnayList (CompanyID, CompanyName, CompanyNumber, CompanyEmail, ') ;

    • 首先,CompnayList 应该是CompanyList。我在您尚未回复的评论中提到了这一点。

    • 其次,`CompanyEmail'后面的SQL语句中不能有逗号

    • 第三,`CompanyEmail'后面应该有一个右括号

    所以修正后的版本应该是

    qry.SQL.Add('INSERT INTO Comp**an**yList (CompanyID, CompanyName, CompanyNumber, CompanyEmail)') ;
    

    接下来,你的 SQL

    qry.SQL.Add('Values (edtCompID.Text, edtCompName.Text, edtCompNumb.Text, edtCompanyEmail.Text') ;
    

    再次缺少右括号,如果您打算访问 edtCompID 的文本,则说明您操作不正确,该行应为

    qry.SQL.Add('Values (' + edtCompID.Text + ', ' + edtCompName.Text + ', ' +  edtCompNumb.Text + ', ' + edtCompanyEmail.Text + ')') ;
    

    正如 David 所说,最好参数化 SQL 语句,但这不仅仅是因为 SQL 注入的风险。

    顺便说一句,通过调用 qry.SQL.Add() 来构建 SQL 语句,您使事情变得比需要的更容易出错。这是因为外括号使您更难在您尝试添加的文本中发现错误,尤其是当文本应该包含自己的括号时。最好使用字符串变量作为临时“持有者”在构建 SQL 时接收它,然后在完成后将其分配给 qry 的 Sql.Text 属性,如下所示

    var
      S : String;
    begin
      [...]
      S := 'select * from mytable';
      qry.SQL.Text := S;
      qry.Open;
      [...]
    end;
    

    【讨论】:

    • 抱歉这么晚了,一直忙着准备考试。感谢您的帮助,我非常感谢,我会再看一遍。
    猜你喜欢
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多