【问题标题】:ADO - how to get primary key fieldsADO - 如何获取主键字段
【发布时间】:2013-07-26 15:05:08
【问题描述】:

我正在使用 ADO(Delphi 和 C++ Builder),我想获取一些 TADOTable 组件中的主键字段(它们的名称)。怎么做?

我发现我需要使用 ADOConnection->OpenSchema 但不知道如何使用它..

现在我尝试了这个:

int bounds[] = {0,2};
OleVariant A(bounds,1, varVariant);
A.PutElement(varEmpty,0);
A.PutElement(varEmpty,1);
A.PutElement("MyDBTable",2);


OleVariant EmptyParam;
EmptyParam.VType = VT_ERROR;
EmptyParam.VError = DISP_E_PARAMNOTFOUND;
TADODataSet *temp = new TADODataSet(NULL);

AdoConnection1->OpenSchema(siPrimaryKeys, A, EmptyParam, temp);
temp->Open();
temp->First();
while (!temp->Eof)
{
    Memo1->Lines->Add(temp->Fields->Fields[0]->AsString);
    temp->Next();
}
temp->Close();
delete temp;

运行此代码时,我得到:“对象或提供者无法执行请求的操作。”?

【问题讨论】:

    标签: database delphi ado c++builder vcl


    【解决方案1】:

    参考OpenSchema Method (ADO),示例可参见here

    Delphi 中 Microsoft Access 和 MSSqlServer 的示例实现如下所示:

    Procedure OpenPrimaryKeyInfo ( Connection:TAdoConnection
                                 ; DatabaseName , SchemaName , TableName : Variant
                                 ; Display:TAdodataset );
    begin
      Connection.OpenSchema( siPrimaryKeys
                            , VarArrayOf([ DatabaseName , SchemaName , TableName ])
                            , EmptyParam , Display );
    end;
    

    Microsoft Access 调用示例:

    OpenPrimaryKeyInfo( AdoConnection2 , UnAssigned , UnAssigned , 'TableX' , Adodataset1 );
    

    MSSqlServer 调用示例:

    OpenPrimaryKeyInfo( AdoConnection1 , 'MyDataBase' , 'dbo' , 'TableX' , Adodataset1 );
    

    【讨论】:

    • 这看起来很棒。只是..如何在 C++ Builder 中编写 VarArrayOf([ DatabaseName , SchemaName , TableName ]) ?
    • @Tracer:documentation 向您展示了 C++ Builder 语法(该页面底部还有指向 C++ 代码示例的链接)。
    【解决方案2】:

    您像往常一样建立连接并打开它(使用TADOConnection.ConnectionStringTADOConnection.Open),然后使用OpenSchema 请求架构。您作为最后一个参数提供的 TADODataSet 将包含一个 RecordSet,您可以像使用任何其他数据集一样使用它。

    这是我放在一起的一个快速示例(感谢@bummi 对第三个参数的更正 - UnassignedNull 都已编译,但在测试时实际上并没有工作)。我在一个新表单上删除了TADOConnectionTADODataSetTMemo,并快速配置了TADOConnection 以指向一个简单的SQL Server Express 数据库,我有一些测试用——我包含了连接字符串;我对其所做的唯一更改是在Data Source 部分中提供的计算机名称中)。

    procedure TForm3.FormShow(Sender: TObject);
    var
      i: Integer;
      sLine: string;
    begin
      Memo1.Clear;
      ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;' +
                                         'Integrated Security=SSPI;' + 
                                         'Persist Security Info=False;' +
                                         'Initial Catalog=Contacts;' +
                                         'Data Source=MyComputer\SQLEXPRESS';
      ADOConnection1.Connected := True;
      ADOConnection1.OpenSchema(siPrimaryKeys, Unassigned, EmptyParam, ADODataSet1);
      sLine := '';
      for i := 0 to ADODataSet1.FieldCount - 1 do
        sLine := sLine + ADODataSet1.Fields[i].FieldName + #9;
      Memo1.Lines.Add(sLine);
      Memo1.Lines.Add('');
    
      while not ADODataSet1.Eof do
      begin
        sLine := '';
        for i := 0 to ADODataSet1.FieldCount - 1 do
          sLine := sLine + ADODataSet1.Fields[i].AsString + #9;
        Memo1.Lines.Add(sLine);
        ADODataSet1.Next;
      end;
    end;
    

    SchemaInfo 值的可能值(传递给 OpenSchema 的第一个参数)可以在 ADODB 单元中找到 - 它们记录在 Delphi help file 中(请注意,文档中说并非所有其中可通过 ADO 获得):

    TSchemaInfo = (siAsserts, siCatalogs, siCharacterSets, siCollations,
      siColumns, siCheckConstraints, siConstraintColumnUsage,
      siConstraintTableUsage, siKeyColumnUsage, siReferentialConstraints,
      siTableConstraints, siColumnsDomainUsage, siIndexes, siColumnPrivileges,
      siTablePrivileges, siUsagePrivileges, siProcedures, siSchemata,
      siSQLLanguages, siStatistics, siTables, siTranslations, siProviderTypes,
      siViews, siViewColumnUsage, siViewTableUsage, siProcedureParameters,
      siForeignKeys, siPrimaryKeys, siProcedureColumns, siDBInfoKeywords,
      siDBInfoLiterals, siCubes, siDimensions, siHierarchies, siLevels,
      siMeasures, siProperties, siMembers, siProviderSpecific);
    

    【讨论】:

    • 第二个 Unassigned 不需要是 EmptyParam,我无法让它与 Unassigned 一起使用。
    • @bummi:是的,你完全正确。它同时使用NullUnassigned 编译,但在实际运行代码时失败。我已对其进行了更正(并为您发现了适当的信用),并包含了实际的工作测试代码。谢谢你的收获。 (顺便说一句,我已经赞成你的回答。):-)
    猜你喜欢
    • 2022-12-14
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    相关资源
    最近更新 更多