Форум: "Начинающим";
Текущий архив: 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.077 c