Работа с PostgreSQL. У кого есть элементтарный пример?
Модератор: Модераторы
Работа с PostgreSQL. У кого есть элементтарный пример?
Приветствую вас!
Подскажите, может у кого то есть готовый пример кода, с подключением к PostgreSQL и элементарной работой с БД (допустим запрос создания пользователя).
Подскажите, может у кого то есть готовый пример кода, с подключением к PostgreSQL и элементарной работой с БД (допустим запрос создания пользователя).
- NXP
- постоялец
- Сообщения: 187
- Зарегистрирован: 02.01.2008 15:11:56
- Откуда: Воронеж
- Контактная информация:
Вот кусок кодов консольного сервера , работающего с Postgres
Нало всего с...
инициализация...
Вот собственно использование...
Содержимое файла auth_user.sql:
Учить SQL можно в PGAdmin
Нагляднее примера нет, т.к еще не доделал (
еще потребуются эти либы:
comerr32.dll
krb5_32.dll
libeay32.dll
libiconv-2.dll
libintl-2.dll
libpq.dll
ssleay32.dll
Код: Выделить всё
uses Classes, Crt, SysUtils, lNet, SQLDB, PQConnection,
TServer = class (TThread) {* сервер обмена файлами *}
private
SQLQuery: TSQLQuery; {коммандный процессор SQL}
SQLTransaction: TSQLTransaction; {координатор транзакций}
PQConnection: TPQConnection; {интерфейс PostgreSQL сервера}
public
constructor Create(Params: pSRVParamRec);
destructor Destroy; override;
protected
procedure Execute; override;
end;Нало всего с...
Код: Выделить всё
constructor TServer.Create(Params: pSRVParamRec);
begin
SQLQuery:= TSQLQuery.Create(nil);
SQLTransaction:= TSQLTransaction.Create(nil);
PQConnection:= TPQConnection.Create(nil);
inherited Create(false);
end;
destructor TServer.Destroy;
begin
PQConnection.Close;
SQLQuery.Free;
SQLTransaction.Free;
PQConnection.Free;
inherited Destroy;
end;
инициализация...
Код: Выделить всё
procedure TServer.Execute;
begin
try {подключение к SQL}
PQConnection.HostName:= Param^.SQL_Server;
PQConnection.UserName:= Param^.SQL_User;
PQConnection.Password:= Param^.SQL_Password;
PQConnection.DatabaseName:= Param^.SQL_DateBase;
PQConnection.Open;
SQLQuery.DataBase:= PQConnection;
SQLQuery.Transaction:= SQLTransaction;
SQLTransaction.DataBase:= PQConnection;
PQConnection.Transaction:= SQLTransaction;
except
on E: Exception do begin
LogMsg:= '@Execute: ' + E.Message;
Log(LogMsg);
Param^.Critical_Log(LogMsg);
Terminate;
end;
end;
+++
end;Вот собственно использование...
Код: Выделить всё
procedure TServer.SrvReceive(aSocket: TLSocket);
function UserAuth(Rec: pSocketRec): boolean; {SQL запрос для проверки user/pass}
var Count: integer = 0;
SQL_File: TStringList;
begin
Result:= false;
if (Rec^.User_Code < 1) or {Преподавательский состав ID < 0}
(Length(Rec^.User_Password) < 1) then exit(false); {пароль не может быть пустым}
try
SQL_File:= TStringList.Create;
SQL_File.LoadFromFile(Param^.SQL_Path + DirectorySeparator + 'auth_user.sql');
SQLQuery.SQL.Text:= SQL_File.Text;
SQL_File.Free;
SQLQuery.Params.ParamByName('SI_USRCOD').Value:=Rec^.User_Code;
SQLQuery.Params.ParamByName('SI_PASS').Value:=Rec^.User_Password;
SQLQuery.Open;
while (not SQLQuery.EOF) do begin
SQLQuery.Next;
inc(count);
end;
SQLQuery.ClearFields;
SQLQuery.Close;
if (Count = 1) then exit(True) else exit(false);
except
on E: Exception do begin
+++
end;
end;
end;
begin
+++
if not UserAuth(Client) then begin ...
+++
end;Содержимое файла auth_user.sql:
Код: Выделить всё
SELECT * FROM users WHERE usr_id = :SI_USRCOD AND passwd = :SI_PASS AND blocked = FALSEУчить SQL можно в PGAdmin
Нагляднее примера нет, т.к еще не доделал (
еще потребуются эти либы:
comerr32.dll
krb5_32.dll
libeay32.dll
libiconv-2.dll
libintl-2.dll
libpq.dll
ssleay32.dll
У меня вопрос. использую lazarus 0.9.25 fps 2.2.1 + PostgreeSQL 8.3 (WinXP) / Связка PQConnection -> SQLTransaction->SQLQuery /
при запросе на выборку тоесть Select // все работает..
НО при запросе Insert Into или Update выскакивает ошибка
"Cannot open non-select statement " В чем может быть проблема?
для наглядности приведу элементарный пример с сохранением синтаксиса. " Insert into "User_name" (id, "name") Values (8, 'Vasia'); "
Заранее благодарю.
в одном из постов на форуме видел что при использовании Inser Into Update или SET нужно использовать не SQLQuery.Open а ExecSQL... пробовал.. ошибка не появляется но и в таблицу ничего не добавляется
при запросе на выборку тоесть Select // все работает..
НО при запросе Insert Into или Update выскакивает ошибка
"Cannot open non-select statement " В чем может быть проблема?
для наглядности приведу элементарный пример с сохранением синтаксиса. " Insert into "User_name" (id, "name") Values (8, 'Vasia'); "
Заранее благодарю.
в одном из постов на форуме видел что при использовании Inser Into Update или SET нужно использовать не SQLQuery.Open а ExecSQL... пробовал.. ошибка не появляется но и в таблицу ничего не добавляется
Присоединяюсь к последнему сказанному, хоть двух годовалой давности сообщение
Выложите, пожалуйста, свой пример программы. Все работает прекрасно за исключением кодировки UTF8, если база в этой кодировке, то будет обрезать кириллические строки, но есть патч для FPC устраняющий эту проблему.
до глубины души согласен.Zorro писал(а):в одном из постов на форуме видел что при использовании Inser Into Update или SET нужно использовать не SQLQuery.Open а ExecSQL... пробовал.. ошибка не появляется но и в таблицу ничего не добавляется
Запрос - INSERT INTO s1.t1(pole)VALUES (99);
все как бы просто, не правдали?
как программим (способ 1 - ошибка запроса на стадии SQLQuery1.SQL.Add)
Код: Выделить всё
PQConnection1.Connected:=true;
except
.............
end;
try
SQLTransaction1.Active:=true;
except
.................
end;
try
SQLQuery1.Close;
SQLQuery1.SQL.Clear;
SQLQuery1.Insert;
SQLQuery1.SQL.Add('INSERT INTO s1.t1(pole)VALUES (99);');
SQLQuery1.Open;
except
.................
end;
как программим (способ 2 - кто нибудь есть дома? ну или что то делается но результата не видно, но делается точно так как нельзя создать 2-ды таблицу с одинаковым именем)
Код: Выделить всё
PQConnection1.Connected:=true;
except
.............
end;
try
SQLTransaction1.Active:=true;
except
.................
end;
try
SQLQuery1.Close;
SQLQuery1.SQL.Clear;
SQLQuery1.SQL.Add('INSERT INTO s1.t1(pole)VALUES (99);');
SQLQuery1.ExecSQL;
except
.................
end;
SQLQuery1.Open или SQLQuery1.Active := True применяется только для получения данных при использовании SELECT. Остальные операции CREATE, INSERT, DELETE, UPDATE - выполняются SQLQuery1.ExecSQL;
SQLQuery1.SQL.Add('INSERT INTO s1.t1(pole)VALUES (99);'); - перед VALUES должен быть обязательно пробел. "pole" какого типа? Если строка, то 99 нужно взять в одинарные кавычки.
В принципе, PQConnection неплохо сообщает об ошибках, я не знаю, как Вы обрабатываете ошибки на except, если никак, то лучше уберите кострукции try except, будет яснее картина с ошибками.
Добавлено спустя 14 минут 8 секунд:
Вот реальный пример, скопировал из работающей программы:
SQLQuery1.SQL.Add('INSERT INTO s1.t1(pole)VALUES (99);'); - перед VALUES должен быть обязательно пробел. "pole" какого типа? Если строка, то 99 нужно взять в одинарные кавычки.
В принципе, PQConnection неплохо сообщает об ошибках, я не знаю, как Вы обрабатываете ошибки на except, если никак, то лучше уберите кострукции try except, будет яснее картина с ошибками.
Добавлено спустя 14 минут 8 секунд:
Вот реальный пример, скопировал из работающей программы:
Код: Выделить всё
procedure TfrmTools.DoSaveIPsToDB(v_contype, v_class, v_net, v_mask, v_gateway,
v_broadcast, v_state, v_name: String);
begin
try
sqlToolsActions.SQL.Text :=
'INSERT INTO localip('
+'lip_contype, lip_class, lip_net, lip_mask, lip_gateway, '
+'lip_broadcast, lip_state, lip_name) '
+'VALUES ('
+v_contype+', ' //lip_contype
+v_class +', ' //lip_class
+v_net +', ' //lip_net
+v_mask +', ' //lip_mask
+v_gateway +', ' //lip_gateway
+v_broadcast+', ' //lip_broadcast
+v_state+', ' //lip_state
+v_name //lip_name
+');';
sqlToolsActions.ExecSQL;
except
//error
end;
end;
sadavod
В способе №1 надо делать немного иначе:
C update тоже самое, только самый первый запрос должен возвращать редактируемую строку.
А вообще непонятно, какие могут быть проблемы, связка Lazarus + zeos +PostgreSQL работала еще год назад как швейцарские часы.
Добавлено спустя 4 минуты 56 секунд:
Хочу так же обратить внимание на преимущества связки Insert + Post: если надо вставить строку, содержащую апостроф, то его надо продублировать, так как это управляющий символ языка SQL. Для этого надо использовать функцию QuotedStr. Один раз ошибешься - получишь exception. В случае выполнения команды компонент Query делает это самостоятельно, так что никаких проблем никогда не возникнет.
В способе №1 надо делать немного иначе:
Код: Выделить всё
try
SQLQuery1.SQL.Text:='select * from mytable where <какое-нибудь условие, возвращающее заведомо ноль строк - чтобы базу не грузить почем зря>';
SQLQuery1.Open;
SQLQuery1.Insert;
SQLQuery1.FieldByName('my_integer_field').AsInteger:=123;
SQLQuery1.FieldByName('my_datetime_field').AsDateTime:=now-2; // типа позавчера
SQLQuery1.FieldByName('my_string_field').AsString:='Строка какая-нибудь';
SQLQuery1.Post;
except
.................
end;А вообще непонятно, какие могут быть проблемы, связка Lazarus + zeos +PostgreSQL работала еще год назад как швейцарские часы.
Добавлено спустя 4 минуты 56 секунд:
Хочу так же обратить внимание на преимущества связки Insert + Post: если надо вставить строку, содержащую апостроф, то его надо продублировать, так как это управляющий символ языка SQL. Для этого надо использовать функцию QuotedStr. Один раз ошибешься - получишь exception. В случае выполнения команды
Код: Выделить всё
SQLQuery1.FieldByName('my_string_field').AsString:='Строка какая-нибудь';Спасибо за ответы еще не тестировал как они работают (дома проверю отпишусь), не понятен мне это момент покамест
<какое-нибудь условие, возвращающее заведомо ноль строк
зачем это?
<какое-нибудь условие, возвращающее заведомо ноль строк
зачем это?
sadavod писал(а):Спасибо за ответы еще не тестировал как они работают (дома проверю отпишусь), не понятен мне это момент покамест
<какое-нибудь условие, возвращающее заведомо ноль строк
зачем это?
Ну как. Чтобы выполнить Query.Insert или Query.Update, нужно, чтобы датасет был открыт (т. е. сначала выполнить Query.Open). Если редактируешь - то понятно, открываем датасет с редактируемой строкой. А если открываешь датасет для вставки новой строки? То пофиг, что там будет в датасете. Я делаю что-нибудь ненапряжное для сервера. Но это для случая, когда в момент выполнения Query.Open известно, что будет дальше - Insert или Update. Если заранее незвестно, то просто открываешь то, что надо в данный момент.
Спасибо ребята, всё заработало
- dunin
- энтузиаст
- Сообщения: 634
- Зарегистрирован: 02.05.2007 13:18:11
- Откуда: Тољя††и
- Контактная информация:
Climber писал(а):sadavod
В способе №1 надо делать немного иначе:
...
Или так:
Код: Выделить всё
const
sql001 = 'Неверно заданы параметры в процедуре';
...
function InsSQL (Base:tIBConnection; TableName: string; FieldsName: array of string; NewValues: array of variant; DoCommitRetaining: boolean = True): boolean;
var iSQL: tSQLQuery;
S: string; I: Integer;
begin
if (Length(FieldsName) <> Length(NewValues))
then begin
raise Exception.Create(sql001+' InsSQL');
exit;
end;
iSQL:= tSQLQuery.Create(Base);
iSQL.DataBase:= Base;
iSQL.Transaction:= Base.Transaction;
iSQL.SQL.Clear; // ?????
iSQL.SQL.Add('insert into '+TableName+' ');
S:='';
for I:= 0 to High(FieldsName)
do S:= S + TableName+'.'+FieldsName[i]+',';
SetLength(S, Length(S)-1);
iSQL.SQL.Add('('+S+') values ');
S:='';
for I:= 0 to High(NewValues)
do S := S+':'+IntToStr(i)+',';
SetLength(S, Length(S)-1);
iSQL.SQL.Add('('+S+')');
for I:= 0 to High(NewValues)
do iSQL.Params.ParamByName(inttostr(i)).Value:= NewValues[i];
try
iSQL.ExecSQL;
if DoCommitRetaining then Base.Transaction.CommitRetaining;
finally
iSQL.Close; iSQL.Free;
Base.Transaction.Active:=True;
end;//finally
Result:= True;
end;Создаем tSQLOuery, передаем значения сразу через параметры, освобождаем. Использую когда надо оперативно что-то куда-то подпихнуть. Пример для tIBConnection. Переделать не сложно. Для удаления и пр. есть схожие функции.
Пожалуйста, дайте пример на Update. Там тоже надо через параметры передавать?
Update ничем не отличается от Insert. Все тоже самое.
