【发布时间】:2019-07-30 14:44:16
【问题描述】:
我需要使用 Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) 通过 ODBC 构建一个 SQL 查询来读取 Excel 文件。
该查询需要SELECT 中的条件语句,表示“如果页面TA 中的列A 具有值x,则R1,否则R2”,R1和 R2 是相同类型的值(0 和 1 或 '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;
这不起作用,根据我如何表达条件(我使用香草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、R1 和R2 中的一列,只是表达了所需的值,在我的情况下是文字值(分别为72 和70)。我的查询也大得多,从joins 和wheres 和order by 请求多个列,到目前为止,我的所有查询都运行良好,使用简单的CRecordset 对象,我将其称为GetFieldValue。我添加条件语句以开始失败的任何查询。我已经对我的工作进行了广泛的调试,并且据我所知,查询的格式正确(没有丢失括号等)。我也不知道这些陈述是不受支持的;欢迎对我的语法进行更正。
我不能简单地获取 TA.A 然后在代码中处理它的值,我不能使用 API 或不同的驱动程序来访问数据。
编辑2: @Parfait:
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 的答案是正确的,我就这样标记它。如果有人知道,我仍然欢迎解释发生的事情。
【问题讨论】:
-
这是什么语言?请标记它。