Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.05;
Скачать: CL | DM;

Вниз

Мастера, подскажите как сделать так, чтобы   Найти похожие ветки 

 
svt   (2006-10-17 09:45) [0]

Мастера, подскажите как сделать так, чтобы пользователь мог выбрать из списка ту базу с которой ему необходимо работать. База реализована на mssql. На сервере их 3-4 (базы). Как это сделать.... динамически сгенерировать строку подключения... короче говоря необходимо вывести список имеющихся баз и после этого строить строку ConnectionString в ADOConnection1.  заранее благодарен


 
ЮЮ ©   (2006-10-17 09:55) [1]

А посмотреть имеющуюся статическую ConnectionString и найти в ней место БД, конечно, религия не позволяет?

function BuildConnectionStringForMSSQL(
 const AServer, ADatabase, AUser, APassword: string
): string;
begin
 Result :=
   "Provider=SQLOLEDB.1;Persist Security Info=False;";
 if (AUser = "") and (APassword = "") then
   Result := Result + "Integrated Security=SSPI;"
 else
   Result := Result + "User ID=" + AUser + ";Password=" + APassword + ";";
 Result := Result +
   "Initial Catalog=" + ADatabase + ";" +
   "Data Source=" + AServer;
end;


 
MsGuns ©   (2006-10-17 10:03) [2]

 // Дескриптор SQL-сервера
 PMSSQLServerDef = ^RMSSQLServerDef;
 RMSSQLServerDef = record
   ServerName: string;          // Имя сервера
   InstanceName: string;        // Установочный ид-р сервера
   IsClustered: boolean;        // Флаг включения в серверный кластер
   Version: RSQLServerVersion;  // Версия сервера
   Port: integer;               // Коммуникационный порт
   Path: string;                // Путь к серверу в сети
 end;

procedure SQLServ_GetServersList(SQLServerList: TList);
//  Процедура посылает по сети широковещательный запрос по порту 1434 и ждет
//  100 мс, затем буфер сокета, просматривается на наличие "ответов" от MS SQL Server
//  Кажый пакет извлекается в буфер в виде строки, парсируется и информация
//  заполняет декскриптор TMSSQLServerDef, который добавляется в список,
//  адрес которого указан вх.параметром
var
 hSocket: TSocket;
 WSAData: TWSAData;
 Buf: array[0..65535] of byte;
 i, tRes, tLenSA, tLenBufRecv: integer;
 tLenBufIOCTL: u_long;
 S: AnsiString;
 saSQLSend, saSQLRecv: sockaddr_in;
 Data: byte;
 ServDef: PMSSQLServerDef;
 ls: TStrings;

const
 fBroadcast: boolean = True;

begin
 // Очистка списка серверов
 for i := 0 to SQLServerList.Count-1 do
   Dispose(PMSSQLServerDef(SQLServerList[i]));
 SQLServerList.Clear;
 Data := $02;
 WSAStartup(MakeWord(2,2), WSAData);    // Инициализация Win DLL версии 2.2. (WS2_32.DLL)
 //Получение дескриптора сокета UDP
 hSocket := Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 if (hSocket = INVALID_SOCKET) then exit;
 //Установка опций сокета
 tRes := setsockopt(hSocket, SOL_SOCKET{IPPROTO_TCP}, SO_BROADCAST, @fBroadcast, sizeof(BOOL));
 if (tRes = SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
 //Установка данных служебной структуры  sockaddr_in
 saSQLSend.sin_family  := AF_INET;
 saSQLSend.sin_port := htons(1434);
 saSQLSend.sin_addr.s_addr := htonl(INADDR_BROADCAST);
 //Посылка широковещательного сообщения
 tRes := sendto(hSocket, Data, 1, 0, saSQLSend, sizeof(SOCKADDR_IN));
 if (tRes = SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
 Sleep(100);  // Ожидание ответа на пакет-запрос
 tRes := ioctlSocket(hSocket,FIONREAD,tLenBufIOCTL);  // Опрос состояния сокета
 if (tRes = SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
 if (tLenBufIOCTL>0) then // В буфере сокета (порта) есть данные
   begin
    tLenSA := sizeof(SOCKADDR_IN);
    saSQLRecv := saSQLSend;
    while tLenBufIOCTL>0 do  // Пока не просмотрен весь буфер
      begin
       // Чтение очередного пакета из буфера сокета
       tLenBufRecv := recvfrom(hSocket, Buf, 65535, 0, saSQLRecv, tLenSA);
       // Уменьшение буфера на длину считанных данных (типа удаление пакета из буфера)
       tLenBufIOCTL := tLenBufIOCTL-tLenBufRecv;
       if(tLenBufRecv=SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
       // Содержимое пакета -> строку
       s := ""; for i := 3 to tLenBufRecv-3 do s := s+Chr(Buf[i]);
       // Парсинг полученной информации и упаковка ее в структуру
       ls := TStringList.Create;
       // Строку порезать на строки (разделитель ";")
       while Length(s)>0 do
         begin
          i := Pos(";",s);
          if i>0 then
            begin ls.Add(Trim(Copy(s,1,i-1))); Delete(s,1,i); end
          else
            begin ls.Add(s); s := ""; end;
         end;
         // Разбор списка строк, где нечетная содержит ключ, а четное - его значение
         if ls.IndexOf("ServerName")>-1 then
           begin
            // Создание нового дескриптора
            ServDef := NEW(PMSSQLServerDef);
            // Имя сервера
            if ls.Count>(ls.IndexOf("ServerName")+1) then
               ServDef.ServerName := ls[ls.IndexOf("ServerName")+1];
            // Установочный идентификатор
            if (ls.IndexOf("InstanceName")>-1) and
               (ls.Count>(ls.IndexOf("InstanceName")+1)) then
               ServDef.InstanceName := ls[ls.IndexOf("InstanceName")+1];
            // Флаг принадлежности к кластеру
            if (ls.IndexOf("IsClastered")>-1) and
               (ls.Count>(ls.IndexOf("IsClastered")+1)) then
               ServDef.IsClustered := not (ls[ls.IndexOf("IsClastered")+1]="No");
            // Версия сервера
            if (ls.IndexOf("Version")>-1) and
               (ls.Count>(ls.IndexOf("Version")+1)) then
              begin
               S := ls[ls.IndexOf("Version")+1];
               // Найти первую точку
               i := Pos(".",S);
               if i>0 then
                 begin
                  ServDef.Version.VersNum := Copy(S,1,i-1);
                  ServDef.Version.ModNum := Copy(S,i+1,Length(S)-i);
                 end
               else
                 begin
                  ServDef.Version.VersNum := S;
                  ServDef.Version.ModNum := "";
                 end;
              end;
            // Адрес коммуникационного порта
            if (ls.IndexOf("tcp")>-1) and
               (ls.Count>(ls.IndexOf("tcp")+1)) then
                ServDef.Port := StrToIntDef(ls[ls.IndexOf("tcp")+1],0);
            // Сетевой путь к серверу
            if (ls.IndexOf("np")>-1) and
               (ls.Count>(ls.IndexOf("np")+1)) then
                ServDef.Path := ls[ls.IndexOf("np")+1];
            SQLServerList.Add(ServDef);
           end;
      end;
   end;
 closeSocket(hSocket);
 WSACleanup;
end;


 
MsGuns ©   (2006-10-17 10:05) [3]

function SQLServ_GetServerDBList(SQLServer: PMSSQLServerDef; ListDB: TStrings): boolean;
// Создается объект TADOConnection с "пустой" БД (Initial Catalog)
// и User ID = "sa". Затем создается объект TADOQuery, привязывается к
// соединению и выполняющий зпрос к системной таблице sysdatabases
// Полученный НД сканируется и содержимое первого поля НД (имена Баз Данных)
// заполняет список ListDB
//  Возвращаемый результат содержит false, если соединение с указанным сервером
// не может быть установлено либо запрос не был выполнен нормально
begin
 result := true;
 ListDB.Clear;
 with TADODataSet.Create(nil) do
   try
     ConnectionString := "Provider=SQLOLEDB;Persist Security Info=false"+
                        ";User ID=sa;Data Source="+SQLServer.ServerName;
     CommandText := "use master select * from sysdatabases";
     try
       Open;
       while not EOF do
         begin ListDB.Add(Fields[0].AsString); Next; end;
       Close;
     except
      result := false;
     end;
   finally
     Free;
   end;
end;

function SQLServ_GetServerTableList(SQLServer: PMSSQLServerDef; DataBase: string; ListTables: TStrings): boolean;
begin
 ListTables.Clear;
 with TADODataSet.Create(nil) do
   try
     ConnectionString := "Provider=SQLOLEDB;"+
                         ";Persist Security Info=false"+
                         ";User ID=sa"+
                         ";Data Source="+SQLServer.ServerName;
     CommandText := "use "+DataBase+" select * from sysobjects where xtype="+QuotedStr("u");
     try
       Open;
       while not eof do
         begin
          ListTables.Add(Fields[0].AsString);
          Next;
         end;
       Close;
       result := true;
     except
       result := false;
     end;
   finally
     Free;
   end;
end;


 
MsGuns ©   (2006-10-17 10:11) [4]

 // Дескриптор SQL колонки (поля)
 PSQLFieldDef = ^RSQLFieldDef;
 RSQLFieldDef = record
   FldName: string;
   PKey: boolean;
   AInc: boolean;
   IsNULL: boolean;
   FldType: string;
   FType: TFieldType;
   Length: word;
   Scale: byte;
   Description: string;
 end;

function SQLServ_GetTableFieldsList(SQLServer: PMSSQLServerDef; DataBase,TableName: string; ListFields: TList): boolean;
var
 i: integer;
 fd: PSQLFieldDef;

begin
 result := false;
 for i := 0 to ListFields.Count-1 do Dispose(PSQLFieldDef(ListFields[i]));
 ListFields.Clear;
 with TADODataSet.Create(nil) do
   try
    ConnectionString := "Provider=SQLOLEDB;"+
                       ";Persist Security Info=false"+
                       ";User ID=sa"+
                       ";Data Source="+SQLServer.ServerName;
    CommandText := "use "+DataBase+" Exec sp_columns "+TableName;
    Open;
    while not EOF do
      begin
       fd := NEW(PSQLFieldDef);
       fd.FldName := FieldByName("COLUMN_NAME").AsString;
       fd.PKey := false;
       fd.FldType := FieldByName("TYPE_NAME").AsString;
       fd.AInc := (Pos("IDENTITY",UpperCase(fd.FldType))>0);
       fd.IsNULL := (FieldByName("IS_NULLABLE").AsString="YES");
       fd.Length := StrToInt(FieldByName("LENGTH").AsString);
       fd.Scale := 0;
       if UpperCase(fd.FldType)="NUMERIC" then
          fd.Scale := StrToInt(FieldByName("SCALE").AsString);
       fd.Description := "No Description";
       ListFields.Add(fd);
       Next;
      end;
    Close;
    // Извлечение описателей
    CommandText := "use "+DataBase+" select sc.name, sp.value "+
                   "from sysobjects so, syscolumns sc, sysproperties sp "+
                   "where so.id=sc.id and so.id=sp.id and "+
                   "sp.smallid=sc.colorder and so.name="+QuotedStr(TableName);
    Open;
    for i := 0 to ListFields.Count-1 do
      if Locate(Fields[0].FieldName,PSQLFieldDef(ListFields[i]).FldName,[]) then
         PSQLFieldDef(ListFields[i]).Description := Fields[1].AsString;
    Close;
    result := true;
   finally
    Free;
   end;
end;


 
svt   (2006-10-17 10:11) [5]


> ЮЮ ©   (17.10.06 09:55) [1]


> MsGuns ©   (17.10.06 10:03) [2]

весьма благодарен


 
MsGuns ©   (2006-10-17 10:11) [6]

 // Дескриптор SQL колонки (поля)
 PSQLFieldDef = ^RSQLFieldDef;
 RSQLFieldDef = record
   FldName: string;
   PKey: boolean;
   AInc: boolean;
   IsNULL: boolean;
   FldType: string;
   FType: TFieldType;
   Length: word;
   Scale: byte;
   Description: string;
 end;

function SQLServ_GetTableFieldsList(SQLServer: PMSSQLServerDef; DataBase,TableName: string; ListFields: TList): boolean;
var
 i: integer;
 fd: PSQLFieldDef;

begin
 result := false;
 for i := 0 to ListFields.Count-1 do Dispose(PSQLFieldDef(ListFields[i]));
 ListFields.Clear;
 with TADODataSet.Create(nil) do
   try
    ConnectionString := "Provider=SQLOLEDB;"+
                       ";Persist Security Info=false"+
                       ";User ID=sa"+
                       ";Data Source="+SQLServer.ServerName;
    CommandText := "use "+DataBase+" Exec sp_columns "+TableName;
    Open;
    while not EOF do
      begin
       fd := NEW(PSQLFieldDef);
       fd.FldName := FieldByName("COLUMN_NAME").AsString;
       fd.PKey := false;
       fd.FldType := FieldByName("TYPE_NAME").AsString;
       fd.AInc := (Pos("IDENTITY",UpperCase(fd.FldType))>0);
       fd.IsNULL := (FieldByName("IS_NULLABLE").AsString="YES");
       fd.Length := StrToInt(FieldByName("LENGTH").AsString);
       fd.Scale := 0;
       if UpperCase(fd.FldType)="NUMERIC" then
          fd.Scale := StrToInt(FieldByName("SCALE").AsString);
       fd.Description := "No Description";
       ListFields.Add(fd);
       Next;
      end;
    Close;
    // Извлечение описателей
    CommandText := "use "+DataBase+" select sc.name, sp.value "+
                   "from sysobjects so, syscolumns sc, sysproperties sp "+
                   "where so.id=sc.id and so.id=sp.id and "+
                   "sp.smallid=sc.colorder and so.name="+QuotedStr(TableName);
    Open;
    for i := 0 to ListFields.Count-1 do
      if Locate(Fields[0].FieldName,PSQLFieldDef(ListFields[i]).FldName,[]) then
         PSQLFieldDef(ListFields[i]).Description := Fields[1].AsString;
    Close;
    result := true;
   finally
    Free;
   end;
end;


 
Johnmen ©   (2006-10-17 10:15) [7]

Вот из фака
Список баз, доступных юзеру
=======================
select name from master.dbo.sysdatabases d
where d.status & ltrim(str(convert(int, 0x03e0), 11)) = 0
 and has_dbaccess(d.name) = 1


 
svt   (2006-10-17 10:25) [8]


> MsGuns ©   (17.10.06 10:11) [6]

Ну спасибо.... информации намного больше чем  я ожидал. благодарен.


 
MsGuns ©   (2006-10-17 10:52) [9]

Процедура опроса доступных в сети серверов не совершенна т.к. зависит от загрузки сети и "реактивности" скл-серверов. Иногда она возвращает неполный список (например, если некоторый шибко загруженный работой сервер не "успел" откликнуться за отведенную десятую секунды).
Я рекомендую  сверять полученный список с некоторой сохраненной ранее информацией о физическом наличии в сети скл-серверов и полученный список сверять с этими данными. Если обнаружится "отсутствующий", то выполнить любой запрос именно к нему в защищенном блоке, чтобы заставить "ленивого" откликнуться либо убедиться в его неактивности (либо отсутствии временно или постоянно).

Этот алгоритм полезен в случаях, когда полный список активных серверов достаточно критичен. Вообще же редко есть необходимость определять с клиента полный перечень активных серверов, т.к. работа идет с конкретной БД, расположенной на конкретном же сервере.



Страницы: 1 вся ветка

Текущий архив: 2006.11.05;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.051 c
2-1161366808
имя
2006-10-20 21:53
2006.11.05
My Proxy 7.56


15-1160935733
Palladin
2006-10-15 22:08
2006.11.05
Are you dead yet!?


15-1161096206
Sergey Masloff
2006-10-17 18:43
2006.11.05
незаметное событие


15-1160997723
DillerXX
2006-10-16 15:22
2006.11.05
Лобанов Александр - "Жестокая Голактика"


15-1160676300
Loginov Dmitry
2006-10-12 22:05
2006.11.05
[Builder 6] Приведение объектных типов