简体   繁体   English

ODBC Excel SQL 条件

[英]ODBC Excel SQL Condition

I need to build a SQL query to read an Excel file, through ODBC with the Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) .我需要构建一个 SQL 查询来读取 Excel 文件,通过 ODBC 和Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)

That query needs a conditional statement in the SELECT that expresses "if the column A from the page TA has the value x , then R1 , else R2 ", R1 and R2 being values of the same type ( 0 and 1 or 'ABC' and 'DEF' ).该查询在SELECT中需要一个条件语句,该SELECT表示“如果页面TA的列A的值为x ,则为R1 ,否则为R2 ”, R1R2是相同类型的值( 01'ABC''DEF' )。

With CASE it would normally give使用CASE它通常会给出

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

or或者

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

This creates an error saying there's a missing operator.这会产生一个错误,指出缺少运算符。

Looking around I've read that Access (because no one gives a darn about Excel) does not have the CASE statement.环顾四周,我读到 Access(因为没有人对 Excel 一无所知)没有CASE语句。

I've then tried the IIF statement,然后我尝试了IIF语句,

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

which doesn't work, with an error telling tales about either missing operators or missing ODBC fields depending on how I expressed the condition (I use a vanilla CRecordset object, it fails on the Open call, and I don't do DoFieldExchange nowhere),这不起作用,根据我表达条件的方式(我使用普通CRecordset对象,它在Open调用中失败,并且我没有在任何地方执行DoFieldExchange ) ,

then I tried the SWITCH statement然后我尝试了SWITCH语句

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

which failed too ("Too few arguments. 1 expected."), then I tried the CHOOSE statement也失败了(“参数太少。预期为 1。”),然后我尝试了CHOOSE语句

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

which, surprisingly, doesn't work, with the same results.令人惊讶的是,它不起作用,结果相同。

I also tried all these queries with RA = ... instead of ... AS RA , to no avail.我也用RA = ...而不是... AS RA尝试了所有这些查询,但无济于事。

How do I properly express a condition in a SQL query aimed at an Excel file through ODBC?如何通过 ODBC 在针对 Excel 文件的 SQL 查询中正确表达条件?

Edit: I know presuming ignorance is the norm in there, so let me be clear, [A] IS a column in TA , R1 and R2 just express the desired values, in my case those are literal values ( 72 and 70 respectively).编辑:我知道假设无知是那里的常态,所以让我说清楚, [A]TA一列, R1R2只是表达所需的值,在我的情况下,这些是字面值(分别为7270 )。 My queries are also far larger, requesting multiple columns from joins with wheres and an order by , and all my queries worked well until now, with simple CRecordset objects that I'd call GetFieldValue from.我的查询也大得多,从带有wheresorder by joins请求多列,到目前为止我所有的查询都运行良好,使用简单的CRecordset对象,我会从中调用GetFieldValue Any query I added a conditional statement to started to fail.我添加了条件语句的任何查询都开始失败。 I've extensively debugged my work and the queries are correctly formatted as far as I can tell (no missing parentheses or such).我已经对我的工作进行了广泛的调试,并且就我所知,查询的格式正确(没有缺少括号等)。 I also have no Actual Knowledge that these statements are unsupported;我也不知道这些陈述是不受支持的; a correction on my syntax that would work is welcome.欢迎对我的语法进行更正。

I CANNOT simply get TA.A then handle its value in code and I CANNOT use an API or a different driver to access the data.我不能简单地获取TA.A然后在代码中处理它的值,我不能使用 API 或不同的驱动程序来访问数据。

Edit2: @Parfait:编辑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: This is CPP/Cli. Edit3:这是CPP/Cli。

The Jet and Ace data providers work with OLEDB objects, I don't know that you can use them with CDatabase/CRecordset. Jet 和 Ace 数据提供程序使用 OLEDB 对象,我不知道您可以将它们与 CDatabase/CRecordset 一起使用。

I went back to this after the week-end, rebuild my query, checked all the table names, file paths, column names etc, tried an IFF, and it worked.周末后我又回到了这个问题,重建我的查询,检查所有的表名、文件路径、列名等,尝试了一个 IFF,它起作用了。 With the Microsoft Excel Driver and all.使用 Microsoft Excel 驱动程序等。 I'm assuming I made a syntax error somewhere but I can't for the life of me figure what it was.我假设我在某个地方犯了一个语法错误,但我一生都无法弄清楚它是什么。 Anyways here is the query that ended working:无论如何,这里是结束工作的查询:

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

Since Parfait's answer is correct, I'll mark it as such.由于 Parfait 的答案是正确的,我将其标记为正确。 I'll still welcome an explanation as to what happened, if anyone has it.我仍然欢迎对发生的事情的解释,如果有人有的话。

Querying Excel workbooks in Windows environments would involve the JET/ACE SQL engine (Windows .dll files) which is the very same engine used in MS Access.在 Windows 环境中查询 Excel 工作簿将涉及 JET/ACE SQL 引擎(Windows .dll 文件),它与 MS Access 中使用的引擎完全相同。 Since this SQL dialect does not support ANSI's CASE statement, the best equivalent would be the IIF function .由于此 SQL 方言不支持 ANSI 的CASE语句,因此最好的等效项是IIF函数 From your statement:从你的陈述:

[A] IS a column in TA, R1 and R2 just express the desired values [A]是TA中的一列,R1和R2只是表达想要的值

Then, your IIF expression must treat the test and desired values as quoted literals if using alphanumerics.然后,如果使用字母数字,您的IIF表达式必须将测试和所需值视为带引号的文字。 Otherwise the engine assumes they are fields in table.否则引擎假定它们是表中的字段。 Do note: you can use actual columns in IIF .请注意:您可以IIF使用实际列。 Also, use a table alias for TA designation.此外,使用表别名来指定TA

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

And for number values as used in attempted code, do not quote them.对于尝试代码中使用的数值,不要引用它们。 In both expressions you are implicitly assigning a data type (string and integer respectively) while explicitly assigning values to new calculated column, RA :在这两个表达式中,您隐式分配数据类型(分别为字符串和整数),同时为新计算列RA显式分配值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM