【问题标题】:How to read columns names in table in ESE using C language and esent.lib?如何使用 C 语言和 esent.lib 在 ESE 中读取表中的列名?
【发布时间】:2020-10-14 01:36:11
【问题描述】:

我需要一个代码示例。我想看看我们如何枚举表中的列名。 (对我来说使用esent.dll/esent.lib和C语言是必不可少的)

我尝试使用附加代码(找到了一个指南,但它没有按我的预期工作)。

    JET_COLUMNLIST column_info;

    JET_RETRIEVECOLUMN j_rc[4];
    err = JetGetTableColumnInfo(sessionID, curr_table.tableID, NULL, &column_info, sizeof(JET_COLUMNLIST), JET_ColInfoList);

    j_rc[0].columnid = column_info.columnidcolumnname;
    j_rc[0].cbData = sizeof(char)*JET_cbNameMost;
    j_rc[0].itagSequence = 1;
    j_rc[0].grbit = 0;
    char buf[JET_cbNameMost] = { 0 };
    j_rc[0].pvData = buf;


    printf("\nRetrieving columns information:\n");
    printf("Row\tId\tType\tName:\n");

    unsigned long columns_qnt = 0;
    for (err = JetMove(sessionID, curr_table.tableID, JET_MoveFirst, 0);
        JET_errSuccess == err;
        err = JetMove(sessionID, curr_table.tableID, JET_MoveNext, 0))
    {
        err = JetRetrieveColumns(sessionID, curr_table.tableID, j_rc, 4);

        columns_qnt++;

        printf("%u\t%s\n", columns_qnt, buf);

        memset(buf, 0, JET_cbNameMost);
    }

请举个例子。如果您知道 ESE C 编程的优秀指南或只是一些描述其工作原理的资源,请与我分享。 (尽管我在 google 上搜索了很多,但不要羞于分享明显的资源)

【问题讨论】:

    标签: c extensible-storage-engine


    【解决方案1】:

    内部表“MSysObjects”(作为服务表存在于每个 ESE 数据库中)有 2 个对我们有用的列:“类型”和“名称”。

        JetOpenTable(sessionID, dbid, "MSysObjects", NULL, NULL, JET_bitTableSequential, &tableID); 
    
        JET_COLUMNBASE j_cb_name, j_cb_type, j_cb_coltype;
    
        JetGetColumnInfo(sessionID, dbid, "MSysObjects", "Name", &j_cb_name, sizeof(JET_COLUMNBASE), JET_ColInfoBase);
    
        JetGetColumnInfo(sessionID, dbid, "MSysObjects", "Type", &j_cb_type, sizeof(JET_COLUMNBASE), JET_ColInfoBase);
    
        JET_RETRIEVECOLUMN j_rc[2];
    

    这里我们填充结构 JET_RETRIEVECOLUMN 以通过 JetRetrieveColumns 获取这 2 列

        j_rc[0].columnid = j_cb_name.columnid;
        j_rc[0].cbData = 1024;
        j_rc[0].itagSequence = 1;
        j_rc[0].grbit = NULL;
        char buf[1024] = { 0 };
        j_rc[0].pvData = buf;
    
        j_rc[1].columnid = j_cb_type.columnid;
        j_rc[1].cbData = sizeof(unsigned short);
        j_rc[1].itagSequence = 1;
        j_rc[1].grbit = NULL;
        unsigned short type;
        j_rc[1].pvData = &type;
    
        for (err = JetMove(sessionID, root_tableID, JET_MoveFirst, 0);
            JET_errSuccess == err;
            err = JetMove(sessionID, root_tableID, JET_MoveNext, 0))
        {
            JetRetrieveColumns(sessionID, root_tableID, j_rc, 2);
    

    我们在这里找到了它们。如果 type == 1 这意味着,我们得到的记录是在描述一个表,如果 type == 2,那么它是在描述一个列。 (还有其他类型)有严格的顺序,首先你会得到类型 1(表)的记录,然后你会得到类型 2 的记录,描述该表的列(在那一刻 buf 保留列名),然后你可以获取引用该表的其他类型(type == 1 除外)的记录。最后你会得到类型 1 的记录,这意味着我们得到的下一个信息是关于另一个表的。

        }
    

    请随意说我的英语很糟糕,我写了一些垃圾,然后我会尝试用其他方式解释:)

    【讨论】:

      【解决方案2】:

      如果您只想要一个特定表的列名列表,而不使用 MSysObjects,这是我的方法。由“JetGetTableColumnInfo”创建的临时表只包含列ID和列名,所以很快:

      JET_ERR GetEseTableColumnNames(JET_SESID hEseSession, JET_TABLEID hEseTable)
      {  JET_ERR        rc;
         JET_COLUMNLIST cl { };
      
         /* Sort order for the temporary table is column name order */
         rc = ::JetGetTableColumnInfo(hEseSession, hEseTable, nullptr, &cl, sizeof(cl), JET_ColInfoList | JET_ColInfoGrbitMinimalInfo);
      
         /* Temporary table ("cl.tableid") is opened and positioned on first record */
         if (rc == JET_errSuccess && cl.cRecord > 0)
         {  wchar_t       wszColumnName[MAX_ESE_OBJECT_NAME + 1]; // ESE doesn't play well with std::strings
            unsigned long cbActual;
      
            for (uint32_t i = 0; i < cl.cRecord; ++i)
            {
               rc = ::JetRetrieveColumn(hEseSession, cl.tableid, cl.columnidcolumnname, wszColumnName, sizeof(wszColumnName), &cbActual, 0, nullptr);
               if (rc == JET_errSuccess)
               {
                  /* ESE does not null terminate strings */
                  wszColumnName[cbActual / sizeof(wchar_t)] = L'\0';
      
                  //********
                  // Okay, so do something with the column name here
                  //********
      
                  /* Next record in temporary table */
                  if (i < cl.cRecord - 1)
                     ::JetMove(hEseSession, cl.tableid, JET_MoveNext, 0);
               }
               else
                  break;
            }
         }
      
         /* Close the temporary table */
         ::JetCloseTable(hEseSession, cl.tableid);
      
         return rc;
      }
      

      我知道其他人使用 MSysObjects 来缩短流程,但这对我来说很好。是的,我的代码看起来过时了 - 我被困在匈牙利语中!

      【讨论】:

        猜你喜欢
        • 2015-04-17
        • 1970-01-01
        • 1970-01-01
        • 2011-06-24
        • 1970-01-01
        • 1970-01-01
        • 2020-03-30
        • 2021-12-31
        • 2011-06-08
        相关资源
        最近更新 更多