Параметризированный запрос в MFC
От: tzragravorox  
Дата: 06.02.06 09:36
Оценка:
Помагите пожалуста!

В MFC формирую запрос с параметром.
Почитал MSDN вроде все ок.

Но неполучаетса не знаю почему.
вот код.


//Recset.h
class CRecset : public CRecordset
{
public:
CString m_Parametr;
…
};



//Recset.cpp
CRecset::CRecset(CDatabase* pdb)
    : CRecordset(pdb)
{
    //{{AFX_FIELD_INIT(CRecset)
    …
    m_CONDITION = _T("");
    …
    //}}AFX_FIELD_INIT
    m_nParams=1;
…
}

void CRecset::DoFieldExchange(CFieldExchange* pFX)
{
    //{{AFX_FIELD_MAP(CRecset)//}}AFX_FIELD_MAP

    pFX->SetFieldType( CFieldExchange::param);
    RFX_Text(pFX, _T("[CONDITION]"), m_Parametr);
}


void CMYDlg::OnButton1() 
{
    CRecset Rec;
    Rec.Open();
    CString bbbb=”tt”; 
    CString SQL="INSERT INTO DEAL_DOCS (CONDITION)
 VALUES(?)";
Rec.m_Parametr=bbbb;
    Rec.m_pDatabase->ExecuteSQL(SQL);
}


После всего этого видаетса пустое сообшение и нехрена не дабавляетса!

Где я ошибся?

Большое Спасибо!

tzragravorox — Copyright (C) 2007

Re: Параметризированный запрос в MFC
От: Аноним  
Дата: 06.02.06 14:14
Оценка:
Здравствуйте, tzragravorox, Вы писали:

возьми вот эту либу.

для неё потребуется скачать OTL и иметь на машине оракловые include/lib
после сборки приложение зависит ТОЛЬКО от установленного Oracle client, никаких ODBC драйверов не нужно.

Сценарий использования:
1) создаётся объект CSQLConnect
2) при необходимости создаются собственные обработчики исключений и свой монитор SQL команд. (наследуются от CSQLExceptionHandlerBase и CSQLMonitorBase соотв.)
3) указываются данные подключения CSQLConnect::SetLogonInfo
4) выполняется соединене CSQLConnect::Connect

теперь мы готовы работать с базой.

Выполним параметризованный запрос.
    CSQLConnect conn;
    ....
    // создаём объект-запрос
    CSQLQuery q(conn);
    q.SetSQLText("select col_a, col_b from my_table where col_a > :val1 and col_b < :val2";
    q["val1"] = 12;
    q["val2"] = 256;
    q.Open();
    while(q.Next())
    {
        cout << "col_a=" << (LPCSTR)q["col_a"] << ", col_b=" << (LPCSTR)q[1] << endl;
    }


Выполним процедуру:
    CSQLConnect conn;
    ....
    // создаём объект-запрос
    CSQLQuery q(conn);
    q.PrepareProcedure("test_proc");
    q.StrParamByName["str_param"] = "bla-bla";
    q.NumParamByName["num"] = 1234;
    q.ExecuteProcedure();
    // здесь доступны выходные параметры


Полностью поддерживается MFC тип данных COleDataTime(). При желании можно достать OTL'ный описатель подключения (CSQLConnect::GetRawConnect) и напрямую юзать те возможности OTL, которые не реализованы в этой обёртке. Так же есть вкусности типа кешированного датасета и возможность слияния запросов.

Если заинтересуетесь — с удовольствием отвечу на возникающие вопросы и исправлю найденные ошибки.
Re[2]: Параметризированный запрос в MFC
От: Аноним  
Дата: 06.02.06 14:57
Оценка:
Здравствуйте, Аноним, Вы писали:

А>возьми вот эту либу.


ИМХО, ещё лучше взять ADO. Никак не пойму, чего народ так любит с MFC/ODBC париться? Неужели только из-за того, что МС лет 15 назад, когда кроме ODBC ничего не было, засунул эти классы в MFC?
Re[3]: Параметризированный запрос в MFC
От: Аноним  
Дата: 06.02.06 19:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>возьми вот эту либу.


А>ИМХО, ещё лучше взять ADO. Никак не пойму, чего народ так любит с MFC/ODBC париться? Неужели только из-за того, что МС лет 15 назад, когда кроме ODBC ничего не было, засунул эти классы в MFC?


Очень жаль, что вы не потрудились посмотреть приведённые мной ссылки. Иначе бы вы поняли что приведённый мной способ ни в коей мере не опирается на MFC (а тем более на ODBC). Это самое что ни на есть нативное решение для Oracle, работающее напрямую через OCI. Только в отличие от муторного OCI лёгкость использования сравнима с Delphi/VB. Эффективность ADO всё-таки похуже будет "родного" Ораклового интерфейса. Плюс для этих либ не нужно ничего лишнего тащить на машину.
Re[2]: Параметризированный запрос в MFC
От: Аноним  
Дата: 06.02.06 19:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, tzragravorox, Вы писали:


А>возьми вот эту либу.


а вот эта либа на sourceforge
Re: Параметризированный запрос в MFC
От: Symon Россия  
Дата: 07.02.06 05:43
Оценка: 3 (1)
Я пользуюсь своей функцией:
SQLRETURN SQLQuery (SQLHSTMT sqlStmt, LPSTR lpszSQL, ...)
{
    int                iPos;
    SQLSMALLINT        sqlParamNum;
    SQLPOINTER        sqlParam;
    SQLINTEGER        *sqlParamLen;
    SQLINTEGER        sqlColumnLen;
    SQLSMALLINT        sqlCType, sqlType;
    va_list            marker;
    CString            strSQL = (LPCSTR) lpszSQL;
    CString            strSQLP = (LPCSTR) lpszSQL;
    int                iSQLLen = strSQL.GetLength ();
    SQLRETURN        sqlRet;

    iPos = strSQLP.Find ('?');
    while (iPos >= 0)
    {
        if ((iPos + 1) < strSQLP.GetLength ())
        {
            switch (strSQLP[iPos + 1])
            {
            case 'b':
            case 'B':
            case 's':
            case 'S':
            case 'f':
            case 'F':
            case 'd':
            case 'D':
                strSQLP.Delete (iPos + 1);
            }
        }
        iPos = strSQLP.Find ('?', iPos + 1);
    }

    sqlRet = SQLPrepare (sqlStmt, (SQLCHAR*) (LPCSTR) strSQLP, SQL_NTS);
    if ((sqlRet != SQL_SUCCESS) && (sqlRet != SQL_SUCCESS_WITH_INFO))
        return sqlRet;

    va_start (marker, lpszSQL);

    sqlParamNum = 0;
    iPos = strSQL.Find ('?');
    while (iPos >= 0)
    {
        sqlParamNum++;
        sqlParam        = va_arg (marker, SQLPOINTER);
        sqlParamLen        = 0;
        sqlColumnLen    = 0;
        sqlCType        = SQL_C_SLONG;
        sqlType            = SQL_INTEGER;

        if ((iPos + 1) < iSQLLen)
        {
            switch (strSQL[iPos + 1])
            {
            case 'b': // sized binary data
            case 'B':
                sqlParamLen = va_arg (marker, SQLINTEGER*);
                sqlColumnLen = *sqlParamLen;
                sqlCType = SQL_C_BINARY;
                sqlType = SQL_LONGVARBINARY;
                break;
            case 's': // zero-terminated string
            case 'S':
                sqlColumnLen = (SQLINTEGER) strlen ((LPCSTR) sqlParam);
                sqlCType = SQL_C_CHAR;
                sqlType = SQL_CHAR;
                break;
            case 'f': // 32-bit floating point
            case 'F':
                sqlCType = SQL_C_FLOAT;
                sqlType = SQL_REAL;
                break;
            case 'd': // 64-bit floating point
            case 'D':
                sqlCType = SQL_C_DOUBLE;
                sqlType = SQL_FLOAT;
                break;
            default: // 32-bit integer
                break;
            }
        }

        sqlRet = SQLBindParameter (sqlStmt, sqlParamNum, SQL_PARAM_INPUT,
                                    sqlCType, sqlType,
                                    sqlColumnLen, 0, sqlParam, sqlColumnLen, sqlParamLen);

        if ((sqlRet != SQL_SUCCESS) && (sqlRet != SQL_SUCCESS_WITH_INFO))
            return sqlRet;

        iPos = strSQL.Find ('?', iPos + 1);
    }
    
    va_end (marker);
    return SQLExecute (sqlStmt);
}
Re[2]: Параметризированный запрос в MFC
От: Symon Россия  
Дата: 07.02.06 05:57
Оценка: 3 (1)
Примеры запросов:
SQLQuery (hstmt, "INSERT INTO [TABLE] ([name]) VALUES (?s)", lpszName);
SQLQuery (hstmt, "UPDATE [TABLE] SET [name] = ?s WHERE ([id] = ?)", lpszName, &id);
SQLQuery (hstmt, "UPDATE [TABLE] SET [data] = ?b WHERE ([id] = ?)", pData, &iSizeData, &id);

?B, ?b — бинарный тип передается указатель на буффер и указатель на размер буфера;
?S, ?s — строковый тип указатель на NULL-terminated string;
?F, ?f — REAL тип БД, передается указатель на float C type;
?D, ?d — FLOAT тип БД, передается указатель на double C type;
? — указатель на целый тип int.

Re[3]: Параметризированный запрос в MFC
От: Аноним  
Дата: 07.02.06 06:09
Оценка:
Здравствуйте, Symon, Вы писали:

S>Примеры запросов:

S>
S>SQLQuery (hstmt, "INSERT INTO [TABLE] ([name]) VALUES (?s)", lpszName);
S>SQLQuery (hstmt, "UPDATE [TABLE] SET [name] = ?s WHERE ([id] = ?)", lpszName, &id);
S>SQLQuery (hstmt, "UPDATE [TABLE] SET [data] = ?b WHERE ([id] = ?)", pData, &iSizeData, &id);
S>

S>

S>?B, ?b — бинарный тип передается указатель на буффер и указатель на размер буфера;
S>?S, ?s — строковый тип указатель на NULL-terminated string;
S>?F, ?f — REAL тип БД, передается указатель на float C type;
S>?D, ?d — FLOAT тип БД, передается указатель на double C type;
S>? — указатель на целый тип int.


как у вас биндятся даты ? входные-выходные параметры процедур ?
Re[4]: Параметризированный запрос в MFC
От: Symon Россия  
Дата: 07.02.06 06:13
Оценка: 3 (1)
Здравствуйте, Аноним, Вы писали:

А>как у вас биндятся даты ? входные-выходные параметры процедур ?


никак предлагаю форумчанам подправить — дописать ?t, ?T — типа время
увидел вопрос — захотелось поделится функцией может кому пригодится...
Re[5]: Параметризированный запрос в MFC
От: Аноним  
Дата: 07.02.06 08:04
Оценка:
Здравствуйте, Symon, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


А>>как у вас биндятся даты ? входные-выходные параметры процедур ?


S>никак предлагаю форумчанам подправить — дописать ?t, ?T — типа время

S>увидел вопрос — захотелось поделится функцией может кому пригодится...

эта либа
Автор:
Дата: 06.02.06
всё это умеет плюс её скорость ГОРАЗДО выше чем у ODBC.
Re[4]: Параметризированный запрос в MFC
От: tzragravorox  
Дата: 07.02.06 11:53
Оценка:
Здравствуйте, Аноним, Вы писали:

Уважаемы я посмотрел еше вчера!

Извините с опазданием.

Очень садержательный ответ.

Спасибо!

Но для меня еше труднавато!

Но думаю что еше пригадитса.

tzragravorox — Copyright (C) 2007

Re[2]: Параметризированный запрос в MFC
От: tzragravorox  
Дата: 07.02.06 11:55
Оценка:
Здравствуйте, Symon, Вы писали:

Большое спасибо!

я еше не пробовал но надеюс на успех.

если вы написали функцию значит ли это что ы вас тоже с MFC не получилос?

tzragravorox — Copyright (C) 2007

Re: Параметризированный запрос в MFC
От: tzragravorox  
Дата: 07.02.06 11:59
Оценка:
Я окончательно запутался.

Кажетса простая зодача а который день мучаюсь.

Не связиваютса параметри и все.

А теперь наткнулся ха следуюшее->

void CDatabase::BindParameters(HSTMT /* hstmt */)
{
    // Must override and call SQLBindParameter directly
}


Что ето значит?

В MNSD говаритса что при исползовании ExecuteSQL нужно переопределять эту функцию.

Но у меня даже нет обекта CDatabase.

Я понял что ODBC отстой но неужели некто это ранше не делал я почти закончил, не хочетса все менять.

Сп!

tzragravorox — Copyright (C) 2007

Re[2]: Параметризированный запрос в MFC
От: bedward70 Россия http://www.bedward70.narod.ru/
Дата: 07.02.06 13:35
Оценка: 3 (1)
Здравствуйте, tzragravorox, Вы писали:

T>Я окончательно запутался.


[skipped]

T>
T>void CDatabase::BindParameters(HSTMT /* hstmt */)
T>{
T>    // Must override and call SQLBindParameter directly
T>}
T>


T>Что ето значит?


T>В MNSD говаритса что при исползовании ExecuteSQL нужно переопределять эту функцию.


T>Но у меня даже нет обекта CDatabase.


T>Я понял что ODBC отстой но неужели некто это ранше не делал я почти закончил, не хочетса все менять.


T>Сп!


Позвольте с вами не согласиться — то что вы приводите есть MFC
Фукции ODBC просты, написаны на C (а не С++), главное: последовательность действий правильно задать
Последовательность действий:
1. В MSDN (я искал в MSDN98) SQLExecute.
2. В разделе можно получить ссылки на другие функции, пример SQLBindParameter, и даже с примером
3. Да и примеров полно. В MSSQL7 кажется, был примерчик для ODBC, как хранимые процедуры MSSQL вызывать всякие.

Я сделал давно-давно сделал себе C++ библиотечку поверх ODBC, и уже лет 12 использую.
Наворотов не много:
1. логин автоматически, по сохраненной ранее строки соединения.Если нет ее, через SQLDriverConnect, который позволяет выбрать драйвер.
2. SQL пишу руками,
3. Pезультат ловлю в структурированный класс
(Дать могу, но код не очень изящный: местами очень старый и как всегда без коментариев , проще самому написать, если чего — в мыло стукни).

Как правило быстродействия хватаиет для небольших проектов (типа найти-распечатать-скоректировать-добавить).
А других типов проектов не так и много
С уважением, Эдвард
Re[3]: Параметризированный запрос в MFC
От: tzragravorox  
Дата: 07.02.06 13:45
Оценка:
Здравствуйте, bedward70, Вы писали:

Спасибо больиое!

наверное я так и сделаю, напишу свою.

но мне ети параметри сдалис из за размера переменной,

почитаю еше

tzragravorox — Copyright (C) 2007

Re[3]: Параметризированный запрос в MFC
От: tzragravorox  
Дата: 07.02.06 13:50
Оценка:
Здравствуйте, Symon, Вы писали:

Уважаемы я попробовал


        CString lpszName="aaa";

    CRecset Rec;
    
    Rec.Open();

    SQLQuery (Rec.m_hstmt, "INSERT INTO TEST (FIELD_1) VALUES (?s)", lpszName);


что то не получилось

почему?

tzragravorox — Copyright (C) 2007

Re[2]: Параметризированный запрос в MFC
От: Burz  
Дата: 07.02.06 14:40
Оценка: 3 (1)
Здравствуйте, Аноним, Вы писали:

А>для неё потребуется скачать OTL и иметь на машине оракловые include/lib

А>после сборки приложение зависит ТОЛЬКО от установленного Oracle client.

Улыбнуло.
Напоминает компилирование прог под линукс — скачайте эту либу, для нее эту, для нее еще парочку этих и ничего кроме еще трех либ вам больше не понадобится
Re[3]: Параметризированный запрос в MFC
От: Аноним  
Дата: 08.02.06 01:23
Оценка:
Здравствуйте, Burz, Вы писали:

B>Здравствуйте, Аноним, Вы писали:


А>>для неё потребуется скачать OTL и иметь на машине оракловые include/lib

А>>после сборки приложение зависит ТОЛЬКО от установленного Oracle client.

B>Улыбнуло.

B>Напоминает компилирование прог под линукс — скачайте эту либу, для нее эту, для нее еще парочку этих и ничего кроме еще трех либ вам больше не понадобится

Эх, ну так уж вышло, что либа опирается на OTL (на один-единственный *.h файл).
Ну я для сборки приложений использующих OCI как ни вертись, а inclue/lib ораклиные нужны

для сборки действительно больше ничего не понадобится, плюс дистрибутив ничего кроме программы ложить не придётся
Re[4]: Параметризированный запрос в MFC
От: Symon Россия  
Дата: 08.02.06 05:35
Оценка: 3 (1)
Здравствуйте, tzragravorox, Вы писали:

T>что то не получилось

T>почему?

BOOL RunSQL (CDatabase *pDB)
{
    SQLHSTMT            hstmt;
    SQLRETURN           retcode;
    CString             lpszName="aaa";

    retcode = SQLAllocHandle (SQL_HANDLE_STMT, pDB->m_hdbc, &hstmt);
    if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO))
    {
        return FALSE; // error
    }

    retcode = SQLQuery (hstmt, "INSERT INTO TEST (FIELD_1) VALUES (?s)", lpszName);
    SQLFreeHandle (SQL_HANDLE_STMT, hstmt);
    if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO))
    {
        return FALSE; //error
    }
    return TRUE;
}
Re[5]: Параметризированный запрос в MFC
От: tzragravorox  
Дата: 08.02.06 14:03
Оценка:
Здравствуйте, Symon, Вы писали:

Огромное Огромное Огромное Огромное Огромное СПАСИБО!

я бы потратил недели рабочеги времени на все это(я вед навичок).

Все ок.

Дашел до последней части.

осталос это все для BLOB написать.

Должен запихнут болшие данние в ORACLE XMLTYPE.

если писать

CString XML="большой документ"

INSERT INTO TABLE (XML_FIELD) VALUES (XMLTYPE('XML'))


если XML>4000баит
то провал

попробую с блоб .

с радастю приму ваши совети.

СПАСИБО!

tzragravorox — Copyright (C) 2007

Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.