Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Правильная передача перечисления для Firebird


Автор: Matrex 7.10.2016, 10:34
Доброго дня коллеги!

Есть функция для удаления строк из БД Firebird 2.5 по идентификатору:

Код

function DEL(const ID: string; IBT: TIBTransaction): Integer;
begin
  fIBS_D := TIBSQL.Create(nil);
  fIBS_D.Transaction := IBT;
  fIBS_D.Database := IBT.DefaultDatabase;
  fIBS_D.SQL.ADD('DELETE FROM SR_USER WHERE id in (:id)');
  fIBS_D.Prepare;
  fIBS_D.ParamByName('id').Value := ID;
  fIBS_D.ExecQuery;
  result := 0;
end;


Если удалять по одной записи:
DEL('10'; fIBT) – все работает

Если удалять серию записей через перечисление:
DEL('10,11,12,13'; fIBT)– функция не работает – просто записи не удаляются.

Я так понимаю необходимо правильно передавать перечисление в качестве параметра – вопрос как это сделать?


Автор: Matrex 7.10.2016, 11:52
Похоже что никак. См
http://www.ibase.ru/ibfaq/#inparam

Автор: Alexeis 7.10.2016, 12:17
Не встречался с такой задачей. Обычно групповое удаление идет каскадно. Т.е. удаление группы записей объединенных общим ключом. Удаляешь мастер запись и каскадно труртся все зависимости. Если стоит вопрос производительности, то можно попробовать написать хранимую процедуру.

Автор: Matrex 7.10.2016, 15:44
Дело не в каскадном удалении. Задача стоит следующая: пользователь в гриде выделяет несколько записей и удаляет их одновременно...

Автор: mixxxa 8.10.2016, 16:13
А так пробовали?
Код

function DEL(const ID: string; IBT: TIBTransaction): Integer;
begin
  fIBS_D := TIBSQL.Create(nil);
  fIBS_D.Transaction := IBT;
  fIBS_D.Database := IBT.DefaultDatabase;
  fIBS_D.SQL.ADD('DELETE FROM SR_USER WHERE id in ('+ID+')');
  fIBS_D.Prepare;
  fIBS_D.ExecQuery;
  result := 0;
end;


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57f8f0e386c4c572484794c6_0

Автор: mixxxa 8.10.2016, 16:13
А так пробовали?
Код

function DEL(const ID: string; IBT: TIBTransaction): Integer;
begin
  fIBS_D := TIBSQL.Create(nil);
  fIBS_D.Transaction := IBT;
  fIBS_D.Database := IBT.DefaultDatabase;
  fIBS_D.SQL.ADD('DELETE FROM SR_USER WHERE id in ('+ID+')');
  fIBS_D.Prepare;
  fIBS_D.ExecQuery;
  result := 0;
end;


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57f8f0e386c4c572484794c6_0

Автор: mixxxa 8.10.2016, 16:13
А так пробовали?
Код

function DEL(const ID: string; IBT: TIBTransaction): Integer;
begin
  fIBS_D := TIBSQL.Create(nil);
  fIBS_D.Transaction := IBT;
  fIBS_D.Database := IBT.DefaultDatabase;
  fIBS_D.SQL.ADD('DELETE FROM SR_USER WHERE id in ('+ID+')');
  fIBS_D.Prepare;
  fIBS_D.ExecQuery;
  result := 0;
end;


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57f8f0e386c4c572484794c6_0

Автор: mixxxa 8.10.2016, 16:13
А так пробовали?
Код

function DEL(const ID: string; IBT: TIBTransaction): Integer;
begin
  fIBS_D := TIBSQL.Create(nil);
  fIBS_D.Transaction := IBT;
  fIBS_D.Database := IBT.DefaultDatabase;
  fIBS_D.SQL.ADD('DELETE FROM SR_USER WHERE id in ('+ID+')');
  fIBS_D.Prepare;
  fIBS_D.ExecQuery;
  result := 0;
end;


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57f8f0e386c4c572484794c6_0

Автор: mixxxa 8.10.2016, 16:13
А так пробовали?
Код

function DEL(const ID: string; IBT: TIBTransaction): Integer;
begin
  fIBS_D := TIBSQL.Create(nil);
  fIBS_D.Transaction := IBT;
  fIBS_D.Database := IBT.DefaultDatabase;
  fIBS_D.SQL.ADD('DELETE FROM SR_USER WHERE id in ('+ID+')');
  fIBS_D.Prepare;
  fIBS_D.ExecQuery;
  result := 0;
end;


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57f8f0e386c4c572484794c6_0

Автор: Akella 10.10.2016, 08:51
Передавать нужно в скобках + закавычить, т.к. это же текстовый параметр.
И сделайте лучше без параметра, сразу сгенерируйте запрос.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2c6086c4c53f9f3ee439_0

Автор: Akella 10.10.2016, 08:51
Передавать нужно в скобках + закавычить, т.к. это же текстовый параметр.
И сделайте лучше без параметра, сразу сгенерируйте запрос.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2c6086c4c53f9f3ee439_0

Автор: Akella 10.10.2016, 08:51
Передавать нужно в скобках + закавычить, т.к. это же текстовый параметр.
И сделайте лучше без параметра, сразу сгенерируйте запрос.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2c6086c4c53f9f3ee439_0

Автор: Akella 10.10.2016, 08:51
Передавать нужно в скобках + закавычить, т.к. это же текстовый параметр.
И сделайте лучше без параметра, сразу сгенерируйте запрос.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2c6086c4c53f9f3ee439_0

Автор: Akella 10.10.2016, 08:51
Передавать нужно в скобках + закавычить, т.к. это же текстовый параметр.
И сделайте лучше без параметра, сразу сгенерируйте запрос.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2c6086c4c53f9f3ee439_0

Автор: Akella 10.10.2016, 09:04
Ещё можно создать процедуру UNLIST

Код

SET TERM ^ ;

create or alter procedure UNLIST (
    STRING varchar(2048),
    SEPARATOR varchar(1))
returns (
    ROW varchar(20))
as
begin
  Separator = coalesce(Separator, ';');
  if (Separator = '') then Separator = ';';
  Row = '';

  while (String != '') do
  begin
    if (substring(String from 1 for 1) != Separator) then
      Row = Row || substring(String from 1 for 1);
    else
    begin
      if (Row != '') then suspend;
      Row = '';
    end
    String = substring(String from 2);

  end
  if (Row != '') then suspend;
end^

SET TERM ; ^


использовать потом так:

Код

SELECT P.TEL, P.ID FROM PHONES P
INNER JOIN UNLIST(:ID, ',') UL ON P.ID = UL.ROW


в ID передаём текст в виде чисел через запятую

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2f6986c4c540115ef9a3_0

Автор: Akella 10.10.2016, 09:04
Ещё можно создать процедуру UNLIST

Код

SET TERM ^ ;

create or alter procedure UNLIST (
    STRING varchar(2048),
    SEPARATOR varchar(1))
returns (
    ROW varchar(20))
as
begin
  Separator = coalesce(Separator, ';');
  if (Separator = '') then Separator = ';';
  Row = '';

  while (String != '') do
  begin
    if (substring(String from 1 for 1) != Separator) then
      Row = Row || substring(String from 1 for 1);
    else
    begin
      if (Row != '') then suspend;
      Row = '';
    end
    String = substring(String from 2);

  end
  if (Row != '') then suspend;
end^

SET TERM ; ^


использовать потом так:

Код

SELECT P.TEL, P.ID FROM PHONES P
INNER JOIN UNLIST(:ID, ',') UL ON P.ID = UL.ROW


в ID передаём текст в виде чисел через запятую

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2f6986c4c540115ef9a3_0

Автор: Akella 10.10.2016, 09:04
Ещё можно создать процедуру UNLIST

Код

SET TERM ^ ;

create or alter procedure UNLIST (
    STRING varchar(2048),
    SEPARATOR varchar(1))
returns (
    ROW varchar(20))
as
begin
  Separator = coalesce(Separator, ';');
  if (Separator = '') then Separator = ';';
  Row = '';

  while (String != '') do
  begin
    if (substring(String from 1 for 1) != Separator) then
      Row = Row || substring(String from 1 for 1);
    else
    begin
      if (Row != '') then suspend;
      Row = '';
    end
    String = substring(String from 2);

  end
  if (Row != '') then suspend;
end^

SET TERM ; ^


использовать потом так:

Код

SELECT P.TEL, P.ID FROM PHONES P
INNER JOIN UNLIST(:ID, ',') UL ON P.ID = UL.ROW


в ID передаём текст в виде чисел через запятую

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2f6986c4c540115ef9a3_0

Автор: Akella 10.10.2016, 09:04
Ещё можно создать процедуру UNLIST

Код

SET TERM ^ ;

create or alter procedure UNLIST (
    STRING varchar(2048),
    SEPARATOR varchar(1))
returns (
    ROW varchar(20))
as
begin
  Separator = coalesce(Separator, ';');
  if (Separator = '') then Separator = ';';
  Row = '';

  while (String != '') do
  begin
    if (substring(String from 1 for 1) != Separator) then
      Row = Row || substring(String from 1 for 1);
    else
    begin
      if (Row != '') then suspend;
      Row = '';
    end
    String = substring(String from 2);

  end
  if (Row != '') then suspend;
end^

SET TERM ; ^


использовать потом так:

Код

SELECT P.TEL, P.ID FROM PHONES P
INNER JOIN UNLIST(:ID, ',') UL ON P.ID = UL.ROW


в ID передаём текст в виде чисел через запятую

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2f6986c4c540115ef9a3_0

Автор: Akella 10.10.2016, 09:04
Ещё можно создать процедуру UNLIST

Код

SET TERM ^ ;

create or alter procedure UNLIST (
    STRING varchar(2048),
    SEPARATOR varchar(1))
returns (
    ROW varchar(20))
as
begin
  Separator = coalesce(Separator, ';');
  if (Separator = '') then Separator = ';';
  Row = '';

  while (String != '') do
  begin
    if (substring(String from 1 for 1) != Separator) then
      Row = Row || substring(String from 1 for 1);
    else
    begin
      if (Row != '') then suspend;
      Row = '';
    end
    String = substring(String from 2);

  end
  if (Row != '') then suspend;
end^

SET TERM ; ^


использовать потом так:

Код

SELECT P.TEL, P.ID FROM PHONES P
INNER JOIN UNLIST(:ID, ',') UL ON P.ID = UL.ROW


в ID передаём текст в виде чисел через запятую

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_57fb2f6986c4c540115ef9a3_0

Автор: G.Alexander 25.10.2016, 08:42
Спасибо за совет. Пока сделал именно так. Но по словам нашего админа это не "тру вэй" т.к. подобная конструкция для некоторых БД, например Oracle (проект разрабатывается для нескольких БД, по этой же причине использование встроенных процедур сведено к минимуму) заставляет механизм построения плана выполнения запроса сервера БД постоянно парсить данный запрос...

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_580ef0ba35218830607e0958_0

Автор: G.Alexander 25.10.2016, 08:42
Спасибо за совет. Пока сделал именно так. Но по словам нашего админа это не "тру вэй" т.к. подобная конструкция для некоторых БД, например Oracle (проект разрабатывается для нескольких БД, по этой же причине использование встроенных процедур сведено к минимуму) заставляет механизм построения плана выполнения запроса сервера БД постоянно парсить данный запрос...

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_580ef0ba35218830607e0958_0

Автор: G.Alexander 25.10.2016, 08:42
Спасибо за совет. Пока сделал именно так. Но по словам нашего админа это не "тру вэй" т.к. подобная конструкция для некоторых БД, например Oracle (проект разрабатывается для нескольких БД, по этой же причине использование встроенных процедур сведено к минимуму) заставляет механизм построения плана выполнения запроса сервера БД постоянно парсить данный запрос...

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_580ef0ba35218830607e0958_0

Автор: G.Alexander 25.10.2016, 08:42
Спасибо за совет. Пока сделал именно так. Но по словам нашего админа это не "тру вэй" т.к. подобная конструкция для некоторых БД, например Oracle (проект разрабатывается для нескольких БД, по этой же причине использование встроенных процедур сведено к минимуму) заставляет механизм построения плана выполнения запроса сервера БД постоянно парсить данный запрос...

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Pravilnaya-peredacha-perechisleniya-dlya-Firebird-id57f75064adbd5f389a06bfb2#findElement_E7045_580ef0ba35218830607e0958_0

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)