如何从 Delphi 中的 SQL 服务器数据库服务器填充组合框?

How can I populate a combobox from a SQL Server database server in Delphi?

首先,我是 Delphi 的新手,我检查了这里的所有相关主题,但似乎没有任何效果。

我只是想用 SQL 服务器数据库中的列值填充 TComboBox

所以基本上,我有一个 VCL 表单和一个 DataModule,其中包含一个 ADOConnection 和一个 ADOQueryADOConnection 连接到我的数据库(测试连接表明它成功)并且 ADOQuery 连接到我的 ADOConnection。 VCL 窗体和 DataModules 是“连接”的。

(实际上还有另一个问题:每当我尝试在我的 ADOQuery 的属性中输入 SELECT name FROM Partners; 并尝试将其设置为活动时,它一直说“无效的对象名称 'Partners'"。SQL 语句是正确的,我在 SSMS 中对其进行了测试,它检索数据没有任何错误。但我不确定这是否是这里的主要问题。

基本上,这是我的代码:

procedure TFormInsertNewItem.ComboBoxPartnersDropDown(Sender: TObject);
begin
  with DataModule1 do
  begin
    ComboBoxPartners.Items.Clear;
    ADOQueryFillPartners.SQL.Clear;
    ADOQueryFillPartners.SQL.Add('SELECT name FROM Partners;');
    ADOQueryFillPartners.Active:=true;
    ADOQueryFillPartners.Open;
    while not ADOQueryFillPartners.Eof do begin
      ComboBoxPartners.Items.Add(ADOQueryFillPartners.FieldByName('name').AsString);
      ADOQueryFillPartners.Next;
    end;
    ADOQueryFillPartners.Active:=false;
    ADOQueryFillPartners.Free;
  end;
end;

每当我点击下拉它时(或者如果在加载表单时运行它可能会更好,但我不知道如何才能准确地引用该事件),它应该填满它。好吧,它不会。我尝试使用 TDBComboBoxTDBLookUpComboBox,设置它们的数据源,但它只向组合框添加了 1 个项目。

任何人都可以帮助我解决我搞砸的问题以及如何让它工作吗?

您发布的代码中存在多个问题。

显然,您要做的第一件事就是正确打开您的查询。如果您无法通过 运行 查询来获取数据,则无法使用该数据来填充组合框。在数据模块上测试 ADOConnection,看看是否可以通过将其 Connected 属性 设置为 True.

来连接到数据库

如果这不起作用,那么您需要正确设置 ConnectionString。 (确保将 Connected 属性 设置回 False。您应该在数据模块的 OnCreate 事件中连接,并在数据模块的 OnDestroy 事件中断开连接。 )

如果确实有效,请检查以确保将 ADOQuery 的 Connection 属性 设置为指向您的 ADOConnection,然后使用 ADOQuery.SQL 属性 输入你的 SQL 声明。完成后,将 ADOQuery.Active 属性 设置为 True。 (同样,不要忘记将其设置回 False 并在 运行 时在您的代码中打开它。)

接下来,您使用了错误的事件。您应该在表单的 OnCreate 事件中执行此操作。

此外,查询不需要同时使用 ActiveOpen。他们做同样的事情;它们之间的唯一区别是 Active 是一个可以测试的布尔值 属性 (if Query1.Active then) 而 Open 只是一个方法。没有理由打开已经激活的查询或激活已经打开的查询。

此外,您在方法末尾释放了查询,这意味着下次调用组合框 OnDropDown 事件时,您将访问无效的 class 实例,这将导致访问冲突。

最后,您应该在清除和填充组合框之前调用 BeginUpdate,然后在完成后调用 EndUpdate

更正确的代码版本应该是这样的

procedure TFormInsertNewItem.FormCreate(Sender: TObject);
begin
  with DataModule1 do
  begin
    {
      I'm not sure why you're doing this at all. If you set the ADOQuery.SQL property
      at designtime, and it never changes, you can remove the next two lines.
    }
    ADOQueryFillPartners.SQL.Clear;
    ADOQueryFillPartners.SQL.Add('SELECT name FROM Partners;');
    ADOQueryFillPartners.Active:=true;
    try  
      ComboBoxPartners.Items.BeginUpdate;
      while not ADOQueryFillPartners.Eof do begin
        ComboBoxPartners.Items.Add(ADOQueryFillPartners.FieldByName('name').AsString);
        ADOQueryFillPartners.Next;
      end;
    finally
      ComboBoxPartners.Items.EndUpdate;
    end;
    ADOQueryFillPartners.Active:=false;
  end;
end;