powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Стринги против массивов, или я достану всех. =)
11 сообщений из 11, страница 1 из 1
Стринги против массивов, или я достану всех. =)
    #36012820
Саабразим Аль-каши Бухани
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нужен совет. Ситуация такая. Есть запрос на удаление нескольких (количестко не постоянное) строк по ID, допустим

Код: plaintext
delete from table1 where id in( 1 , 2 , 3 , 4 , 5 )

Список ID формируется на клиенте. Но как-то душа не лежит формировать на клиенте полностью весь запрос типа
Javastring ids = "1,2,3,4,5";
//[.....]
ResultSet rs = s.executeQuery("delete from table1 where id in(" + ids + ")");

Хочется сделать это в виде некой серверной сущности (типа вью или ХП) с разделением прав, SQL-дезинъекцией и т.д. которой просто передавать список ID.
Путем долгих мучений коллег тут и тут выяснилось, что чтобы передать массив из кода Java нужны танцы с бубнами:
1. реализовать java.sql.Array (готовой реализации я не нашел)
2. пользовать connection.createArrayOf() (подозреваю, хотя не вникал, что он не творит чудеса а ищит в драйвере реализацию (которую, повторюсь, я не нашел) или что-то типа того)
или же
3. пересмотреть архитектуру.

Вот третий вариант мне кажется наиболее правильным по таким соображениям
1. Все сложное от лукавого
2. На данный момент СУБД - Postgres. ТЕОРЕТИЧЕСКИ она может поменяться, поэтому хочется найти как можно более общее решение.

Сейчас единственный рабочий вариант это сделать что-то на подобии
victor_krcreate function delsmth(ids character varying) returns void as
$body$
begin
execute 'delete from table1 where id in(' + ids + ')';
end;
$body$
LANGUAGE 'plpgsql' VOLATILE;
и передавать туда стринг с id через запятую.

Есть также мысль сделать 2 хранимки: одна сохраняет в БД ID для удаления, другая удаляет, но мне кажется что есть более кошерный варианты чем вызывать ХП N+1 раз.

Какие еще варианты? Буду рад любым идеям.
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36012859
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант со стрингами выглядит... более привлекательно, имхо ))))
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36012894
Саабразим Аль-каши Бухани
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для "паритета" приведу второй вариант:

Код: plaintext
1.
2.
3.
4.
create function delsmth(ids integer[]) returns void as
begin
  delete from table1 where id = ANY(ids);
end;
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36012900
Саабразим Аль-каши БуханиНужен совет. Ситуация такая. Есть запрос на удаление нескольких (количестко не постоянное) строк по ID, допустим

Код: plaintext
delete from table1 where id in( 1 , 2 , 3 , 4 , 5 )

Список ID формируется на клиенте. Но как-то душа не лежит формировать на клиенте полностью весь запрос типа
Javastring ids = "1,2,3,4,5";
//[.....]
ResultSet rs = s.executeQuery("delete from table1 where id in(" + ids + ")");

...
Сейчас единственный рабочий вариант это сделать что-то на подобии
victor_krcreate function delsmth(ids character varying) returns void as
$body$
begin
execute 'delete from table1 where id in(' + ids + ')';
end;
$body$
LANGUAGE 'plpgsql' VOLATILE;
и передавать туда стринг с id через запятую.

Есть также мысль сделать 2 хранимки: одна сохраняет в БД ID для удаления, другая удаляет, но мне кажется что есть более кошерный варианты чем вызывать ХП N+1 раз.

Какие еще варианты? Буду рад любым идеям.
и
egorychвариант со стрингами выглядит... более привлекательно, имхо ))))

Только это... Не надо забывать, что длина у стринга тоже ограничена... У Оракула, вроде бы максимальная длина строки, передаваемой "извне" равна 8Кб (между ХП что-то около 30 Кб)... Если уложитесь, то без проблем...
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36013075
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Станислав С...кийУ Оракула, вроде бы максимальная длина строки, передаваемой "извне" равна 8КбЕсли вы про тип VARCHAR2, то 4000 байт.

я бы еще предложил вариант с циклом и параметрами (т.е. удалять по одной записи, id передавать параметром), но это не всегда оптимально.
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36013086
Саабразим Аль-каши Бухани
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft
я бы еще предложил вариант с циклом и параметрами (т.е. удалять по одной записи, id передавать параметром), но это не всегда оптимально.

Не очень понял. Можно подробнее?
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36013111
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Саабразим Аль-каши Буханиmiksoft
я бы еще предложил вариант с циклом и параметрами (т.е. удалять по одной записи, id передавать параметром), но это не всегда оптимально.Не очень понял. Можно подробнее?примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
OracleQuery1->SQL->Text="DELETE FROM mytable WHERE ID=:ID";
OracleQuery1->DeclareVariable("ID",otString);
for(int i= 0 ;i<StringList1->Count;i++)
{
  OracleQuery1->SetVariable("ID",StringList1->Strings[i]);
  OracleQuery1->Execute;
}
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36013163
Фотография Роман Дынник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Массивы и списки в SQL Server
Статья по MSSQL, но идеи общие, разберетесь.
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36013440
_мод
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Саабразим Аль-каши БуханиКакие еще варианты? Буду рад любым идеям.
Загнать список во временную таблицу - длина списка не ограничена
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36013921
Если Вас смущает SQL-injection, первый вариант - execute 'delete from table1 where id in(' + ids + ')' - как раз не очень подходит, покольку ids может содержать все что угодно.
Что касается PostgreSQL, можно как-нибудь так:
Код: plaintext
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.
CREATE OR REPLACE FUNCTION create_integer_array (_string varchar) RETURNS integer [] AS
$body$
DECLARE
    str text;
    strval text;  
    len integer;
    currval integer; 
    pos integer;
    arr INTEGER[]; 
    i INTEGER;
BEGIN
    str = _string;  
    i =  0 ;        
    select position(',' in str) into pos;
    WHILE (pos >  0 ) LOOP   
       select char_length(str) into len;   
       select substring(str from  1  for pos- 1 ) into strval;
       select to_number(strval,'00000000') into currval; 
       select substring(str from pos+ 1  for len) into str;
       select position(',' in str) into pos;
       i = i +  1 ; 
       arr[i] = currval; 
    END LOOP; 
        select ltrim(str,',') into strval;
        select to_number(strval,'00000000') into currval; 
        arr[i+ 1 ] = currval; 

   return arr;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY DEFINER;
При этом varchar _string - строка вида ''x1,x2,....,xN'', где x1,...,xN - целые числа.

И далее:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create function delsmth(_string varchar) RETURNS SETOF record AS
$body$
DECLARE
    ids       INTEGER[];
begin
  ids = create_integer_array(_string);
  delete from table1 where id = ANY(ids);
end;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY DEFINER;

Но ведь у Вас на клиенте, наверно, не один запрос вызывается. Если Вы вообще не хотите запросы в явном виде в коде писать, логично тогда их все через хранимые процедуры реализовывать.
...
Рейтинг: 0 / 0
Стринги против массивов, или я достану всех. =)
    #36014009
Саабразим Аль-каши Бухани
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Золотая рыбкаЕсли Вас смущает SQL-injection, первый вариант - execute 'delete from table1 where id in(' + ids + ')' - как раз не очень подходит, покольку ids может содержать все что угодно.

Поэтому мне это вариант и не особо нравится.
Золотая рыбка
Что касается PostgreSQL, можно как-нибудь так:

Спасибо!


Кстати получилось передавать параметр из java вот так:
Код: plaintext
1.
2.
3.
4.
5.
            Object[] param = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 };
            String separator = " | ";
            Array array = connection.createArrayOf("integer", param);
            CallableStatement proc = connection.prepareCall("select * from getallprods(?)");
            proc.setArray( 1 , array);
            ResultSet rs = proc.executeQuery();
Это так, к слову. Теперь у меня куча вариантов, за что спасибо большое ответившим.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Стринги против массивов, или я достану всех. =)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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