ODBC Excel SQL条件

问题描述 投票:2回答:1

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

该查询需要在SELECT中的条件语句表达“如果A页面中的TA列具有值x,则R1,否则R2”,R1R2是相同类型的值(01'ABC''DEF') 。

通过CASE它通常会给

SELECT CASE A WHEN x THEN R1 ELSE R2 END AS RA FROM TA;

要么

SELECT CASE WHEN A = x THEN R1 ELSE R2 END AS RA FROM TA;

这会产生一个错误,表示缺少运算符。

环顾四周我已经读过Access(因为没有人对Excel有关)没有CASE声明。

我接着尝试了IIF声明,

SELECT IIF (A = x, R1, R2) AS RA FROM TA;

哪个不起作用,错误告诉故事有关丢失的操作符或缺少ODBC字段取决于我如何表达条件(我使用香草CRecordset对象,它在Open调用失败,我不做DoFieldExchange无处) ,

然后我尝试了SWITCH声明

SELECT SWITCH (A = x, R1, true, R2) AS RA FROM TA;

哪个也失败了(“太少的争论.1预期。”),然后我尝试了CHOOSE声明

SELECT CHOOSE (1*(A = x), R1, R2) AS RA FROM TA;

令人惊讶的是,它不起作用,结果相同。

我也用RA = ...而不是... AS RA尝试了所有这些查询,但无济于事。

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

编辑:我知道假设无知是那里的常态,所以让我明白,[A]TA中的一列,R1R2只是表达了所需的值,在我的情况下,这些是字面值(分别是7270)。我的查询也要大得多,从joins请求wheresorder by的多个列,我所有的查询都运行良好,直到现在,我用CRecordset来简单的GetFieldValue对象。任何查询我都添加了条件语句以开始失败。我已经广泛调试了我的工作,并且我已经知道了查询格式正确(没有丢失的括号等)。我也没有实际知识这些陈述不受支持;我的语法更正可行。

我不能简单地让TA.A处理它在代码中的值,我不能使用API​​或不同的驱动程序来访问数据。

Edit2:@Perfect:

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。

Jet和Ace数据提供程序使用OLEDB对象,我不知道您可以将它们与CDatabase / CRecordset一起使用。

我在周末结束后回到了这里,重建了我的查询,检查了所有表名,文件路径,列名等,尝试了IFF,并且它有效。使用Microsoft Excel驱动程序和所有。我假设我在某个地方犯了语法错误,但我不能为我的生活弄清楚它是什么。无论如何这里是结束工作的查询:

if (!here_rs->Open (CRecordset::snapshot,
    "SELECT"
    "   `A`,"
    "   IIF(`A` = x, 72, 70) AS RA"
    " FROM `TableA$`"
    "", CRecordset::readOnly))
{
    __debugbreak () ;
}

由于Parfait的答案是正确的,我会将其标记为正确。我仍然会欢迎解释发生了什么,如果有人的话。

sql excel odbc case clr
1个回答
1
投票

在Windows环境中查询Excel工作簿将涉及JET / ACE SQL引擎(Windows .dll文件),这与MS Access中使用的引擎完全相同。由于这个SQL方言不支持ANSI的CASE语句,最好的等价物是IIF function。从你的陈述:

[A]是TA中的一列,R1和R2只表示所需的值

然后,如果使用字母数字,你的IIF表达式必须将测试和所需的值视为带引号的文字。否则引擎会假定它们是表中的字段。请注意:您可以使用IIF中的实际列。另外,使用表别名进行TA指定。

SELECT IIF(TA.A = 'test', 'R1', 'R2') AS RA 
FROM [TableA$] AS TA

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

SELECT IIF(TA.A = 'test', 72, 70) AS RA 
FROM [TableA$] AS TA
© www.soinside.com 2019 - 2024. All rights reserved.