• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

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

  • Автор темы VSergV
  • Дата начала
Статус
Закрыто для дальнейших ответов.
V

VSergV

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

grigsoft

А обрамление <> правильное для имени таблицы? Я с драйвером access не работал, но вроде обычно [] используются в ODBC\DAO.
 
V

VSergV

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

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

Help me
 
E

European

Судя по ошибке, после открытия ты перемещаешь курсор... Или я не прав?
 
V

VSergV

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

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

European

<!--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]
Покажи больше кода
 
S

skysun

SELECT * FROM UnitedTable;

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

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

VSergV

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

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:
 
S

skysun

Код:
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?
Если да то замени в вызвове
m_Db->Open( "WafersDate.mdb",FALSE,TRUE,_T("ODBC;"));
имя mdb-ки на имя источника данных, заранее зарегистрированного в ODBC.

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

SunSanych

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

VSergV

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

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

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


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

skysun

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

Так что-то не понял что такое m_str

SunSanych писал:
В класс-наследник от CRecordset помощник из VisualStudio для каждого возвращаемого поля создает член-переменную. Для строковых полей создаётся член-переменная типа CString.
Просто название переменной(если поле в БД названо лат.символами)обычно имеет вид m_имяПоля

А мне выскочила ошибка от BD: Недопустимое символьное значение для указания отклонения на строке номер 5(PlantNumber).
АХЕЗ что за ошибка! Дело явно не в запросе. Попробуй все же объект в какой-нибудь функции создать новый объект CRecordset и проделать что нибудь подобное:
Код:
 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();
Результат эксперимента должен показать в чем проблема!!!
 
S

SunSanych

Попытаюсь с другого боку.
Возможно имеет место переполнение памяти.
В С, С++ строка - это просто массив байт (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);

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

SunSanych

На счет m_str - я же не телепат, догадываться как у тебя называются переменные. Просто назвал чтобы хоть как-то назвать. Это как корова массой 1 кг и объёмом 1 литр которую нельзя увидеть потому что она хранится в Париже в палате мер и весов.
 
V

VSergV

Все попробую и сообщу о результате)))
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!