ODBC Excel SQL Условие - PullRequest
       9

ODBC Excel SQL Условие

2 голосов
/ 08 марта 2019

Мне нужно построить запрос 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 () ;
}

Поскольку ответ Парфе верен, я отмечу его как таковой. Я все равно буду приветствовать объяснение того, что случилось, если у кого-то есть это.

1 Ответ

1 голос
/ 08 марта 2019

Для запросов к книгам Excel в среде Windows может потребоваться механизм SQL JET / ACE (файлы .dll Windows), который является тем же механизмом, который используется в MS Access. Поскольку этот диалект SQL не поддерживает оператор ANSI CASE, лучшим эквивалентом будет функция IIF . Из вашего заявления:

[A] - это столбец в TA, R1 и R2 просто выражают желаемые значения

Тогда ваше выражение IIF должно обрабатывать тест и желаемые значения как кавычки, если используются алфавитно-цифровые символы. В противном случае двигатель предполагает, что они являются полями в таблице. Обратите внимание: вы можете использовать фактические столбцы в IIF. Также используйте псевдоним таблицы для обозначения 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...