Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.043 c
15-1160668265
menart
2006-10-12 19:51
2006.11.05
Modbus


3-1157703493
Petrovski
2006-09-08 12:18
2006.11.05
Суммирование в DBGridEh


15-1160930652
Игорь Шевченко
2006-10-15 20:44
2006.11.05
А кто нибудь пробовал MONO ?


2-1161257587
Helen
2006-10-19 15:33
2006.11.05
Поменять кодировку


3-1157457438
parovoZZ
2006-09-05 15:57
2006.11.05
Создание папки в древесной структуре





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский