ODBC Excel SQL 条件

ODBC Excel SQL Condition

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

该查询需要 SELECT 中的条件语句,表示 "if the column A from the page TA has the value x, then R1, else 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;

也失败了("Too few arguments. 1 expected."),然后我尝试了CHOOSE语句

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

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

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

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

编辑:我知道假设无知是那里的常态,所以让我说清楚,[A]TAR1R2 中的一个专栏表达所需的值,在我的例子中,这些是文字值(分别为 7270)。我的查询也大得多,使用 wheresorder byjoins 请求多个列,直到现在我的所有查询都运行良好,我使用简单的 CRecordset 对象d 调用 GetFieldValue 来自。我添加条件语句的任何查询开始失败。我已经广泛调试了我的工作,并且据我所知查询的格式正确(没有遗漏括号等)。我也不知道这些陈述不受支持;欢迎对我的语法进行更正。

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

编辑2: @芭菲:

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 一起使用。

周末后我又回到这个问题上,重建我的查询,检查所有 table 名称、文件路径、列名等,尝试了 IFF,它成功了。使用 Microsoft Excel 驱动程序和所有。我假设我在某处犯了一个语法错误,但我终究无法弄清楚它是什么。无论如何,这是结束工作的查询:

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

既然Parfait的回答是正确的,我就这样标记它。如果有人知道发生了什么,我仍然欢迎解释。

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

[A] IS a column in TA, R1 and R2 just express the desired values

然后,如果使用字母数字,您的 IIF 表达式必须将测试值和所需值视为带引号的文字。否则引擎假定它们是 table 中的字段。请注意:您 可以 使用 IIF 中的实际列。此外,使用 table 别名作为 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