Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.07.2011, 18:43   #1
delphicoding
Заблокирован
 
Регистрация: 04.07.2011
Сообщений: 261
Восклицание Странные баги в FB

Здравствуйте!

Возникло не сколько странных проблем с СУБД/БД никак не могу решить, может сможете что-то подсказать... IBExpert + FB2.5

1. Не воспринимает CASE, ругается на строке (!) Parsing error! Пробовал в конце каждой строки when ставить ";" без разницы. Переделал на IF всё сразу заработало.
Код:
begin
 case TYPE
  when 1 then a_shift=:shift (!)
  when 2 then b_shift=:shift
  when 3 then c_shift=:shift
 end
end
2. Из программы посылается запрос в БД ввиде списка через запятую номеров строк нужной таблицы (проверено список правильный, перед отправкой отображается в программе в тестовом поле), список разбивается в БД спец процедурой (процедура проверена вручную - список разбивается на таблицу):
Код:
create or alter procedure LIST_TO_VALUES (
    LST blob sub_type 1 segment size 80)
returns (
    ID varchar(100))
as
declare variable I integer = 1;
declare variable J integer = 1;
begin
  while (i <= char_length(lst)) do begin
    if (substring(lst from i for 1) = ',') then begin
      if (i > j) then
          id = trim(leading from substring(lst from j for i - j));
      else
        id = null;
      if (id is not null) then   suspend;
      j = i+1;
    end
    i = i+1;
  end
 
  if (i > j) then
      id = trim(leading from substring(lst from j for i - j));
  else
    id = null;
 
  if (id is not null) then   suspend;
end
Список обрабатывается двумя хранимыми процедурами в БД:
А. Первая совершает определённое действие над всем списком, корректировка данных в БД для строк из списка. Увы, почему-то обрабатывает только последний (!) номер из списка. Содержит конструкцию:
Код:
for
  select id from list_to_values (:list_value) into :id
  do < далее код обработки >
Б. Вторая процедура должна возвращать таблицу данных собранных из нескольких таблиц на основе номеров из списка. Увы, возвращает пустую таблицу только с названиями полей, но данных нет!
Код:
create or alter procedure RPR_OFFICES (
    LIST_ID NOTE_BLOB)
returns (
    "Компания" NAME,
    "Офис" NAME,
    "ОфисНомер" NUM)
as
begin
 for
 select
 c.company_name, o.name, o.number
 
 from
  list_to_values(:list_id) l
  left join offices o on l.id = o.office_id
  left join companies c on o.company_id=c.company_id
 
 order by 1,2,3
 into :"Компания", :"Офис", :"ОфисНомер"
 do begin
  suspend;
 end
end
Ковыряюсь над этими проблемами уже два дня не могу понять что неправильно... ?! Может СУБД работает в режиме старой версии типа FB1.0? Как это проверить в IBExpert???
delphicoding вне форума Ответить с цитированием
Старый 31.07.2011, 13:06   #2
delphicoding
Заблокирован
 
Регистрация: 04.07.2011
Сообщений: 261
По умолчанию

Профи, помогайте, сам пока разобраться не могу - не хватает опыта с SQL...

Проверил в БД все входящие данные, всё передано из программы верно.
Код:
   insert into "_TEST_TEMP" (TEXT) VALUES (:list_value); (1)
for
  select id from list_to_values (:list_value) into :id
  do
   insert into "_TEST_TEMP" (TEXT) VALUES (:id); (2)
    if (:status_id=5) then
      update Offices set OFFICE_STATUS_ID=5
      where OFFICE_ID=:ID;
    if (:status_id=3 or :status_id=4) then
      update Offices set OFFICE_STATUS_ID=3
      where OFFICE_ID=:ID;
Положим передаём список из 3х номеров "100,101,102"...
Главная процедура п.2.А получила весь список "100,101,102" (1), процедура разбиения списка п.2 разбила список и вернула таблицу (проверено вручную запросом и проверкой результата), после чего процедура п.2.А отработала (2) - согласно проверочной записе вставленной после слова "do" - 3 раза, тк при каждом цикле в тестовую таблицу добавлялись номера "100","101","102"... но в реальности данные изменились только у последней записи номер "102"!

Впечатление, что у конструкции функция корректировки записей работает после ВСЕХ циклов, а не в каждом цикле...

Или же наоборот - начинается цикл с конца списка и сразу после обработки первой в исполнении записи (последней в списке - "102") цикл работает вхолостую не корректируя нужные записи...

Подскажите что нужно скорректировать для этого...

Последний раз редактировалось delphicoding; 31.07.2011 в 13:20.
delphicoding вне форума Ответить с цитированием
Старый 31.07.2011, 14:32   #3
delphicoding
Заблокирован
 
Регистрация: 04.07.2011
Сообщений: 261
По умолчанию

=== вопрос 1 решён только с использованием IF, CASE не принимает ни в каком виде! странно.
=== вопрос 2.А решён добавлением else в каждую строку.

По поводу вопроса 2.Б тоже нашёл где проблема - с процедурой в БД написанной в первом постинге всё в порядке, список просто не доходит до процедуры. Проблема в конструкции:
Код:
spDS1: TpFIBDataSet;
With spDS1 do begin
    close;
    Prepare;
    InsertSQL.Text:='insert into "_TEST_TEMP" (TEXT_BLOB, TEXT) VALUES (:list_id, 10)';
    Params[0].Value:=pList; (проверено, что pList содержит список)
    open;
end;
Процедура якобы выполняется, но ничего не происходит, возможно запрос просто не передаётся... что неправильно???

Последний раз редактировалось delphicoding; 31.07.2011 в 16:13.
delphicoding вне форума Ответить с цитированием
Старый 31.07.2011, 16:48   #4
delphicoding
Заблокирован
 
Регистрация: 04.07.2011
Сообщений: 261
По умолчанию

Решён вопрос 2.Б!
Заработала такая конструкия:
Цитата:
With spDS1 do begin
Prepare;
spDS1.Params[0].Value:=pList;
Open;
=============================

Осталось лишь непонятно почему IBExpert+FB2.5 никак не хочет пропускать CASE ???
delphicoding вне форума Ответить с цитированием
Старый 31.07.2011, 21:01   #5
Прик
Форумчанин
 
Регистрация: 08.09.2010
Сообщений: 880
По умолчанию

Цитата:
Сообщение от delphicoding Посмотреть сообщение
Осталось лишь непонятно почему IBExpert+FB2.5 никак не хочет пропускать CASE ???
Цитата из учебника по SQL FB:
Цитата:
Операция выбора CASE
Операция выбора CASE позволяет определить результат в столбце ТРЗ,
исходя из определенных условий. Имеются две формы операции CASE:
простая и с поиском. Простая форма имеет следующий синтаксис:
CASE <выражение> {WHEN <значение1> THEN результат1}
[{WHEN <значение2> THEN результат2}] ...
[ ELSE результат(N+1)]
END.
В этой форме последовательно сравниваются значения при фразах WHEN со
значением заданного выражения. При первом же совпадении возвращается
значение при соответствующей фразе THEN. Если совпадений нет, то
возвращается результат(N+1) при фразе ELSE.
Синтаксис операции CASE с поиском имеет следующий вид:
CASE {WHEN <условие_поиска1> THEN результат1}
[{ WHEN <условие_поиска2> THEN результат2}]...
[ ELSE результат(N+1) ]
END.
В этом случае последовательно проверяются все условия при фразах WHEN.
Если условие истинно, то возвращается результат соответствующей фразы
THEN. Если ни одно условие при фразах WHEN ни оказалось истинным,
возвращается результат(N+1) при фразе ELSE.
В обоих вариантах в качестве результата после фраз THEN или ELSE может быть задано либо выражение (которое может включать константы, имена столбцов, функции, а также арифметические операции и операцию конкатенации), либо NULL-значение.
Где здесь написано, что в качестве результата может быть оперция присвоения?
Прик вне форума Ответить с цитированием
Старый 31.07.2011, 23:40   #6
delphicoding
Заблокирован
 
Регистрация: 04.07.2011
Сообщений: 261
По умолчанию

А что не может? Какая по-сути разница какое действие производить-то?!
То есть в таком случае писать можно только через конструкцию?:
Код:
IF TYPE=1 THEN a_shift=:shift; else
IF TYPE=2 THEN b_shift=:shift; else
IF TYPE=3 THEN c_shift=:shift;

Последний раз редактировалось delphicoding; 31.07.2011 в 23:46.
delphicoding вне форума Ответить с цитированием
Старый 01.08.2011, 09:01   #7
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
А что не может? Какая по-сути разница какое действие производить-то?!
Оператор CASE предназначен для возврата значений в зависимости от условий).
Точка!
Использовать его так, как Вы хотите (исходя из того, что его имя совпадает с оператором выбора в других ЯП) - НЕЛЬЗЯ!


Цитата:
То есть в таком случае писать можно только через конструкцию?:
ну а почему нет.. имхо, вполне можно. не вижу ничего страшного
(ну кроме того, что вы в зависимости от типа создаёте кучу дополнительнх переменных.... А если TYPE будет принимать 100 значений? А если тысячу? я бы посмотрел над изменением алгоритма и/или использования вместо a_shift b_shift и т.д. массивов... Ну, тут Вам, как разработчику, виднее, как нужно, как лучше, как удобнее, универсальнее и т.д. и т.п.)
Serge_Bliznykov вне форума Ответить с цитированием
Старый 01.08.2011, 13:53   #8
delphicoding
Заблокирован
 
Регистрация: 04.07.2011
Сообщений: 261
По умолчанию

Цитата:
Оператор CASE предназначен для возврата значений в зависимости от условий).
Логики в этом нет, вполне можно было разрешить использовать присвоение. даже более того, именно оператор CASE оптимально подходит для присвоения того же значения, что и сравниваемое! Например мы пишем:
Код:
for ... begin
if a=1 then a=3 --
if a=2 then a=4
if a=3 then a=5 --
end
и таким образом создаётся ошибка повторного присвоения!

CASE же как раз должен работать иначе - выходить из цикла при нахождении искомого A=1 и таким образом повторное присвоение становится невозможным.
Код:
for ... begin CASE A
when 1 then a=3 --> end
when 2 then a=4
when 3 then a=5
end
Глупо, то CASE так нельзя использовать, тк именно для этого он подходил бы лучше всех остальных!
delphicoding вне форума Ответить с цитированием
Старый 01.08.2011, 14:27   #9
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Логики в этом нет, вполне можно было разрешить использовать присвоение.
ещё раз.
CASE в SQL запросах ВОЗВРАЩАЕТ значение!

Возвращает. и всё. Никаких операций по изменению данных он не производит И НЕ ДОЛЖЕН производить!

Не пойму, что здесь непонятного?!

p.s. для вашего примера может пройти так:
Код:
for ... begin
a := CASE A 
  when 1 then 3
  when 2 then 4
  when 3 then 5 end;
end
если только, конечно, FB поймёт такой синтаксис...

Последний раз редактировалось Serge_Bliznykov; 01.08.2011 в 14:31.
Serge_Bliznykov вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
странные таблички Пепел Феникса Свободное общение 5 22.09.2010 14:13
странные проблемы с с++ Plastilin Общие вопросы C/C++ 9 21.02.2010 03:50
Странные ошибки. Rio309 Общие вопросы Delphi 2 19.10.2009 19:22
Странные задачи L_M Свободное общение 60 19.05.2009 08:54