Мне нужно построить запрос SQL для чтения файла Excel через ODBC с Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)
.
Этот запрос требует условного оператора в SELECT
, который выражает "если столбец A
со страницы TA
имеет значение 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;
, который не работает, с ошибкой, рассказывающей истории об отсутствующих операторах или пропущенных полях ODBC, в зависимости от того, как я выразил условие (я использую объект vanilla 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
, но безрезультатно.
Как правильно выразить условие в запросе SQL, направленном на файл Excel через ODBC?
Редактировать: я знаю, предполагая, что невежество является нормой, поэтому позвольте мне прояснить: [A]
ЕСТЬ столбец в TA
, R1
и R2
просто выражают желаемые значения, в моем случае это буквальные значения (72
и 70
соответственно). Мои запросы также намного больше, запрашивая несколько столбцов из joins
с wheres
и order by
, и все мои запросы работали до сих пор, с простыми CRecordset
объектами, которые я бы назвал GetFieldValue
. Любой запрос, к которому я добавил условный оператор, начал давать сбой. Я тщательно отладил свою работу, и, насколько я могу судить, запросы правильно отформатированы (без пропущенных скобок или чего-то подобного). У меня также нет фактического знания, что эти заявления не поддерживаются; исправление моего синтаксиса, которое будет работать, приветствуется.
Я НЕ МОГУ просто получить TA.A
, затем обработать его значение в коде, и Я НЕ МОГУ использовать API или другой драйвер для доступа к данным.
Edit2:
@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 () ;
}
Поскольку ответ Парфе верен, я отмечу его как таковой. Я все равно буду приветствовать объяснение того, что случилось, если у кого-то есть это.