Ms Access (sql-запрос)

Тема в разделе "MS Visual C++", создана пользователем VSergV, 11 окт 2007.

Статус темы:
Закрыта.
  1. VSergV

    VSergV Гость

    Помогите. Очень нужно из-за этого затыка проект горит.
    Я открыл соединение с БД послал SQL-запрос через CRecordset s(BD); s.open(...,"SELECT * FROM <TableName>;") А мне выскочила ошибка от BD: Недопустимое символьное значение для указания отклонения на строке номер 5(PlantNumber). Запускал в запрос в самом Access все работает как часики. В чем может быть проблема??? Спасибо зарание всем.... Пишите на VSergV@inbox.ru :)
     
  2. grigsoft

    grigsoft Well-Known Member

    Регистрация:
    15 ноя 2005
    Сообщения:
    735
    Симпатии:
    0
    А обрамление <> правильное для имени таблицы? Я с драйвером access не работал, но вроде обычно [] используются в ODBC\DAO.
     
  3. VSergV

    VSergV Гость

    На данное обрамление не обращайте внимания я просто поставил чтобы показать что имя может быть любое....

    Мне а так там написан запрос: "SELECT * FROM UnitedTable;"

    Help me
     
  4. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    Судя по ошибке, после открытия ты перемещаешь курсор... Или я не прав?
     
  5. VSergV

    VSergV Гость

    А в чем ошибка?? вроде в том чтоя написал: "SELECT * FROM UnitedTable;"
    ошибки нет это стандартный запрос "взять все записи из таблицы".... :)

    а обрамления в запросе небыло... Я же говорил что я всего лишь хотел обрамлением показать что, это имя может быть любы но не значит что я именно так и написал....(((( :(
     
  6. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    <!--QuoteBegin-VSergV+12:10:2007, 22:56 -->
    <span class="vbquote">(VSergV @ 12:10:2007, 22:56 )</span><!--QuoteEBegin-->ошибки нет это стандартный запрос "взять все записи из таблицы".
    [snapback]81606" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Покажи больше кода
     
  7. skysun

    skysun Гость

    SELECT * FROM UnitedTable;

    В коде точка с запятой есть?
    Если память не подводит, там в отличии от ахеса точка с запятой должна отсутствовать.

    Если работаешь с ахесом старых версий, лучше используй CDaoRecordset, а еще лучще OLEDB
     
  8. VSergV

    VSergV Гость

    Я работаю с Office2003 вот. Пробывал с точкой с запятой и без и так и так не помогает(((( всеравно выдаёт эту гр*цензура*ю ошибку..
     
  9. VSergV

    VSergV Гость

    А код выглядит так:
    *.h
    CDatabase*m_Db;
    CRecordset* m_pSet;
    В конструкторе я создал динамически обьект:
    *.cpp
    m_Db = NULL;
    m_Db = new CDatabase();
    m_Db->Open( "WafersDate.mdb",FALSE,TRUE,_T("ODBC;"));
    после я содал динамически
    m_pSet = new CRecordset(m_Db);
    после когда все соединения установленны посылаю запрос:
    SQLrequest.Format("SELECT * FROM UnatedTable" );
    m_pSet->Open(CRecordset::forwardOnly, SQLrequest, CRecordset::readOnly );
    m_pSet->Close();
    P.S.: Да обьект m_pSet создан от класса CWorkWith_BD(m_Db); который является наследником CRecordset и создан с помощью Wizard(a)... Так что я думаю что ошибки в общем исключены(((( :angry:
     
  10. skysun

    skysun Гость

    Код (Text):
    CDatabase*m_Db;
    CRecordset* m_pSet;
    CString SQLrequest;
    CString strVal;

    m_Db = NULL;
    m_Db = new CDatabase();
    m_Db->Open("InterFace",FALSE,TRUE,_T("ODBC;"),TRUE);
    m_pSet = new CRecordset(m_Db);
    SQLrequest.Format("SELECT * FROM [данные]" );
    m_pSet->Open(CRecordset::forwardOnly, SQLrequest, CRecordset::readOnly );
    m_pSet->GetFieldValue(1,strVal);
    m_pSet->GetFieldValue(2,strVal);
    m_pSet->Close();
    Все работает?!

    Используешь в качестве провайдера ODBC?
    Если да то замени в вызвове
    имя mdb-ки на имя источника данных, заранее зарегистрированного в ODBC.

    И еще разница между моим кодом и твоим в том, что я использовал непосредственно CRecorset а ты его потомка. Хотя проблем быть не должно, проверь (
    )
    может он уже открыт, и ты повторно его пытаешься его открыть.
     
  11. SunSanych

    SunSanych Well-Known Member

    Регистрация:
    28 июн 2006
    Сообщения:
    71
    Симпатии:
    0
    У меня когда-то тоже была проблема при работе с CRecordset. А именно при работе со строками.
    В класс-наследник от CRecordset помощник из VisualStudio для каждого возвращаемого поля создает член-переменную. Для строковых полей создаётся член-переменная типа CString.
    Далее, в процессе выполнения запроса эти переменные заполняются данными из запроса в виртуальной функции DoFieldExchange() класса-наследника.
    В DoFieldExchange() для каждого типа вызываются свои функции обмена вида RFX_тип. Для строкового типа это RFX_Text().
    А теперь самая суть. Функций RFX_Text() несколько, с разными типами входных параметров. Но все они в итоге сводятся к одной в которую передаются указатель на буфер и его максимальный размер. Этот максимальный размер передаётся как необязательный параметр по-умолчанию равный 255, а конструктор CString по-умолчанию создаёт буфер размером 64 байта (не уверен но меньше 255 точно) который и попадает в RFX_Text(). Получаем банальное переполнение памяти.
    Выхода может быть два, или передавать в параметр RFX_Text() nMaxLength размер буфера CString, но тогда данные скорее всего будут урезаться. Или увеличивать размер буфера до 255 и более.
    Примерно так:
    Код (Text):
    CChild::DoFieldExchange(CFieldExchange* pFX)
    {
    // m_str - член-переменная класса CChild
    RFX_Text(pFX, _T("[fieldname]"), m_str.GetBufferSetLength(255) );
    }
     
  12. VSergV

    VSergV Гость

    Так "WafersDate.mdb" -это и есть имя источника данных.... Или туда необходимо вставить имя таблицы??? :)

    Используешь в качестве провайдера ODBC?
    Если да то замени в вызвове
    Цитата
    m_Db->Open( "WafersDate.mdb",FALSE,TRUE,_T("ODBC;"));

    имя mdb-ки на имя источника данных, заранее зарегистрированного в ODBC.


    Так что-то не понял что такое
    и от куда оно берётся это
    поясните пожалуйста....
    А что если я укажу размер 255 напрямую т.е:RFX_Text(pFX, _T("[fieldname]"), 255);
    ??? :unsure:
     
  13. skysun

    skysun Гость

    Дело в том что имя источника данных не обязанно совпадать с именем mdb-шника, у тебя указано расширение файла, это меня и ввело в заблуждение!

    SunSanych писал:
    Просто название переменной(если поле в БД названо лат.символами)обычно имеет вид m_имяПоля

    АХЕЗ что за ошибка! Дело явно не в запросе. Попробуй все же объект в какой-нибудь функции создать новый объект CRecordset и проделать что нибудь подобное:
    Код (Text):
     CDatabase*m_Db;
    CRecordset* m_pSet;
    CString SQLrequest;
    CString strVal;

    m_Db = NULL;
    m_Db = new CDatabase();
    m_Db->Open("InterFace",FALSE,TRUE,_T("ODBC;"),TRUE);
    m_pSet = new CRecordset(m_Db);
    SQLrequest.Format("SELECT * FROM [данные]" );
    m_pSet->Open(CRecordset::forwardOnly, SQLrequest, CRecordset::readOnly );
    m_pSet->GetFieldValue(1,strVal);
    m_pSet->GetFieldValue(2,strVal);
    m_pSet->Close();
    Результат эксперимента должен показать в чем проблема!!!
     
  14. SunSanych

    SunSanych Well-Known Member

    Регистрация:
    28 июн 2006
    Сообщения:
    71
    Симпатии:
    0
    Попытаюсь с другого боку.
    Возможно имеет место переполнение памяти.
    В С, С++ строка - это просто массив байт (UNICODE пока не трогаем). И никаких проверок на выход за пределы массива не делается (чем грозит запись за границы - отдельный разговор). Считается, что программист - умный, знает что делает.
    Класс CString пытается упростить работу со строками. Он сам динамически выделяет столько памяти, сколько нужно, чтобы хранить строку. Все хорошо пока мы не пытаемся передать объект класса CString в какую-нибудь функцию вместо параметра char*. У класса CString есть оператор приведения к этому типу. Поэтому компилятор не выдаст ошибки. При приведении типов объект типа CString просто возвращает указатель на память которой он в данный момент владеет в надежде, что с ней будут обращаться "хорошо".
    "Хорошая" функция чтобы не вылезти за границы строки требует также длинну переданного массива.
    Так вот CString по-умолчанию, даже для пустой строки, выделяет только 64. А функция RFX_Text() по-умолчанию считает что ей передаётся массив в 255 байт и с чистой совестью будет записывать в него строки до 254 байт длинной (незабываем про завершающий 0).
    Здесь еще важно понять, что если строки в поле БД меньше 64 байт, то и ошибки не возникнет, но чтобы быть уверенным в результате надо заставить объект CString выделить больше памяти под строку. Для этого вызывается функция-член класса CString GetBufferSetLength(). И предупредить RFX_Text(), сколько байт она может записать.
    Допустим в БД в поле "Comment" может хранится строка до 1024 символов, тогда чтобы гарантированно получить всю строку целиком надо перед вызовом RFX_Text() попросить объект CString выделить 1024 байт:
    RFX_Text(pFX, _T("[Comment]"), m_Comment.GetBufferSetLength(1024), 1024);

    Вот в кратце :).
     
  15. SunSanych

    SunSanych Well-Known Member

    Регистрация:
    28 июн 2006
    Сообщения:
    71
    Симпатии:
    0
    На счет m_str - я же не телепат, догадываться как у тебя называются переменные. Просто назвал чтобы хоть как-то назвать. Это как корова массой 1 кг и объёмом 1 литр которую нельзя увидеть потому что она хранится в Париже в палате мер и весов.
     
  16. VSergV

    VSergV Гость

    Все попробую и сообщу о результате)))
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей