Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Работа с базами данных

246
12 мая 2008 года
GIZMO
1.8K / / 30.07.2004
Здесь все, что связано с разработкой баз данных.
1
14 мая 2008 года
kot_
7.3K / / 20.01.2000
Вопрос:
Как мне динамически сформировать строку подключения к базе данных?
Ответ:
Строка подключения для компонетов должна выглядеть следующим образом:
Для MSSQLServer:
 
Код:
WideString ConnectionString ="Provider=SQLNCLI.1;Password=<Ваш пароль>;Persist Security Info=True;User ID=<Ваш пользователь>;Initial Catalog=<имя вашей базы>;Data Source=<Имя сервера>;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=<имя локальной машины>;Use Encryption for Data=False;Tag with column collation when possible=False;MARS Connection=False;DataTypeCompatibility=0;Trust Server Certificate=False";

Для MSSQLServer с динамическим присоединением базы:
 
Код:
WideString ConnectionString ="Provider=SQLNCLI.1;Password=<Ваш пароль>;Persist Security Info=True;User ID=<Ваш пользователь>;Initial Catalog=<имя вашей базы>;Data Source=<Имя сервера>;Extended Properties=\"<Имя базы=Путь к файлу БД>\";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=<имя локальной машины>;Use Encryption for Data=False;Tag with column collation when possible=False;MARS Connection=False;DataTypeCompatibility=0;Trust Server Certificate=False";

Для MSAccess:
 
Код:
WideString ConnectionString ="Provider=MSDASQL.1;Persist Security Info=False;Extended Properties=\"DSN=<Имя ДСН-подключения>;DBQ=<Имя файла>;DriverId=25;FIL=MS Access;MaxBufferSize=2048;PageTimeout=5;UID=<admin>;\""


Для MSExcel:
 
Код:
WideString ConnectionString = "Provider=MSDASQL.1;Persist Security Info=False;Extended Properties=\"DSN=<Имя ДСН-подключения>;DBQ=<Имя файла>;DefaultDir=<Директория>;DriverId=790;FIL=excel 8.0;MaxBufferSize=2048;PageTimeout=5;\";Initial Catalog=<Имя файла>";

там где необходимо экранировать кавычки в строке - они экранированы. Соответственно вместо значений в угловых скобках вы должны подставить свои.
Пример
формирование строки подключения для MSSQLServer:
Код:
TADOConection *adoConnect = new TADOConnection(this);
WideString provider = "SQLNCLI.1";
WideString pass = "bez parola";
WideString user = "petya vasechkin";
WideString base = "base";
WideString server = "192.168.1.100,1430";
char buff[MAX_SIZE];
DWORD sizebuff = MAX_SIZE;
GetComputerName(buff,&size);

WideString ConnectionString ="Provider="+provider+";Password="+pass+";Persist Security Info=True;User ID="+user+";Initial Catalog="+base+";Data Source="+server+";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID="+((WideString)buff)+";Use Encryption for Data=False;Tag with column collation when possible=False;MARS Connection=False;DataTypeCompatibility=0;Trust Server Certificate=False";

adoConnect->ConnectionString = ConnectionString;
adoConnect->LoginPrompt = false;
adoConnect->Connection = true;

Обратите внимание на то как задано имя сервера: "192.168.1.100,1430" - т.е. адрес и порт, что бы это сработало, в свойствах сервера должен быть разрешен TCP/IP. Так же к серверу можно обратиться через его инстанс - "DataBaseSrv\MSSQLSERVER" - формат соответственно ДОМЕННОЕ_ИМЯ\ИНСТАНС_СЕРВЕРА. Если сервер запущен на локальной машине - ".\MSSQLSERVER". Не забывайте экранировать слеш.
1
18 мая 2008 года
kot_
7.3K / / 20.01.2000
Вопрос:
Как хранить и отображать в базе данных дерево с произвольным уровнем вложенности?
Ответ:
Для отображения структуры дерева в БД вам необходимо создать таблицу, которая имеет следующую структуру:
 
Код:
nodeid    parentid  nodename
=====   ======   =======
1            0           Ветка первого уровня
2            1           Ветка второго уровня
3            0           Вторая ветка первого уровня
....

Код создания таблицы для MSSQL выглядит так:
 
Код:
CREATE TABLE [dbo].[nodes](
    [nodeid] [int] IDENTITY(1,1) NOT NULL,
    [parentid] [int] NOT NULL,
    [nodename] [varchar](512) COLLATE Cyrillic_General_CI_AS NOT NULL,
 CONSTRAINT [PK_nodes] PRIMARY KEY CLUSTERED
(
    [goodtypeid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

Создаем хранимую процедуру для чтения значений из таблицы (в принципе можно обойтись и запросом - но работать с таблицами напрямую, я лично считаю ошибкой проектирования):
 
Код:
CREATE PROCEDURE [dbo].[sSelectNodes]
   
    @parentid int
AS
BEGIN
        SET NOCOUNT ON;
    SELECT nodeid,nodename from nodes  
        WHERE parentid = @parentid
   
END

Естественно необходимо индексировать поля по которым идет выборка - но с этим я думаю вы сумеете разобраться сами.
Дальше в коде приложения объявляем следующюю функцию:
Код:
//Объявление
int AddChildCategory(TTreeView *Tree,TTreeNode *Node,const int &parentid);
//Реализация
int AddChildCategory(TTreeView *Tree,TTreeNode *Node,const int &parentid){
//Создаем объект для вызова процедуры
 TADOStoredProc *spAddChild = new TADOStoredProc(NULL);
 spAddChild->Connection = dmMain->adoConnect; //Устанавливаем соединение
//как устанавливать соединение - смотри предыдущий вопрос.
 spAddChild->ProcedureName = "sSelectNodes;1";//Выбираем имя процедуры
 spAddChild->Prepared = true;
//Создаем параметр для передачи в процедуру
spAddChild->Parameters->CreateParameter(WideString("@parentid"),ftInteger,pdInput,sizeof(int),0);
//Присваеваем значение ему
 spAddChild->Parameters->ParamByName(WideString("@parentid"))->Value = parentid;
//Запускаем
 spAddChild->Active = true;
 TTreeNode *Child;
 String name = ""; //Переменные для имени и идентификатора
 int id = 0;
//Перебераем полученные данные
 while(!spAddChild->Eof){
 id = spAddChild->FieldByName("nodeid")->Value;
 name = spAddChild->FieldByName("nodename")->AsString;
//Добавляем ветку
 Child = Tree->Items->AddChildObject(Node,name,static_cast<void*>(new int(id)));
//Рекурсивно высываем нашу функцию
 AddChildCategory(Tree,Child,id);
//Продолжаем перебор
 spAddChild->Next();
 }
 spAddChild->Active = false;
 delete spAddChild;
}

Как использовать -
 
Код:
void __fastcall TfmMain::actLoadTreeExecute(TObject *Sender)
{
tvMain->Items->Clear();
TTreeNode *nodeparent = tvMain->Items->AddObjectFirst(NULL,"Дерево из базы",static_cast<void*>(new int(-1)));
AddChildCategory(tvMain,nodeparent,0);

 nodeparent->Expand(true);
 nodeparent->Selected = true;
 tvMainClick(tvMain);
}

tvMain - компонент TTreeView
fmMain - форма на которую он положен.
На что обратить внимание:
parentid корня дерева не должен быть равен ни одному из nodeid - т.е. если корень дерева у нас равен 0 - то nodeid со значением 0 недопустим - иначе получите бесконечный цикл.
11
19 мая 2008 года
oxotnik333
2.9K / / 03.08.2007
Вопрос:
Как хранить и отображать в базе данных дерево с произвольным уровнем вложенности?
Ответ:

Таблица представлена в виде:
 
Код:
nodeid    parentid  nodename
=====   ======   =======
1            0           Ветка первого уровня
2            1           Ветка второго уровня
3            0           Вторая ветка первого уровня


запрос из БД:

 
Код:
SELECT * FROM nodes
ORDER BY parentid


Выжно: т.к. алгоритм является линейным и однопроходным (без рекурсий) необходимо упорядочить записи таким образом что бы для каждой последующай записи (кадого последующего значения поля parentid) уже существовала запись nodeid.

Непосредственно рисуем дерево:
Код:
#include <map>
using namespace std;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  map <int, TTreeNode*>NodesMap;
  ADOQuery1->Active = true;
  TIntegerField *IDKey = (TIntegerField*)ADOQuery1->FieldByName("nodeid");
  TIntegerField *ParentIndex = (TIntegerField*)ADOQuery1->FieldByName("parentid");
  TStringField *ItemName = (TStringField*)ADOQuery1->FieldByName("nodename");
  int id, level, parent_index;
  String item_name;
  while (!ADOQuery1->Eof)
        {
          id = IDKey->AsInteger;
          parent_index = ParentIndex->AsInteger;
          item_name = ItemName->AsString;
          if (parent_index == 0) // если это root уровень
             NodesMap[id] = TreeView1->Items->Add(NULL, item_name);
          else
             {
               if (NodesMap[parent_index]) // проверка на существование значения
                  NodesMap[id] = TreeView1->Items->AddChild(NodesMap[parent_index], item_name);
             }
          NodesMap[id]->Data = (void*)(int)id; // присваиваем уникальный индекс каждому TTreeNode для последующей навигации по БД при помощи TTreeView
          ADOQuery1->Next();
        }
// обчно после составления большого дерева винда резервирует под приложение много памяти, сбрасываем все резервы:
  SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
  ADOQuery1->Active = false;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог