Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > СУБД, общие вопросы > помогите выбрать БД


Автор: Vaulter 26.2.2004, 22:05
нужна такая система:
.dll
которую мона подрубить к c++шной прогу, и юзать SQL из нее...
но чтобы .dll скидывала/читала БД напрямую из файлика, который лежит тут же рядом с ней....
что заюзать?

Автор: AntonSaburov 27.2.2004, 10:08
Так через ADO можно все, что хочется юзать - DBF, TXT, MDB

Хотя вопрос не совсем понятен - тебе надо все-таки реальный SQL-сервер или работать с табличками через SQL-запросы ?

Подробнее объясни, плиз.

Автор: Vaulter 7.3.2004, 13:15
AntonSaburov
работать с табличками, точнее чтобы через API какойлибо БД+ .dll этой БД + файл тут же рядом
никаких серверов, служб и т.д.
компактно и удобно

Автор: sergejzr 7.3.2004, 22:31
Определённо советую http://www.sqlite.org.

Ona спасла меня во время дипломной работы полгода назад.
Как я понял, она полностью отвечает Вашим требованиям.

Преимущества:
1. Си, Lib, DLL, exe (как угодно)
2. компилируется на любой платтформе
3. весит около 200 кБ
4. созданныи фаилик читется так же на любой платтформе
5. может работать исключительно в памяти
6. существуют так же драйвера для кучи языков (PHP,Perl,...), ODBC
7.По моему одна из самых (если не самая) быстрая БД
и самое главное:
8. http://groups.yahoo.com/group/sqlite/ можно спокоино поговорить с разработчиком (ошибки и предложения часто рассматриваются в течении нескольких часов максимум суток)

есть конечно некоторые приколы, но проблем с ними особенных нет.




Автор: Vaulter 8.3.2004, 16:47
sergej.z
спасибо, хоть какойто вариант есть, буду пробовать )

Автор: sergejzr 8.3.2004, 17:15
забыл добавить:
Она OpenSource конечно и продвинута не хуже чем MySQL какой нибудь.
поддерживает почти весь SQL92.

Если сказать коротко, то это библиотека которая позволяет использовать SQL в C/C++-коде.

PS: Рад был помочь. И надеюсь что смогу как нибудь помочь в будущем.
Просто эта тема меня тоже очень интересует, так как принимал активное участие в свое время.

Автор: Vaulter 8.3.2004, 23:19
sergej.zтэк, а теперь блин ) примерчик на си helloworld пожалуйста,
как с этой dll выполнить обычный SELECT * FROM table и куданить вывести в консоль результат?

Автор: sergejzr 9.3.2004, 19:07
С главной страницы:
http://www.sqlite.org/quickstart.html

Здесь мой вариант с комментариями. Так как необходимо было показать пару возможностей, и код должен был оставаться рабочим (с загрузкой длль итп.), файл получился большеватый. Распечатаю в следующем сообшении.
http://www.iwi-iuk.org/cashmere/htdocs/xsample.cpp

PS: И первый (exec/callback) и второй(compile/step/finalize) методы имееют свои преимущества и недостатки. Я думаю это видно из кода. Кроме того существуют такие методы как

sqlite_exec_printf(db,"select from %s where %s='%s'",mytable,my_column, my_value,.......); ,

который согласитесь тоже имеет свои преимущества.


Автор: sergejzr 9.3.2004, 19:10
xsample.cpp

Код
#include <stdio.h>
#include <windows.h>



/*
Конечно SQLite можно загрузить из DLL или же Link Lib(?).
*/
#define  SQLITEDLL



#ifdef SQLITEDLL

#define SQLITE_OK      0  /* Successful result */
#define SQLITE_ERROR    1  /* SQL error or missing database */
#define SQLITE_ROW     100 /* sqlite_step() has another row ready */
#define SQLITE_DONE    101 /* sqlite_step() has finished executing */

typedef struct sqlite_vm sqlite_vm;
typedef struct sqlite sqlite;




typedef int (*sqlite_callback)(void*,int,char**, char**);

typedef int (__cdecl * sqlite_exec_dll)(
     sqlite*,           /* An open database */
      const char *sql,       /* SQL to be executed */
      sqlite_callback,       /* Callback function */
      void *,            /* 1st argument to callback function */
      char **errmsg         /* Error msg written here */
      );
typedef sqlite * (__cdecl * sqlite_open_dll)(
      const char *filename,
      int mode,
      char **errmsg

      );


typedef int (__cdecl * sqlite_compile_dll)(
         sqlite *db,       /* The open database */
         const char *zSql,    /* SQL statement to be compiled */
         const char **pzTail,   /* OUT: uncompiled tail of zSql */
     sqlite_vm **ppVm,    /* OUT: the virtual machine to execute zSql */
         char **pzErrmsg     /* OUT: Error message. */
         );

typedef int (__cdecl * sqlite_step_dll)(
     sqlite_vm *pVm,     /* The virtual machine to execute */
      int *pN,         /* OUT: Number of columns in result */
         const char ***pazValue, /* OUT: Column data */
         const char ***pazColName /* OUT: Column names and datatypes */
         );

typedef int (__cdecl * sqlite_finalize_dll)(
     sqlite_vm *pVm,     /* The virtual machine to be finalized */
         char **pzErrMsg     /* OUT: Error message */
         );

typedef void (__cdecl * sqlite_close_dll)(
         sqlite *db
         );
sqlite_exec_dll sqlite_exec;
sqlite_open_dll sqlite_open;
sqlite_compile_dll    sqlite_compile;
sqlite_step_dll sqlite_step;
sqlite_finalize_dll sqlite_finalize;
sqlite_close_dll    sqlite_close;
HINSTANCE    SQLiteDLL;
#else

#include "sqlite.h"
#endif

int myCallback(void*,int,char**, char**);
int init();
void finish();

int main()
{

/*это собственно указатель на БД. Таких может быть несколько в программе, если понадобится работать с несколькими
файлами.
*/
sqlite *db;

// Мессага, которая обяснит ошибку, если таковая произойдёт
char *zErrMsg = 0;

//Error code
int rc;
if( init()!=0)
{
printf("DLL's not loaded ");
return 1;
}
/*arg1: Моя_БД.db есть файл БД. Если его несуществует, SQLite сама его создаст.
   arg2:Mode 0=  Открыть файл read/write, 1 read only.
              Обьяснение простое: Если файл открыт на read/write никакой другой процесс ОС не сможет в него писать.
              Соответственно открываем read only если нам нужно только селектировать данные, но не изменять БД  и
              оставляем другому процессу возможность изменять БД.
              Но в нашем случае (как и в большинстве других)никакие другие процессы не будут испльзовать этот файл, так
              что 0 нас вполне устроит.
   arg3: Сообщение об ошибке. Его можно распечатать, но только если возвращённый db==NULL.

../Где_Угодно/Моя_БД.db

*/
db = sqlite_open("my.db", 0, &zErrMsg);

/*
 Если было невозможно создать файлик то db естественно NULL,
 a zErrMsg сообщит, что именно случилось.
*/
if( db==0 )
{
  printf( "Can't open database: %s\n", zErrMsg);
  return 1;
 }
/*
Всё в порядке, можно работать!

В SQLite существует два способа получения результата БД.

1. exec/callback
        Функция callback будет вызываться SQLite с каждой строкой от ResultSet'a
        Чем то похоже Listener на в JAVA

2. compile/step/finalize
        в этом случае можно забирать ResultSet строка за строкой
*/
/*

рассмотрим sqlite_exec

arg1: Наша БД
arg2: SQL statement
arg3: Функция callback (Здесь нам не нужна).
arg4: Аргумент, который будет передаваться в функцию callback. Например вектор, в который мы хотим добавлять результат,
  или вообще указатель на какой нибудь обьект (Здесь нам не нужeн).
arg5: Сообщение об ошибке. Его можно распечатать, но только если возвращённый rc!=0.

Накидаем табличку
*/
rc=sqlite_exec(db, "create table test(num integer,name string);", NULL, NULL, &zErrMsg);

/*
if(rc!=SQLITE_OK)
{
 printf( "%s\n", zErrMsg);
    return 1;
}
*/
/*
 При импорте данных очень важно начать с begin иначе БД будет тормозить.
   Обьяснение: Все записи будут осуществляться в памяти и только с commit писаться на диск.
   После этого SQLite проверит, всё ли записано правильно.
   Без beginn'a это будет осуществляться при каждой записи
*/
rc=sqlite_exec(db, "begin;", NULL, NULL, &zErrMsg);

for(int i=0;i<10;i++)
    {
/*
 На оригинальность не претендую :)
*/
char sqlText[200];
sprintf(sqlText,"insert into test values(%i,'name_%i');",i,i);


rc=sqlite_exec(db, sqlText, NULL, NULL, &zErrMsg);
 if(rc!=SQLITE_OK)
     {
     printf( "%s\n", zErrMsg);
   break;
     }
   }
/*
произведём селект способом 1:
*/
printf("\n exec/callback \n");
rc=sqlite_exec(db, "select * from test;", myCallback, NULL, &zErrMsg);

if(rc!=SQLITE_OK)
 {
     printf( "%s\n", zErrMsg);
     return 1;
    }





/*
  произведём SELECT способом 2:
*/
const char *sqlText="select * from test;";
/*
 ppVm непрозрачная структура виртуальной машины. В некоторых случаях я исползьовал несколько таких машин,
   чтобы опрашивать несколько разных ResultSet'ов.
*/
sqlite_vm *ppVm;

/*
 рассмотрим sqlite_compile

 arg1:Наша БД
 arg2:SQL statement
 arg3:Указатель на Statement. не примомню , можно/нужно ли это как то использовать. В нашем случае нет.
 arg4:Виртуальная машинка.
 arg5:Сообщение об ошибке (SQLSyntax).
*/
rc=sqlite_compile(db, sqlText,&sqlText,&ppVm,&zErrMsg);
if(rc!=SQLITE_OK)
      {
      printf( "%s\n", zErrMsg);
    return 1;
     }

   printf("\n compile/step/finalize \n");
   int columns;
   const char **pazValue;
   const char **pazColName;
 /*
    рассмотрим sqlite_step
    arg1:Виртуальная машинка
    arg2:Эта переменная соовщит нам, сколько колонок в строчке результата.
    arg3:data
    arg4:Имена колонок и типы данных

 */
rc=sqlite_step(ppVm,&columns,&pazValue,&pazColName);
while(rc!=SQLITE_DONE)
{



 for(int i=0;i<columns;i++)
 {
 /*
   Типы данных хранятся в pazColName с отступом в columns.
  */
 printf("%s(%s)=%s |",pazColName[i],pazColName[i+columns],pazValue[i]);
 }

printf("\n");
   rc=sqlite_step(ppVm,&columns,&pazValue,&pazColName);
}

/*destructor Виртуальной машины*/
rc=sqlite_finalize(ppVm,&zErrMsg);

rc=sqlite_exec(db, "commit;", NULL, NULL, &zErrMsg);
sqlite_close(db);
return 0;
}


static int myCallback(void *NotUsed, int columns, char **pazValue, char **pazColName){
int i;
for(i=0; i<columns; i++){

 printf("%s(%s)=%s |",pazColName[i],pazColName[i+columns],pazValue[i] ? pazValue[i]:"NULL");
}
printf("\n");
finish();
return 0;
}




int init()
{
#ifdef SQLITEDLL
HINSTANCE    SQLiteDLL = LoadLibrary("sqlite.dll");

    sqlite_exec=((sqlite_exec_dll) GetProcAddress (SQLiteDLL, "sqlite_exec"));
    sqlite_open=((sqlite_open_dll) GetProcAddress (SQLiteDLL, "sqlite_open"));
    sqlite_compile=((sqlite_compile_dll) GetProcAddress (SQLiteDLL, "sqlite_compile"));
    sqlite_step=((sqlite_step_dll) GetProcAddress (SQLiteDLL, "sqlite_step"));
    sqlite_finalize=((sqlite_finalize_dll) GetProcAddress (SQLiteDLL, "sqlite_finalize"));
    sqlite_close=((sqlite_close_dll) GetProcAddress (SQLiteDLL, "sqlite_close"));
    return SQLiteDLL==NULL ? 1:0;

#endif
return 0;
}

void finish()
{
#ifdef SQLITEDLL
if(SQLiteDLL!=NULL)
FreeLibrary(SQLiteDLL);
#endif
}

Автор: Vaulter 9.3.2004, 19:22
sergej.z
во! спасибо! + в рейтинг тебе! )

Автор: sergejzr 9.3.2004, 20:16
Спасибо, рад помочь!

У меня просьба, если будут какие нибудь замечания/предложения по поводу SQLite, не меняйте код локально, сообщайте об этом http://groups.yahoo.com/group/sqlite/ или этом http://www.sqlite.org/cvstrac/tktnew . Возможно в следующем релизе ошибки/предложения будут исправлены/реализованы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)