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
"、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;
这不起作用,根据我表达条件的方式,错误告诉我缺少运算符或缺少 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]
是 TA
、R1
和 R2
中的一个专栏表达所需的值,在我的例子中,这些是文字值(分别为 72
和 70
)。我的查询也大得多,使用 wheres
和 order by
从 joins
请求多个列,直到现在我的所有查询都运行良好,我使用简单的 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
我需要构建一个 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
"、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;
这不起作用,根据我表达条件的方式,错误告诉我缺少运算符或缺少 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]
是 TA
、R1
和 R2
中的一个专栏表达所需的值,在我的例子中,这些是文字值(分别为 72
和 70
)。我的查询也大得多,使用 wheres
和 order by
从 joins
请求多个列,直到现在我的所有查询都运行良好,我使用简单的 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