:: Visual Foxpro, Foxpro for DOS
Re: Как вызывать процедуру Postgres с OUT-параметрами
Аркадий
Автор

Сообщений: 252
Откуда: Санкт-Петербург
Дата регистрации: 30.11.2005
Так ведь нельзя написать в одну строчку
UPDATE id_counter SET @nRetVal = id_counter.id, id_counter.id = id_counter.id + 1

приходится в две
nRetVal = (select id from disp.id_counter);
UPDATE disp.id_counter SET id = id + _interval ;
что всех напрягает.
Тут транзакция не нужна?
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Аркадий
Автор

Сообщений: 252
Откуда: Санкт-Петербург
Дата регистрации: 30.11.2005
Для Postgres
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
pasha_usue

Сообщений: 3649
Откуда: Е-бург
Дата регистрации: 06.10.2006
Аркадий
Так ведь нельзя написать в одну строчку
UPDATE id_counter SET @nRetVal = id_counter.id, id_counter.id = id_counter.id + 1

приходится в две
nRetVal = (select id from disp.id_counter);
UPDATE disp.id_counter SET id = id + _interval ;
что всех напрягает.
Тут транзакция не нужна?
1. Транзакция не нужна. Вы пишете в функции, а функция по-умолчанию открывает транзакцию. Соответственно, если что-то брякнется, откатится всё, что производилось в функции.
2. А вот здесь требуется блокировка записи: (select id from disp.id_counter for update)
В противном случае, два разных клиента могут получить один и тот же айдишник, если начнут читать таблицу одновременно. Выглядеть это будет так:
client1: begin;
client1: nRetVal = (select id from disp.id_counter);
client2: begin;
client2: nRetVal = (select id from disp.id_counter);
client1: UPDATE disp.id_counter SET id = id + _interval ;
client2: UPDATE disp.id_counter SET id = id + _interval ;
client1: commit;
client2: commit;
Соответственно, оба прочитали одинаковое значение. И оба одинаково счетчик увеличили. Причём даже если бы UPDATE позволял в одну команду написать, это бы ничего не поменяло.
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Аркадий
Автор

Сообщений: 252
Откуда: Санкт-Петербург
Дата регистрации: 30.11.2005
Большое спасибо!
И осталась ещё одна проблема. Как вернуть из процедуры несколько курсоров? Пока с горем пополам удалось получить один, и то в нём каждая запись с полями через разделитель помещена в MEMO-поле.
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
pasha_usue

Сообщений: 3649
Откуда: Е-бург
Дата регистрации: 06.10.2006
Аркадий
Большое спасибо!
И осталась ещё одна проблема. Как вернуть из процедуры несколько курсоров? Пока с горем пополам удалось получить один, и то в нём каждая запись с полями через разделитель помещена в MEMO-поле.
Значит вы получили аггрегатное поле типа record. Такая конструкция в ряде случаев разворачивает record:
SELECT * FROM (<<Your subselect returning record>>) CurSubselect


А возвратить несколько курсоров... Можно, конечно, попробовать выгонять в OUT параметры данные с определённым типом. Но факт, о нём ни ODBC ничего не знает, ни фокс тем более.
Может быть лучше в функции создавать временные таблицы, которые будут жить до конца транзакции. А потом отдельными запросами эти временные таблицы вытаскивать, после чего коммитить транзакцию.
BEGIN;
SELECT MyFunction();
SELECT * FROM MyTable1;
SELECT * FROM MyTable2;
COMMIT;

А таблицу создавать в функции так:
CREATE TEMP TABLE ... ON COMMIT DROP;
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Аркадий
Автор

Сообщений: 252
Откуда: Санкт-Петербург
Дата регистрации: 30.11.2005
Спасибо, попробую.
В SQL Server я без всяких параметров делал сколько угодно SELECT-ов и получал их в
SQLEXEC(nStatementHandle [, cSQLCommand [, cCursorName[, aCountInfo]]])
под именами cCursorName, cCursorName1, cCursorName2...
Наверное, тот ODBC умнее.
Похоже, легче вообще отказаться от Postgre-совских процедур и всё делать через SQLEXEC().
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
pasha_usue

Сообщений: 3649
Откуда: Е-бург
Дата регистрации: 06.10.2006
Аркадий
Спасибо, попробую.
В SQL Server я без всяких параметров делал сколько угодно SELECT-ов и получал их в
SQLEXEC(nStatementHandle [, cSQLCommand [, cCursorName[, aCountInfo]]])
под именами cCursorName, cCursorName1, cCursorName2...
Наверное, тот ODBC умнее.
Похоже, легче вообще отказаться от Postgre-совских процедур и всё делать через SQLEXEC().
В примере выше по временным таблицам как раз возвращается много курсоров.

Можно так же вернуть много курсоров из функции, без временных таблиц. Проблема в том, что вы такой ответ переварить на фоксе не можете. По сути это будет record[], каждая колонка которого - record[], возможно и с большей степенью вложенности. По-моему, Java переваривает такое издевательство.

Pervasive.SQL попробуйте. Вот где наркомания.
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Аркадий
Для этого я завёл свой счётчик.
"счётчик" это объект sequence - с недавних пор он есть и в Mssql. А вовсе не убогий, да ещё и неправильный в реализации "update таблицы из 1 записи".
Аркадий
я смогу всюду использовать свои базовые классы с подобными процедуринами.
Какое страшное заблуждение - оно ведёт к просто таки безобразным архитектурным решениям, наподобии вышеупомянутого update...
Слой абстракции должен просто позволять использовать разные механизмы, присущие разным СУБД - и да, поддерживать можно 1-2-3 и даже 10 различных СУБД, но КОНКРЕТНО прописывая служебный/системный код для каждой из них, а никак не каким-то "универсальным" кодом. Ну и да, в этом случае следует свести к абсолютному минимуму использование ХП, да и различных типов данных, ограничившись самыми примитивными и базовыми. Даже "логический" тип подпадает под запрет, не говоря уж про таймстамп, дату без времени, всякие хитрые числа, например повышенной тончности, или "ограничиваемые" диапазоном целочисленных byte/int/long...
Возможно какой-то из ODBC драйверов для постгреса и реализует штатный ODBC-ный синтаксис вызова ХП {call ... } включая возможность получать назад значения для OUT/INOUT параметров - но это надо внимательно искать в документации к этому самому драйверу.
EXEC это вообще чисто MSSQL-ный синтаксис, и другими СУБД как правило не поддерживается.


------------------
WBR, Igor
Ratings: 0 negative/1 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Аркадий
Автор

Сообщений: 252
Откуда: Санкт-Петербург
Дата регистрации: 30.11.2005
Вот-вот, моя процедурина обогатилась специальным кодом для Postgres. Вся универсальность - её имя.
К несчастью, новый SQL Server из-за скупердяйства нам не купили, а группа энтузиастов на этой почве решила завести бесплатную неизведанную систему, что-то понаписала и свалила.
С непривычки отсутствие возможности естественным, казалось бы, образом удовлетворить примитивные потребности немного бесит, т. к. надо пользоваться теми данными.
И команда EXECUTE там есть, но что-то не запускается. И конечно хранимые процедуры были бы подспорьем.



Исправлено 1 раз(а). Последнее : Аркадий, 06.11.18 10:00
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Berloga

Сообщений: 72
Откуда: Нефтекамск
Дата регистрации: 19.12.2007
Цитата:
Подскажите, пожалуйста, если кто-нибудь работает в Postgres, как, для примера, создать и вызвать из фокса простейшую процедуру
На сервере
CREATE OR REPLACE FUNCTION test_out(INOUT par1 integer, INOUT par2 integer)
RETURNS record AS
$BODY$begin
par1 := par1+1;
par2 := par2-1;
return;
end;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
На клиенте
Local lnPar1, lnPar2, lcCom
lnPar1 = 1
lnPar2 = 2
lcCom = [{CALL test_out(?@lnPar1::int,?@lnPar2::int)}]
SQLExec(nStatementHandle,lcCom)
Драйвер PostgreSQL ANSI 09.01.0200 (20 августа 2012 г.; 10:02:48)

Насчет dbo.new_id совсем не понял, что Вы хотите. Может Вам поможет help - UPDATE
UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
WHERE city = 'San Francisco' AND date = '2003-07-03'
RETURNING temp_lo, temp_hi, prcp;
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Berloga

Сообщений: 72
Откуда: Нефтекамск
Дата регистрации: 19.12.2007
А теперь понятно.
insert into sdadd.email (email) values ('def');
select currval('sdadd.my_big_sequence'::regclass);
Можно поменять на одну команду
insert into sdadd.email (email) values ('def') returning id



Исправлено 1 раз(а). Последнее : Berloga, 06.11.18 15:23
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Процедура генерирующая уникальные "номера записей", равно как и поддерживающая её таблица попросту не нужны в большинстве СУБД, т.к. там есть другие механизмы для этого. Да, в MSSQL без сиквенсов может понадобиться подобная процедура - только её как правило делают совсем не с помошью Update служебной таблицы - т.к. это весьма кривое решение. И при том 1-в-1 оно гарантированно не переносится в другие СУБД - придётся там свои велосипеды создавать- где с треугольными колёсами, где с квадратными...
Да, я понимаю что сложно отказаться от ранее принятого изначально кривого "проектного решения", тем более если система уже достаточно старая, кода понаписан вагон... Такая же фигня была, если что. Ещё и id генерились с шагом в 100 - "для целей репликации", которая никогда в изначально задуманом виде и не была реализована, а то как оно было сделано не нуждалось в подобном костыле. Так что я знаю как должна выглядеть ХП генерящая id-ники по вспомогательной таблице, и насколько это плохое решение по итогу...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
of63

Сообщений: 25254
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
()
Не дай бох, доживу до необходимости иметь таблички >2Г (должно было хватить аккурат к пенсии как раз, по расчетам, но Пу сдвинул рамки ). Пока я действительно, имел физическую сетевую табличку табличку для занятия уникальных номеров, метода такая:
- занимаю табличку экслюзивно (USE EXCLUSE, транзакция начинается типа)
- занимаю в ней номер свободный номер, по методу "последний +1" (там не единственная запись, а по количеству всяких "ресурсов", необходимых в работе. Ну типа, как бы много табличек, но все в одной, в виде записей)
- отпускаю табличку из эксклюива (просто закрываю, USE)
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Аркадий
Автор

Сообщений: 252
Откуда: Санкт-Петербург
Дата регистрации: 30.11.2005
Спасибо. Поэкспериментирую со всеми вариантами.
Ratings: 0 negative/0 positive
Re: Как вызывать процедуру Postgres с OUT-параметрами
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Подходу NewId сто лет в обед - он в примерах фокса есть, когда ещё никаких AUTOINC и в помине не было. Он "идеологически", конечно, совпадает с вариантом автора темы - но там все нюансы в реализации. Даже фоксовый код гораздо больше тривиального Update 1 записи - ручные блокировки и т.п.
Для серверов, естественно, тоже потребуется код заметно сложнее указанного update - и тоже для обеспечения безошибочной генерации реально уникальных значений в условиях многопользовательской и конкуретной работы с БД.
Мой пункт был в том, что в большинстве "больших" СУБД этот вопрос так или иначе уже решён силами самой СУБД. Грубо говоря там уже есть "встроенная" функция делающая такую работу - конечно же она реализована и эффективнее и "правильнее" чем любой самодельный вариант. Проблема в том что эти "функции" разные в разных СУБД, и никакой "универсализации" нет. Но вполне можно сделать свои легковесные "обёртки" - над теми же sequence к примеру. Лучше - со стороны фокса, но можно и со стороны самой СУБД, если она позволяет соответствующие ХП писать. Постгрес и оракл должны позволять - вот и пример вызова для конкретного ODBC драйвера показали.
Это если не менять сам подход


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 19 iczelion  (Гостей: 18)

© 2000-2024 Fox Club 
Яндекс.Метрика