powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Создание/использование хранимых процедур
23 сообщений из 23, страница 1 из 1
Создание/использование хранимых процедур
    #39734945
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго дня!
Вообщем идея такая - есть 2 таблицы:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TABLE LOGS (
    ID      IDTYPE,
    GRP     INTEGER,
    EVNT    INDEXTYPE,
    USR     INDEXTYPE,
    EXTINT  EXTINTTYPE,
    OUTINT  EXTINTTYPE,
    DTIME   TIMESTAMP
);



и

Код: sql
1.
2.
3.
4.
CREATE TABLE EXTSTRING (
    ID   IDTYPE,
    STR  VARCHAR(150)
);



Поле EXTINT таблицы LOGS связано с полем ID таблицы EXTSTRING, причем не всегда, чаще всего там пустое значение,
также несколько записей из таблицы LOGS могут ссылаться на одну запись из таблицы EXTSTRING.

В случае добавления новой записи в таблицу LOGS, с учетом того, что будет связь с таблицей EXTSTRING возникает
необходимость совершить следующее:
1. Проверить, имеется ли такая же строка как и входящая в таблице EXTSTRING, если нет, создать ее
2. Вернуть значение ID из таблицы EXTSTRING на нужную строку
3. Добавить новую запись в таблицу LOGS, в котором поле EXTINT равно ID из пункта 2.

В соответствии с этим рисую stored proc:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE PROCEDURE CHECK_ID_EXTSTR
    (EXTSTR VARCHAR(150))
RETURNS
    (ID INT)
AS  DECLARE VARIABLE TID INTEGER;
BEGIN
 SELECT TID
 FROM extstring
 WHERE (STR = EXTSTR)
 INTO TID;
 ID = TID;
 IF (TID IS NULL) THEN BEGIN
   TID = gen_id(GEN_LOGS_ID, 1);
   INSERT INTO extstring(TID, STR)
   VALUES(TID, EXTSTR);
   ID = TID;
 END
 INTO ID;
END



Ну и вопросы:
1. Что-то не то с процедурой. Строка 10 "INTO TID2;" - не нужна, но если ее убрать - ругается на IF (TID IS NULL)..., если оставить - ругается на строку 18 "INTO ID;" - ошибка стандартная: "Token unknown".
2. Получу ли я реально значение генератора, и занесение его в таблицу, как в строках 13, 14? Просто именно это значение
мне и нужно вернуть из процедуры.
3. Будет ли работать процедура в таком запросе:

Код: sql
1.
2.
INSERT INTO logs(id, grp, EVNT, usr, DTIME ,extint, OUTINT)
VALUES(gen_id(GEN_LOGS_ID, 1), 100, 100, 30, '13.11.2018 16:44:58', CHECK_ID_EXTSTR('новая_строка'), 0)



Ну вот как-то так...
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734954
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg,

Перед параметрами в текстах любых запросов надо ставить двоеточие.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734965
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Переделал так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE PROCEDURE CHECK_ID_EXTSTR
    (EXTSTR VARCHAR(150))
RETURNS
    (ID INT)
AS  DECLARE VARIABLE TID INTEGER;
BEGIN
 SELECT ID TID
 FROM extstring
 WHERE (STR = :EXTSTR)
 INTO :TID;
 ID = TID;
 IF (TID IS NULL) THEN BEGIN
   TID = gen_id(GEN_EXTSTRING_ID, 1);
   INSERT INTO extstring(ID, STR)
   VALUES(:TID, :EXTSTR);
   ID = TID;
 END
-- INTO :ID;
END



Создание процедуры вроде как прокатило, но вот при попытке вызова:

Код: sql
1.
2.
INSERT INTO logs(id, grp, EVNT, usr, DTIME ,extint, OUTINT)
VALUES(gen_id(GEN_LOGS_ID, 1), 100, 100, 30, '13.11.2018 16:44:58', CHECK_ID_EXTSTR('новая_строка'), 0)



получаю ошибку:

SQL error code = -804.
Function unknown.
CHECK_ID_EXTSTR.

Бред какой-то... Может ее как то по другому вызывать нужно? Но gen_id прокатывает-то...?
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734969
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg,

ты процедуру с функцией путаешь. Процедуры вызываются иначе. Или через EXECUTE PROCEDURE или через SELECT ... FROM PROC(...)
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734971
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg,

Добавь в процедуру suspend и попробуй получить значение из нее при помощи select. Но почему бы тебе и собственнно вставку не переместить внутрь процедуры?
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734973
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg,

Сервер, кстати, какой версии?
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734974
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vlad F,

Firebird 2.5
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734981
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg,

Тогда "легким движением" переделать ее на функцию не получится. В тройке было бы проще.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734985
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,

с одной стороны да, с другой — функции с побочным эффектом bad design
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734990
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

С каким таким побочным эффектом?
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734996
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,

У него процедура вставкой еще занимается. В функцию лучше такого не засовывать - по сути ты вызываешь проверку, а вместо простой проверки у тебя еще в разных местах какие-то записи появляются. Неочевидно по прошествии некоторого времени.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39734997
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Переделал вот так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE PROCEDURE CHECK_ID_EXTSTR
    (EXTSTR VARCHAR(150))
RETURNS
    (ID INT)
AS  DECLARE VARIABLE TID INTEGER;
BEGIN
 SELECT ID TID
 FROM extstring
 WHERE (STR = :EXTSTR)
 INTO :TID;
 ID = TID;
 IF (TID IS NULL) THEN BEGIN
   TID = gen_id(GEN_EXTSTRING_ID, 1);
   INSERT INTO extstring(ID, STR)
   VALUES(:TID, :EXTSTR);
   ID = TID;
 END
 SUSPEND;
-- INTO :ID;
END



и запрос:

Код: sql
1.
2.
INSERT INTO logs(id, grp, EVNT, usr, DTIME ,extint, OUTINT)
VALUES(gen_id(GEN_LOGS_ID, 1), 100, 100, 30, '13.11.2018 16:44:58', (SELECT ID FROM CHECK_ID_EXTSTR('новая_строка')), 0)



И всё заработало!!!
Спасибо всем за помощь!
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735000
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOlegПеределал так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE PROCEDURE CHECK_ID_EXTSTR
    (EXTSTR VARCHAR(150))
RETURNS
    (ID INT)
AS  DECLARE VARIABLE TID INTEGER;
BEGIN
 SELECT ID TID
 FROM extstring
 WHERE (STR = :EXTSTR)
 INTO :TID;
 ID = TID;
 IF (TID IS NULL) THEN BEGIN
   TID = gen_id(GEN_EXTSTRING_ID, 1);
   INSERT INTO extstring(ID, STR)
   VALUES(:TID, :EXTSTR);
   ID = TID;
 END
-- INTO :ID;
END




Создание процедуры вроде как прокатило, но вот при попытке вызова:

Код: sql
1.
2.
INSERT INTO logs(id, grp, EVNT, usr, DTIME ,extint, OUTINT)
VALUES(gen_id(GEN_LOGS_ID, 1), 100, 100, 30, '13.11.2018 16:44:58', CHECK_ID_EXTSTR('новая_строка'), 0)




получаю ошибку:

SQL error code = -804.
Function unknown.
CHECK_ID_EXTSTR.

Бред какой-то... Может ее как то по другому вызывать нужно? Но gen_id прокатывает-то...?

Ну как-то вот так
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE PROCEDURE CHECK_ID_EXTSTR
    (EXTSTR VARCHAR(150))
RETURNS
    (ID INT)
AS  DECLARE VARIABLE TID INTEGER;
BEGIN
......
......
......
  suspend;
END



Код: sql
1.
2.
INSERT INTO logs(id, grp, EVNT, usr, DTIME ,extint, OUTINT)
select  gen_id(GEN_LOGS_ID, 1), 100, 100, 30, '13.11.2018 16:44:58', EXTSTR,0 from CHECK_ID_EXTSTR('новая_строка')


зы. в процедуру не вникал
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735001
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,

функция не должна менять данные, иначе её применение сильно ограничено. Как минимум это сразу отклоняет использование таких функций в SELECT запросах, ибо пути оптимизатора неисповедимы, а следовательно невозможно заранее предсказать сколько раз будет выполнена функция. А раз она вносит изменения в данные, то невозможно и предсказать какими будут данные.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735014
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMasterVlad F,

У него процедура вставкой еще занимается. В функцию лучше такого не засовывать - по сути ты вызываешь проверку, а вместо простой проверки у тебя еще в разных местах какие-то записи появляются. Неочевидно по прошествии некоторого времени.

Чего-чего? Название не нравится? Ну так переобозвать ее на что-то вроде ВставкаСПроверкой и пусть работает очевидным образом. Вы так дойдете до того, что и в ориггерах нельзя в другие таблицы вставлять "в разных местах" ведь тоже другие записи появляются.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735024
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,

не... ты не понял моего объяснения. Я не категорически против таких функций.
Но во-первых, как ты правильно заметил, функцию надо правильно назвать. Ибо по дурости её можно в какой нибудь SELECT запихнуть, например


Код: sql
1.
2.
3.
4.
5.
SELECT *
FROM T1
JOIN T2 ON T1.N = T2.N
WHERE CHECK_ID_EXTSTR(T1.A) = 1
  AND T1.A = 1 AND T2.B = 2



сколько раз выполнится CHECK_ID_EXTSTR?
Правильный ответ ХЗ. Зависит от количества записей в T1, T2 их распределения и плана который выберет оптимизатор.
Кстати к селективным ХП это тоже относится
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735025
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисVlad F,

функция не должна менять данные, иначе её применение сильно ограничено. Как минимум это сразу отклоняет использование таких функций в SELECT запросах, ибо пути оптимизатора неисповедимы, а следовательно невозможно заранее предсказать сколько раз будет выполнена функция. А раз она вносит изменения в данные, то невозможно и предсказать какими будут данные.
Я имел ввиду троечные функцию, которую можно бало бы топикастеру подставить в инсерт без паразитного селекта. Что выглядело бы как минимум более элегантно, и не думаю, что оптимизатор от этого потерял бы голову.))
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735028
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисVlad F,

не... ты не понял моего объяснения. Я не категорически против таких функций.
Но во-первых, как ты правильно заметил, функцию надо правильно назвать. Ибо по дурости её можно в какой нибудь SELECT запихнуть, например


Код: sql
1.
2.
3.
4.
5.
SELECT *
FROM T1
JOIN T2 ON T1.N = T2.N
WHERE CHECK_ID_EXTSTR(T1.A) = 1
  AND T1.A = 1 AND T2.B = 2



сколько раз выполнится CHECK_ID_EXTSTR?
Правильный ответ ХЗ. Зависит от количества записей в T1, T2 их распределения и плана который выберет оптимизатор.
Кстати к селективным ХП это тоже относится
Все, я сдаюсь, ибо тебя упорно сносит в сторону какого то селекта, от которого я и предлагал по возможности отказаться.))
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735030
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,

оптимизатор голову и не теряет. А вот логика в таком SELECT запросе крайне сомнительна.

Я же говорю как минимум функцию надо правильно назвать, чтобы спустя полгода не воткнуть её туда, где она натворит бед.

Да и INSERT тоже разный бывает. Сегодня вставляешь 1 запись, завтра нужно несколько вставить INSERT ... SELECT, послезавтра вообще MERGE потребуется. Где гарантия, что автора не возникнет соблазн перетащить свою функцию в новые запросы.

ИХМО, нужна сложная логика записи в лог. Ну так сделать хранимую процедуру которая делает и INSERT INTO LOGS и INSERT INTO extstring с проверками в одной процедуре. И сразу будет ясно что и где делается
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735047
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg,

добавлю
Код: sql
1.
2.
3.
4.
 SELECT ID TID
 FROM extstring
 WHERE (STR = :EXTSTR)
 INTO :TID;



задание алиаса TID (SELECT ID TID) абсолютно бессмысленно, потому что INTO запишет значение в переменную TID независимо от имени выбираемого столбца.

Кроме того, этот код выдаст NULL в TID в двух случаях
- когда есть запись с NULL в TID
- когда нет записи where str=:extstr

И, по логике программирования тут не процедура нужна, а триггер на таблицу LOG.
Insert с побочным insert в процедуре, да еще и через select - это жуть какая-то, а не код.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735051
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvзадание алиаса TID (SELECT ID TID) абсолютно бессмысленно, потому что INTO запишет значение в переменную TID независимо от имени выбираемого столбца.

в простейшем запросе автора да. Однако если запрос сложный с использованием JOIN или выражений в SELECT, я всё равно задаю алиасы, просто потому что так удобно отлаживать отдельно взятый запрос, у которого тупо отпилен INTO
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735058
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

я сам пишу алиасы. Просто по тексту возникло впечатление, что автор думает, что имя алиаса столбца должно совпадать с именем переменной для into.
...
Рейтинг: 0 / 0
Создание/использование хранимых процедур
    #39735069
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdvКроме того, этот код выдаст NULL в TID в двух случаях
...
- когда нет записи where str=:extstrНе буквоедства ради, но... в этом случае значение :TID не изменится.
А это совсем не то же самое, что присваивание NULL.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Создание/использование хранимых процедур
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]