powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
9 сообщений из 9, страница 1 из 1
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118818
vladgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток!

Есть специфическая задача завязанная на хранение данных, так как они находятся в памяти аппаратуры.
В связи с этим есть таблица текстов
для простоты
Код: plsql
1.
2.
TblText 
(ID, text)


В этой таблице могут находиться помимо просто текстов и тексты следующего вида
Код: pascal
1.
'какой-то текст @23 снова текст @25 текст и т.д'


где @23 и @25 - это ссылки на ID=23 и 25 в этой же таблице.
Т.е. одна запись в таблице ссылается на другие записи в этой же таблице.
Код: plaintext
(Сразу отвечу для чего это сделано -  чтобы сильно экономить память аппаратуры на текстах, т.к. много одинаковых составляющих)

Задача проверять неиспользуемые элементы и удалять их.
Решил попробовать сделать это на стороне БД через ХП. (опыт в ХП практически 0)
Сделал ХП, которая распарсивает входную строку и возвращает набор значений ссылок на ID, найденных в переданной строке.
Например,
Код: plsql
1.
 Select out_ID from MyParse('текст@5 текст текст@17 текст текст текст@2текст@7текст)'


вернет
Код: plsql
1.
2.
3.
4.
5.
out_id
5
17
2
7



На этом шаге я застрял.
Не пойму что нужно сделать, чтобы просмотреть таблицу текстов и отобразить те записи, на которые нет ссылок в полученном списке по ID.
Запрос вида
Код: plsql
1.
2.
3.
select A.ID, A.Text from TblText A
where
 ([not] exists (select OUT_ID from MyParse(A.Text) where A.ID=OUT_ID))


выдает все записи/ либо ни одной записи в зависимости от "not"
думаю что-то упускаю, но не пойму где.

Также пробовал делать так
Код: plsql
1.
2.
3.
select A.ID, A.Text from Tbltext A
where
 (A.ID in ((select OUT_ID from MyParse(A.Text))))



Насколько я понимаю:
внутренняя часть
Код: plsql
1.
select OUT_ID from MyParse(A.Text)


вернет мне набор ID, ссылки на которые найдет MyParse
Далее, как я понимаю, должна сравнить A.ID текущей записи таблицы TblText с полученным списком.
Конечно, поскольку текущая запись сама на себя не ссылается, то я и получаю пустую выборку.

Как мне построить запрос, чтобы сравнить не с текущей записью полученный список, а снова со всей таблицей?
и вывести только те записи, для которых будут найдены ссылки. Через distinct оставим только уникальные значения.
Код: plaintext
(понятно, что будет медленно, но максимально общее количество записей около 10000, а по факту вообще около 3000)
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118823
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vladgulЗадача проверять неиспользуемые элементы и удалять их.

То есть удалить из таблицы записи с ID, который не встречается в конструкциях
"@XX" любых других записей?

vladgul
максимально общее количество записей около 10000, а по факту вообще около 3000

База - тоже в памяти "аппаратуры", что вы и из неё выжимаете байты?
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118860
vladgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторТо есть удалить из таблицы записи с ID, который не встречается в конструкциях
"@XX" любых других записей?
Верно

авторБаза - тоже в памяти "аппаратуры", что вы и из неё выжимаете байты?
Да. И как показала практика такая забота об использовании памяти позволила уже не один раз легко добавлять новые свойства и разделы без существенной переделки схемотехники.

Я могу решить эту задачу непосредственно в программе, но хочется немного больше разобраться с ХП и подобными действиями на стороне сервера.
Сейчас вопрос именно в этом

Как мне построить запрос, чтобы сравнить не с текущей записью полученный список, а снова со всей таблицей?

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

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t as (
  select
    distinct 
    p.OUT_ID 
  from Tbltext A
  left join MyParse(A.Text) p on 1=1
)
select A.ID, A.Text 
from TblText A
where not exists(select * from t where t.OUT_ID  = a.ID)



но это будет работать ооочень медленно. Рекомендую завести gtt tmp и сначала вставить найденные записи в неё

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
execute block
as
begin
  -- delete from tmp;

  insert into tmp(OUT_ID)
  select
    distinct 
    p.OUT_ID 
  from Tbltext A
  left join MyParse(A.Text) p on 1=1;

  delete from TblText A
  where not exists(select * from tmp where tmp.OUT_ID  = a.ID);
end
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118887
vladgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис
vladgul,

with t as (
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
 with t as (
  select
    distinct 
    p.OUT_ID 
  from Tbltext A
  left join MyParse(A.Text) p on 1=1
)
select A.ID, A.Text 
from TblText A
where not exists(select * from t where t.OUT_ID  = a.ID)




Работает неправильно.
часть в with всегда возвращает null.
А если заменить left join на right join, то вообще выдает ошибку

The cursor identified in the UPDATE or DELETE statement is not positioned on a row.
no current record for fetch operation


Я так понимаю, что с моей ХП что-то не так.
собственно текст ХП, которая ищет ссылки в переданной строке.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
create or alter procedure PARSETEXTLINKS (
    IN_TEXT varchar(300))
returns (
    OUT_ID integer)
AS
declare variable POS2 integer;
declare variable POS1 integer;
declare variable STR1 varchar(300);
declare variable SS varchar(300);
begin
  /* Procedure Text */
  SS = :IN_TEXT;
  while ((:SS <> '')) do
  begin
    POS1 = position(ascii_char(12) in :SS) + 1;
    if (POS1 > 1) then
    begin
      SS = substring(:SS from :POS1 for char_length(:SS));/* Исключаем все символы до найденного */
      POS2 = position(ascii_char(32) in :SS);/* Ищем окончание ссылки по пробелу */
      if (:POS2 = 0) then /* Если не нашли, то до конца строки */
        POS2 = char_length(SS);
      STR1 = substring(:SS from 1 for :POS2); /* Копируем найденную часть в отдельную строку */
      OUT_ID = cast(:STR1 as integer);/* Преобразуем к числу*/
      suspend;
      /* Получаем оставшуюся часть строки и проверяем вхождение по новой */
      SS = substring(:SS from :POS2 + 1 for char_length(:SS));/* Убираем обработанную часть */
    end
    else
      break; /* Если вхождений нет, то выход */
  end
end



Думаю не поставил какую-то директиву связанную с курсором.

Как правильно нужно было бы сделать?
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118888
vladgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис
vladgul,
но это будет работать ооочень медленно. Рекомендую завести gtt tmp и сначала вставить найденные записи в неё


Попробовал также пойти другим путем.
и создать еще одну ХП, которая вернет список всех найденных значений ID, для всех записей в таблице TblText
а уже потом использовать ее результаты.
но здесь вообще не получилось
Подскажите в чем ошибка
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
create or alter procedure ALLTEXTLINKS ()
returns (
    OUT_ID integer  )
as
declare variable ID1 integer;
declare variable ID2 integer;
declare variable NAME1 varchar(300);
begin
  /* Procedure Text */
  for select Text
      from TblText
      into :Text1
  do
  begin
    for select OUT_ID from PARSETEXTLINKS(:Text1)
    into :ID2
    do
    begin
     OUT_ID=:ID2;
     Suspend;
    end
  end
end
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118941
H.e.l.p
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Список ИД для удаления (при условии, что TBLTEXT.TEXT not null) можно определить так

Код: sql
1.
2.
3.
4.
5.
select P.OUT_ID
from TBLTEXT A
left join MYPARSE(A.TEXT || '@' || A.ID) P on 1 = 1
group by 1
having count('x') < 2



Далее сам.
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40118945
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vladgulВерно

Тогда тупо переводим на англицкий:
Код: sql
1.
2.
3.
delete from TblText t1 where not exists
   (select * from TblText t2
     where t2.text similar to '%@'||t1.id||'[^[:DIGIT:]]%')



vladgulДа.
Вы реально сэкономите намного, намного больше места если замените эту базу
простым текстовым файлом.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
    #40119027
vladgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

Тогда тупо переводим на англицкий:
Код: sql
1.
2.
3.
delete from TblText t1 where not exists
   (select * from TblText t2
     where t2.text similar to '%@'||t1.id||'[^[:DIGIT:]]%')




Вот это прям то что надо. БОЛЬШОЕ спасибо.
Про такую возможность даже не знал.

Dimitry Sibiryakov

Вы реально сэкономите намного, намного больше места если замените эту базу
простым текстовым файлом.

Может я раньше не совсем верно указал. Сама база не хранится в аппаратуре (в виде файла).
Просто для удобства разработки, отладки, оперирования данными и для того, чтобы не усложнять степень разработки стараемся делать максимально "похожие" данные на компе и в аппаратуре. Тем более, что тексты это всего ли 1/52 часть от БД. А СУБД очень помогает, при оперировании этими данными. А в аппаратуру "заливается" 95%.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Помогите понять как нужно поступить с хранимой процедурой или множественный выбор ...
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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