首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ODBC Excel SQL条件

ODBC Excel SQL条件
EN

Stack Overflow用户
提问于 2019-03-08 14:35:58
回答 1查看 1.6K关注 0票数 2

我需要通过ODBC和Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb).构建SQL查询来读取Excel文件。

该查询需要SELECT中的一个条件语句,该语句表示“如果来自页面TA的列A的值为x,则为R1,否则为R2",R1R2为相同类型的值(01'ABC'd14)。

对于CASE,它通常会给出

代码语言:javascript
运行
复制
SELECT CASE A WHEN x THEN R1 ELSE R2 END AS RA FROM TA;

代码语言:javascript
运行
复制
SELECT CASE WHEN A = x THEN R1 ELSE R2 END AS RA FROM TA;

这会产生一个错误,说明缺少一个操作符。

环顾四周,我读到了Access (因为没有人给出关于Excel的消息)没有CASE语句。

然后我尝试了IIF语句,

代码语言:javascript
运行
复制
SELECT IIF (A = x, R1, R2) AS RA FROM TA;

这不起作用,错误地讲述了丢失运算符或缺少ODBC字段取决于我表达条件的方式(我使用普通的CRecordset对象,它在Open调用中失败,并且我没有在任何地方执行DoFieldExchange ),

然后我尝试了SWITCH语句

代码语言:javascript
运行
复制
SELECT SWITCH (A = x, R1, true, R2) AS RA FROM TA;

这也失败了(“参数太少。1期望。”),然后我尝试了CHOOSE语句。

代码语言:javascript
运行
复制
SELECT CHOOSE (1*(A = x), R1, R2) AS RA FROM TA;

但令人惊讶的是,结果却是一样的。

我还用RA = ...而不是... AS RA尝试了所有这些查询,但都没有效果。

如何通过ODBC在针对Excel文件的SQL查询中正确地表示条件?

编辑:我知道假定无知是那里的规范,所以让我明确一点,[A]是TA、R1和R2中的一个列,只表示想要的值,在我的例子中,它们是文字值(72和70 )。我的查询也要大得多,使用wheres和order by从wheres请求多个列,到目前为止,我的所有查询都运行良好,使用了简单的CRecordset对象,我可以从这些对象中调用GetFieldValue。任何我添加了条件语句的查询都开始失败。我已经广泛地调试了我的工作,就我所知,查询的格式是正确的(没有遗漏括号之类的)。我也不知道这些声明是不受支持的;对我的语法进行更正是值得欢迎的。

我不能简单地获得TA.A,然后在代码中处理它的值,也不能使用API或其他驱动程序来访问数据。

Edit2:@Parfait:

代码语言:javascript
运行
复制
CDatabase *here_db = new CDatabase () ;
here_db->OpenEx ("Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:\\ExcelFile.xls") ;
CRecordset *here_rs = new CRecordset (here_db) ;
here_rs->Open (CRecordset::snapshot, "SELECT COUNT(*) FROM [TableA$]", CRecordset::readOnly) ;
//This works, btw.
int rowCount ;
CDBVariant v ;
here_rs->GetFieldValue ((short) 0, v, SQL_C_SLONG) ;
rowCount = v.m_lVal ;
here_rs->Close () ;
here_rs->Open (CRecordset::snapshot, CString (
    "SELECT"
    " CASE A"
    "   WHEN 'test' THEN 72"
    "   ELSE 70"
    " END AS RA"
    " FROM [TableA$]"
    ""), CRecordset::readOnly) ;
short i ;
int colCount ;
colCount = here_rs->GetODBCFieldCount () ;
CString h ("") ;
while (!here_rs->IsEOF ())
{
    for (i = 0; i < c; i++)
    {
        here_rs->GetFieldValue (i, h) ;
    }
    here_rs->MoveNext () ;
}
here_rs->Close () ;
delete here_rs ;
here_db->Close () ;
delete here_db ;
return TRUE ;

Edit3:我是CPP/Cli。

CDatabase数据提供者使用OLEDB对象,我不知道您是否可以将它们与CDatabase/CRecordset一起使用。

在周末之后,我又回到了这个问题,重新构建了我的查询,检查了所有的表名、文件路径、列名等等,尝试了IFF,它成功了。使用Microsoft驱动程序等等。我假设我在某个地方犯了语法错误,但我无法理解它是什么。无论如何,这里是结束工作的查询:

代码语言:javascript
运行
复制
if (!here_rs->Open (CRecordset::snapshot,
    "SELECT"
    "   `A`,"
    "   IIF(`A` = x, 72, 70) AS RA"
    " FROM `TableA$`"
    "", CRecordset::readOnly))
{
    __debugbreak () ;
}

既然Parfait的答案是正确的,我就把它标记成这样。如果有人知道的话,我还是欢迎你解释一下发生了什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-08 17:22:23

在Windows环境中查询Excel工作簿将涉及JET/ Access引擎(Windows .dll文件),这是MS Access中使用的完全相同的引擎。因为这个SQL方言不支持ANSI的CASE语句,所以最好的等效语言是 function。从你的发言中:

A是TA、R1和R2中的一个列,仅表示所需的值。

然后,如果使用字母数字,您的IIF表达式必须将测试和所需的值以引号形式处理。否则,引擎假设它们是表中的字段。注意:您可以在IIF中使用实际的列。另外,使用表别名来指定TA。

代码语言:javascript
运行
复制
SELECT IIF(TA.A = 'test', 'R1', 'R2') AS RA 
FROM [TableA$] AS TA

对于尝试代码中使用的数字值,不要引用它们。在这两个表达式中,您都在隐式分配数据类型(分别为字符串和整数),同时显式地将值赋值给新的计算列( RA )。

代码语言:javascript
运行
复制
SELECT IIF(TA.A = 'test', 72, 70) AS RA 
FROM [TableA$] AS TA
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55065382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档