powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Пакетное выполнение команд, сравнение - строк 2 вопроса
31 сообщений из 31, показаны все 2 страниц
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388434
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1) Если я правильно понял, в окне Редактора команд нельзя выполнять
команды типа IF, CREATE FUNCTION
Каким наиболее оптимальным образом (в каком окне, что нужно сделать для вызова этого окна) можно выполнить команды вида

IF EXISTS (SELECT * FROM SYSCAT.ROUTINES WHERE ROUTINESCHEMA = 'VFP' AND ROUTINENAME = 'AT' ) THEN
DROP FUNCTION VFP.AT ;
END IF ;
IF EXISTS (SELECT * FROM SYSCAT.ROUTINES WHERE ROUTINESCHEMA = 'VFP' AND ROUTINENAME = 'RAT' ) THEN
DROP FUNCTION VFP.RAT ;
END IF ;
то есть я проверяю наличие пользовательских функций и затем их удаляю
и затем создание нескольких пользовательских функций ?
то есть выполнение несколько команд вида CREATE FUNCTION
Если я правильно понял, то аналогом команды GO MS SQL Server является команда @ ?
2) Точное (бинарное) сравнение и поиск в строках
Есть ли возможность при создании базы данных задать, какое будет сравнение строк -
чувствительное к регистру case-sensitive или нечувствительное к регистру
case-insensitive, то есть функции для работы со строками (типа locate, translate, replace)
будут работать по разному в зависимости от установки ?
Если я правильно понял документацию, то такой возможности в явном виде нет,
и сравнение зависит от collating sequence ?
В документации я нашел несколько примеров collating sequence SQL_CS_SYSTEM,
SQL_CS_SYSTEM_NLSCHA, SQL_CS_IDENTITY_16BIT и т.д.
Во всех присутствует CS - case-sensitive , отсюда вопрос встречал ли кто-нибудь в своей практике
collating sequence в которой сравнение и поиск строк был бы нечувствительным к регистру ?
Не имеет ли смысл использовать тип FOR BIT DATA для гарантированного бинарного сравнения и поиска в строках независимо от collating sequence ?
Спасибо.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388435
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Речь идет о базе данных DB2 Express.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388961
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конечно, в "Редакторе команд" можно выполнять как IF...THEN, так и CREATE FUNCTION. Вот с сочетанием различных команд могут возникнуть проблемы.

Перво-наперво, чтобы успешно выполнять команды типа CREATE FUNCTION, надо понимать смысл завершителей (statement termination character). Рассмотрим
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
BEGIN ATOMIC 
  FOR row AS 
    SELECT pk, c1, discretize(c1) AS d 
    FROM source 
  DO 
    IF row.d is NULL THEN INSERT INTO except VALUES(row.pk, row.c1); 
    ELSE INSERT INTO target VALUES(row.pk, row.d); 
    END IF; 
  END FOR; 
END;
По умолчанию "внешний" statement termination character равен точке с запятой ("внутренний" всегда равен точке с запятой), и это ведёт к неприятностям. "Внешний" надо задать другим символом (напр., @, и писать так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
BEGIN ATOMIC 
  FOR row AS 
    SELECT pk, c1, discretize(c1) AS d 
    FROM source 
  DO 
    IF row.d is NULL THEN INSERT INTO except VALUES(row.pk, row.c1); 
    ELSE INSERT INTO target VALUES(row.pk, row.d); 
    END IF; 
  END FOR; 
END @
), задаётся в левом нижнем углу экрана (для CLP - опция -tdРАЗДЕЛИТЕЛЬ, напр. -td@).
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388963
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пункт второй - EXISTS. В DB2 из IF его, к сожалению, не вызвать. Надо писать что-то вроде
Код: plaintext
1.
2.
3.
4.
5.
6.
BEGIN
  DECLARE i INTEGER;
  SET i = (SELECT  1  FROM ... FETCH FIRST  1  ROW ONLY);
  IF i =  1  THEN 
     ...
END @
Можно ещё делать DROP без проверки и перехватывать исключение.

Как я помню, в BEGIN ATOMIC ... END такие манипуляции невозможны, а BEGIN ... END должно быть частью хранимой процедуры.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388965
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зачем такие сложности (раньше был аналогичный вопрос с DROP'анием таблицы), когда можно просто писать, не утруждая себя проверками,
Код: plaintext
1.
2.
DROP такаяФункция;
DROP эдакаяФункция;
для меня загадка. Видимо, у молодёжи накапливается слишком много энергии, и им некуда больше её приложить.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388966
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@ - это не аналог MS SQL go, а просто разделитель. Можно выбрать другой.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33388967
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сравнение строк в DB2 чувствительно к регистру. Нечувствительное придётся задавать как SELECT ... FROM ... WHERE ucase(field) = ucase(:value). Индексов по функциям на данный момент нет, но есть суррогат. Если определить поле a la
u_field generated always as (ucase(field))
то оптимизер может осуществить подстановку как
SELECT ... FROM ... WHERE u_field = ucase(:value)
а по u_field можно создавать индекс
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33402404
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Виктор, большое спасибо за полный ответ.
Еще один вопрос к Вам, как к эксперту, но сначала небольшое предисловие.
Если я правильно понял, я не могу в пользовательской функции выполнять следующие команды
CREATE TABLE
DECLARE GLOBAL TEMPORARY TABLE
Теперь предположим, я пишу пользовательскую функцию, возвращающую таблицу ( в MS SQL Server я, к примеру, могу задать в такой функции имя возвращаемой таблицы), которая слова из строки символов помещает в таблицу.
В DB2 я должен обращаться к уже существующим таблицам – поэтому я не нашел лучшего решения
как создать командой CREATE TABLE SESSION.МОЯ_ТАБЛИЦА фиктивную таблицу для того, чтобы собрать пользовательскую функцию без появления сообщений типа «я не могу найти таблицу SESSION.МОЯ_ТАБЛИЦА»,
затем перед вызовом моей пользовательской функции я выполняю команду
DECLARE GLOBAL TEMPORARY TABLE МОЯ_ТАБЛИЦА
И при работе пользовательской функции при обращении к SESSION.МОЯ_ТАБЛИЦА происходит обращение в временной таблице, поскольку в соответствии с документацией при одновременном существовании
постоянной таблицы МОЯ_ТАБЛИЦА в схеме SESSION и одноименной временной таблице обращение к SESSION.МОЯ_ТАБЛИЦА относится к временной таблице.
Является ли найденный мной вариант наилучшим, можете ли Вы предложить нечто лучшее?
То есть пользовательская функция должна в идеале работать каждая со своей таблицей и возвращать в виде таблицы некий результат.
Спасибо.
Кстати, нашел интересное поведение функции Locate.
values locate('','string',100); возвращает 100, вообще, можно указать любое число в качестве третьего аргумента и функция возвратит его (если первый аргумент пустая строка). Хотя должна была бы возвращать всегда 0.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33402826
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор
Теперь предположим, я пишу пользовательскую функцию, возвращающую таблицу ( в MS SQL Server я, к примеру, могу задать в такой функции имя возвращаемой таблицы), которая слова из строки символов помещает в таблицу.
В DB2 я должен обращаться к уже существующим таблицам – поэтому я не нашел лучшего решения
как создать командой CREATE TABLE SESSION.МОЯ_ТАБЛИЦА фиктивную таблицу

Честно говоря не пойму зачем так делать?
Неужели обыкновенного SQL не хватает?
Можно ведь создать э... виртуальную временную таблицу, которая целиком раполагается в памяти. И работать будет быстрее.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33403564
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
наверное, наследие ms sql
почему-то работающие с ним очень _активно_ используют временные таблицы, но это субъективное наблюдение
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33403839
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ggvнаверное, наследие ms sql
почему-то работающие с ним очень _активно_ используют временные таблицы, но это субъективное наблюдение
Это не субъективное наблюдение. Такая же фигня с теми кто юзает Sybase.
У этих баз (они же родственники) SQL очень слаб.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404081
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
недавно давал "рецензию" по поводу возможности миграции проекта с ms sql на db2.
Посмотрел DDL скрипты, с просто неописуемым количеством temp tables, по нескольку штук в SP, поговорил с разработчиками - к ms sql претензий нет, все устраивает, вот только временные таблицы, вот с ними бы получше, чтоб не клинило так когда их много......
no comments
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404356
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Игорь2004: Я DECLARE GLOBAL TEMPORARY TABLE ещё не разу не использовал - просто не было нужды. Почитайте лучше "кулинарную книжку" с http://ourworld.compuserve.com/homepages/Graeme_Birchall/HTM_COOK.HTM

Если вы всё-таки будете настаивать на временных таблицах, то... поищите http://groups.google.com/group/comp.databases.ibm-db2, да на news://news.software.ibm.com, там были обсуждения. Я читал, но забыл почти сразу, о чём там говорилось. Помню только, что там есть свои тонкости, и вообще не факт, что к временной таблице можно обратиться из UDF (). Скорее нет, чем да.

Важный момент. "при одновременном существовании постоянной таблицы МОЯ_ТАБЛИЦА в схеме SESSION и одноименной временной таблице обращение к SESSION.МОЯ_ТАБЛИЦА относится к временной таблице." Очевидно, это относится к компиляции SQL-выражения. Предположим, на момент T1 временная таблица ещё не определена, вы скомпилировали SQL-выражение в момент T2, и затем определили временную таблицу в момент T3. В T4 выполнили SQL, но план SQL-выражения уже определён. Как я понимаю, план не должен измениться. А хранимая процедура на SQL в DB2, как правило, использует Static SQL, т.е. план хранится в базе. Стало быть, см
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404358
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
URL не туда попал - он про temporary в UDF.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404362
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UDF - не Static SQL, а фактически макроподстановка, компилируется вместе с вызвавшим её SQL-выражением, так что шансы могут быть. Но план надо смотреть.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404364
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
да и здесь на форуме что-то было --- типа, невыполнимое условие в теле процедуры, под условием - DECLARE GLOBAL TEMPORARY TABLE
и компилятор не ругается
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404514
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
(я успел немного погуглить) в ньюсгруппе comp.databases.ibm-db2 Серж Релю (?) предлагал решение
Код: plaintext
1.
2.
3.
IF  1 = 0  THEN
  DECLARE GLOBAL TEMPORARY TABLE...
END IF;
бррррр
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404541
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Victor Metelitsa
Важный момент. "при одновременном существовании постоянной таблицы МОЯ_ТАБЛИЦА в схеме SESSION и одноименной временной таблице обращение к SESSION.МОЯ_ТАБЛИЦА относится к временной таблице." Очевидно, это относится к компиляции SQL-выражения. Предположим, на момент T1 временная таблица ещё не определена, вы скомпилировали SQL-выражение в момент T2, и затем определили временную таблицу в момент T3. В T4 выполнили SQL, но план SQL-выражения уже определён. Как я понимаю, план не должен измениться. А хранимая процедура на SQL в DB2, как правило, использует Static SQL, т.е. план хранится в базе.
Неверно. When binding a package that has static SQL statements that refer to tables implicitly or explicitly qualified by SESSION, those statements will not be bound statically. When these statements are invoked, they will be incrementally bound, regardless of the VALIDATE option chosen while binding the package. At runtime, each table reference will be resolved to a declared temporary table, if it exists, or a permanent table. If neither exists, an error will be raised (SQLSTATE 42704). Но это к SP и т.п., а насчёт UDF всё ещё непонятно.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404545
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот теперь всё ясно.
Restrictions on the Use of Declared Global Temporary Tables: Declared global temporary tables cannot:
– Be specified in an ALTER, COMMENT, GRANT, LOCK, RENAME or REVOKE statement (SQLSTATE 42995).
– Be referenced in a CREATE ALIAS, CREATE FUNCTION (SQL Scalar, Table, or Row), CREATE TRIGGER, or CREATE VIEW statement (SQLSTATE 42995).
– Be specified in referential constraints (SQLSTATE 42995).
Очевидно, я это всё читал, но забыл.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404547
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вывод: читайте кулинарную книжку. http://ourworld.compuserve.com/homepages/Graeme_Birchall/HTM_COOK.HTM
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404750
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gardenman ggvнаверное, наследие ms sql
почему-то работающие с ним очень _активно_ используют временные таблицы, но это субъективное наблюдение
Это не субъективное наблюдение. Такая же фигня с теми кто юзает Sybase.
У этих баз (они же родственники) SQL очень слаб.
Слабый SQL это не главная причина. Я например тоже спокойно юзаю локальные и глобальные времянки на WatcomSQL, хотя его слабым назвать по отношению MSSQL/Sybase ASE нельзя. Глобальные времянки позволяют клиентскому приложению сессионно хранить промежуточные данные (например юзер понащелкал в списке, что должно попасть в отчет, клиентская прога это сохранила в глобальную времянку и вызвала отчет, который обычным джойном по заполненной времянке уже фильтрует в отчет только то, что нужно). Локальные времянки же используются внутри ХП для разруливания сложных запросов, промежуточных аггрегаций, используемых многократно и борьбы с блокировками. С учетом того, что у нас глобальные и локальные времянки можно обьявлять как NOT TRANSACTIONAL и нет такого тяжелого наследия, как TempDB у MSSQL, то с времянками все просто летает. И кстати на глобальные времянки можно вешать все что угодно и использовать где угодно, кроме FOREIGN KEY. Хоть триггеры писать - что иногда очень даже неплохо. Так что не надо удивляться тому, чего не понимаешь - я вот например в тихом шоке, что DB2-шники хранимки предпочитают на C писать и вообще тут язык хранимых процедур насколько я понимаю не очень то давно появился, я не представляю, как без него в СУБД можно было обходится - судя по работающим проектам на DB2 - можно, хотя мне понять и сложно.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33404773
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем участникам за высказанные мнения.
TO gardenman

“Можно ведь создать э... виртуальную временную таблицу, которая целиком раполагается в памяти”
А каким образом можно создать виртуальную временную таблицу ? Я ничего про виртуальные временные таблицы,
к сожалению, не нашел в документации. Только про временные и глобальные временные таблицы.

To Виктор Вы совершенно правы касательно временных таблиц (из функции их просто не видно).
Спасибо за порекомендованую книжку, весьма доступно и хорошо написана. Мне там понравился следующий пример, в котором таблица наполняется «из воздуха»,
если можно так выразится.
Вот этот пример
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE FUNCTION NumList(max_num INTEGER)
RETURNS TABLE(num INTEGER)
LANGUAGE SQL
BEGIN ATOMIC
RETURN WITH temp1 (num) AS
(VALUES ( 0 )
UNION ALL
SELECT num +  1  FROM temp1 WHERE num < max_num)
SELECT num FROM temp1;
END    
Собственно говоря, я затеял возню с временными таблицами, только для того, чтобы в функции, возвращающей таблицу,
не обращаться ни к какой постоянной таблице.
Вот описание моей функции
GETALLWORDS() Функция определенная пользователем
Помещает в таблицу все слова из строки
GETALLWORDS( cString[, cDelimiters])
Тип возвращаемого значения таблица GETALLWORDS (WORDNUM smallint, WORD varchar(4000), STARTOFWORD smallint, LENGTHOFWORD smallint)
Описание структуры возвращаемой таблицы GETALLWORDS
поле WORDNUM smallint – порядковый номер слова в строке cString
поле WORD varchar(4000) - слово
поле STARTOFWORD smallint – позиция в строке cString, с которой начинается слово
поле LENGTHOFWORD smallint – длина слова

Параметры
cString varchar(4000) – строка, слова которой будут помещены в таблицу GETALLWORDS.
cDelimiters varchar(256) - необязательный параметр, определяет те символы, которые будут служить разделителями слов в строке cString. Разделителями по умолчанию являются пробелы, символы табуляции, возврата каретки и перевода строки.
GETALLWORDS() считает каждый символ из строки cDelimiters как отдельный разделитель, а не всю строку cDelimiters как единый разделитель.
Примечания: GETALLWORDS() по умолчанию считает, что слова разделены пробелами, символами табуляции, возврата каретки и перевода строки. Если передан параметр cDelimiters, функция игнорирует пробелы, символы табуляции, возврата каретки и перевода строки.
Пример вызова:
Код: plaintext
1.
2.
SELECT *  FROM TABLE(VFP.GETALLWORDS('Как прикажете, мессир? - спросил Фагот у замаскированного.
      Ну что  же, -  задумчиво отозвался тот,  они  люди как  люди. Любят деньги, но ведь это всегда было...  Человечество любит деньги, из чего бы  те ни  были сделаны,  из кожи ли, из бумаги ли, из бронзы или из золота.
Ну,  легкомысленны...  ну,  что  ж... и  милосердие  иногда  стучится  в  их сердца...  обыкновенные люди... в  общем,  напоминают прежних...  квартирный вопрос только испортил их...')) AS A;
Вот какое решение мне удалось найти (пришлось создать постоянную таблицу), наполнять ее, возвращать результат и
при последующих вызовах удалять записи, вставленные в предыдущих вызовах.
Но у моего решения возможно есть недостаток – теоретически при большом количестве вызовов, один пользователь
Может удалить записи вставленные другим пользователем. Это место показано в коде.
Не говяря уже о том что наверняка есть более красивое решение.
Отсюда вопрос – может ли кто-нибудь предложить другое, более элегантное решение.
Использовать временную таблицу (наполняя ее в самой функции как в приведенном выше прмере из «кулинарной» книги мне не удалось, поскольку, алгоритм поиска слов в строке не является простым).
Вот код моей функции
Код: 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.
31.
32.
33.
34.
35.
36.
37.
38.
39.
CREATE FUNCTION VFP.GETALLWORDS
(cString1 VARCHAR( 4000 ), cDelimiters1 VARCHAR( 256 ))
RETURNS table (WORDNUM SMALLINT, WORD VARCHAR( 4000 ), STARTOFWORD SMALLINT, LENGTHOFWORD SMALLINT)
SPECIFIC  GETALLWORDS
DETERMINISTIC NO EXTERNAL ACTION MODIFIES SQL DATA
BEGIN ATOMIC
     DECLARE   k, BegOfWord, wordcount, nEndString, flag SMALLINT;
     DECLARE cString  VARCHAR( 4000 ) FOR BIT DATA;
     DECLARE cDelimiters  VARCHAR( 256 ) FOR BIT DATA;
     DECLARE CALL_ID  CHAR( 13 ) FOR BIT DATA;
     SET CALL_ID  = GENERATE_UNIQUE();
     SET  cString = cString1,  cDelimiters  = cDelimiters1;
     SET   k =    1  ,  wordcount  =   1  ,  BegOfWord  =   1  ,  flag  =   0  ,  cString  =  COALESCE(cString, '') ,  cDelimiters  =  COALESCE(cDelimiters,  CHR( 32 ) CONCAT  CHR( 9 ) CONCAT CHR( 10 ) CONCAT  CHR( 13 )) ,
     nEndString  =   1   +  LENGTH(cString);
     BOUCLE: WHILE  1  >  0      DO
          IF k - BegOfWord >  0  THEN
                INSERT INTO  VFP1.GETALLWORDS (WORDNUM, WORD, STARTOFWORD, LENGTHOFWORD, UNIQUE_ID )
                             VALUES      (wordcount, SUBSTR(cString, BegOfWord, k - BegOfWord), BegOfWord, k - BegOfWord, CALL_ID );
                SET   wordcount =   wordcount  +   1   ,  BegOfWord  =  k; -- previous word
          END IF;
          IF flag =  1  THEN
                LEAVE BOUCLE;
          END IF;
          WHILE nEndString > k and LOCATE(SUBSTR(cString, k,  1 ), cDelimiters) >  0        DO
               SET   k =   k  +   1   ,  BegOfWord  =  BegOfWord  +   1 ; -- skip  break characters, if any
          END WHILE;
          WHILE  nEndString > k and LOCATE(SUBSTR(cString, k,  1 ), cDelimiters) =  0       DO
               SET   k =   k  +   1 ; -- skip  the character in the word
          END WHILE;
          IF k >= nEndString THEN
               SET   flag =    1 ;
          END IF;
     END WHILE;

    DELETE FROM VFP.GETALLWORDS WHERE DEL = 'T' AND  UNIQUE_ID < CALL_ID;
    UPDATE  VFP1.GETALLWORDS SET DEL = 'T' WHERE UNIQUE_ID  = CALL_ID;
-- вот узкое место (на мой взгляд) в данный момент кто-нибудь может удалить 
-- только что полученный реультат
   RETURN SELECT WORDNUM, WORD, STARTOFWORD, LENGTHOFWORD  FROM  VFP1.GETALLWORDS WHERE UNIQUE_ID  = CALL_ID ;
END


При всех недостатках MS SQL Server там данная задача решалась легко, возможно и DB2 есть нормальное решение.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33405153
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Игорь
"виртуальную временную таблицу" я как раз и имел в виду рекурсивные запросы. Вы наверное никогда не пробовали юзать рекурсивный SQL. Попробуйте. Кстати, в том же COOK BOOK есть пример Normalize/Denormalize data. Это как раз вам в тему. И, если мне не изменяет память здесь на форуме был уже пример как строку разложить по словам в таблицу.
И, еще, если вдруг вам придет в голову создать выражение, которое возвращает конкретное число записей, посмотрите в сторону values:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
db2 => values ( 1 ,current timestamp),( 2 ,current timestamp),( 3 ,current timestamp)

 1             2 
----------- --------------------------
           1   2005 - 11 - 29 - 11 . 00 . 21 . 351000 
           2   2005 - 11 - 29 - 11 . 00 . 21 . 351000 
           3   2005 - 11 - 29 - 11 . 00 . 21 . 351000 

   3  record(s) selected.

db2 =>


А что касается использовать SQL для решения задач подобной вашей, я .. даже не смотря на то, что SQL позволяет все это сделать решил бы ее на C/C++. Я конечно затрачу времени на это раза в 2-3 больше, но производительность увеличится раз в 100. Причем табличные функции на C/C++ именно в DB2 пишутся просто влет. Задача приведенная вами - сугубо вычислительная. Жрет много процессорных ресурсов.

Кстати, объясните пожалуйста зачем cScting и cDelemiters вы делаете FOR BIT DATA.

2 ASCRUS
У DB2 есть спицифика в разработке. Особые фичи.Особый путь. Которым можно и не пользоваться. Я здесь на форуме неоднократно говорил о том, что такое Static SQL. Для чего нужны ХП? Для того, чтобы избавится от затрат времени на компиляцию. Для того, чтобы перенести бизнес-логику на сервер.
А в DB2 это возможно и без ХП. С помощью статического SQL. Причем производительность только выростет. Если действительно есть желание с этим разобраться почитайте про команды BIND и PREP и про статический SQL.

Что касается временных таблиц в DB2. Когда вы создаете временную таблицу инфа о ней не хранится в системном каталоге. Я даже не знаю способа посмотреть список всех временных таблиц. Да и получить структуру временной таблицы можно лишь так:
describe select * from <tmpеtable>
Поэтому при создании времянок нет никаких блокировок в системном каталоге.
но с другой стороны и триггеров не создать Короче все приносится в жертву только одному - производительности.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33406708
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извините, пока лень вникать в ваш алгоритм. В чём вы видите "не является простым"? В том, что разделители могут быть разными? Так их можно свести к одному (пробелу) при помощи функции TRANSLATE, после чего уже воспользоваться примером из кулинарной книжки, разбирающим строку на слова (там была небольшая ошибка, но её легко исправить). При этом нумерация получается легко, а длина слова получается, естественно, функцией LENGTH от этого слова. (lenght(WORD)=LENGTHOFWORD)

Над вычислением STARTOFWORD надо подумать. Скажем, можно попробовать так: рекурсивный алгоритм "поедает" анализируемую строку, и зная начальную длину и длину "поедаемого" остатка, можно определить и STARTOFWORD.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33406716
Victor Metelitsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Игорь2004
-- вот узкое место (на мой взгляд) в данный момент кто-нибудь может удалить
-- только что полученный реультат
Каким же образом? Строки ведь заблокированы до завершения транзакции. Вот добавить своё (в новой DB2; в старой тоже сядет на блокировку), пожалуй, сможет.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33407419
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To gardenman
“я как раз и имел в виду рекурсивные запрос”
У меня была смутная догадка на этот счет, я искал по слову «virtual» но ничего не нашел.

“Кстати, в том же COOK BOOK есть пример Normalize/Denormalize data. Это как раз вам в тему.”
Да, именно так.

« И, если мне не изменяет память здесь на форуме был уже пример как строку разложить по словам в таблицу.»
Мне ничего найти не удалось.

«даже не смотря на то, что SQL позволяет все это сделать решил бы ее на C/C++. Я конечно затрачу времени на это раза в 2-3 больше, но производительность увеличится раз в 100. Причем табличные функции на C/C++ именно в DB2 пишутся просто влет.»
А с каким компилятором пишуться программы на C/C++ для DB2 ?
А интересно было бы сравнить разницу в скорости ?
Есть ли бесплатные компиляторы для этой цели, и примеры того как нужно писать , компилировать и вызывать написанное из DB2 ?

«Кстати, объясните пожалуйста зачем cScting и cDelemiters вы делаете FOR BIT DATA.»
1) Скорость работы строковых функций по моему предположению должна быть выше поскольку не зависит от Collattion Setting
2) Сравнение и поиск всегда чувствительны к регистру (вдруг все таки есть базы нечувствительные к регистру)
Все это мои предположения, хотя вроде что –то мельком видел в документации.



To Виктор
«Каким же образом? Строки ведь заблокированы до завершения транзакции. Вот добавить своё (в новой DB2; в старой тоже сядет на блокировку), пожалуй, сможет.» Я предполагал нечто подобно, и хотел получить подтверждение.

«пока лень вникать в ваш алгоритм.» Алгоритм надежный как автомат Калашникова, просто в DB2 выглядит некрасиво.

« В чём вы видите "не является простым"? В том, что разделители могут быть разными? Так их можно свести к одному (пробелу) при помощи функции TRANSLATE»
Читая пример я тоже до этого додумался. Но сводить в общем случае не к пробелу (ведь его может и не быть в строке из символов разделителей),
а к одному из (любому) символов из строки разделителей, в частном случае лучше к пробелу.

«там была небольшая ошибка, но её легко исправить».
На самом деле две ошибки – пример не работал при пустом символе разделителе, и в двух местах нужно было вычесть 1.

Ну что ж в итоге получилась функция (будет время сравню по скорости с предыдущим вариантом) ,
Работает и пустым разделителем, и с единым разделителем состоящим из нескольких разных символов.
Код: 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.
31.
-- вспомогательная функция ( в общем случае мне нужно обрезать  единый разделитель состоящий из нескольких разных символов,
-- пробел является часным случаем
CREATE FUNCTION VFP.MYLTRIM
(cExpressionSearched VARCHAR( 4000 ), cSearchExpression VARCHAR( 256 ))
RETURNS VARCHAR( 4000 )
SPECIFIC  MYLTRIM
DETERMINISTIC NO EXTERNAL ACTION CONTAINS SQL
BEGIN ATOMIC
    DECLARE   i, len, lencSearchExpression  SMALLINT;
    DECLARE cLtrimString VARCHAR( 4000 );
    SET  i  =   1 ,  len  =  LENGTH(cExpressionSearched),  lencSearchExpression  =  LENGTH(cSearchExpression) ;
    IF  lencSearchExpression =  1  and ASCII(cSearchExpression) =  32  THEN
       SET cLtrimString  = LTRIM(cExpressionSearched);
    ELSE
     IF  lencSearchExpression >  0  THEN
         IF  len >  0  THEN
      	    BOUCLE: WHILE i <= len   DO
     	      IF  (i + lencSearchExpression -  1 ) > len OR LOCATE(cSearchExpression, SUBSTR(cExpressionSearched, i, lencSearchExpression)) =  0  THEN
	            LEAVE  BOUCLE;
      	      END IF;
              SET   i =   i  +  lencSearchExpression;
            END WHILE;
           SET cLtrimString = RIGHT(cExpressionSearched, len - i +  1 ) ;
         ELSE
          SET cLtrimString = '';
        END IF;
      ELSE
        SET cLtrimString = cExpressionSearched;
      END IF;
   END IF;
  RETURN cLtrimString;
END



Код: 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.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
CREATE FUNCTION VFP.GETALLWORDS2
(cString1 VARCHAR( 4000 ), cStringSplitting1 VARCHAR( 256 ))
RETURNS table (WORDNUM SMALLINT, WORD VARCHAR( 4000 ), STARTOFWORD SMALLINT, LENGTHOFWORD SMALLINT)
SPECIFIC GETALLWORDS2
DETERMINISTIC NO EXTERNAL ACTION CONTAINS SQL
-- GETALLWORDS2() User-Defined Function Inserts the words from a string into the table.
 -- GETALLWORDS2( cString[,  cStringSplitting])
 -- Parameters
 -- cString   varchar(4000) - Specifies the string whose words will be inserted into the table  GETALLWORDS2.
 -- cStringSplitting  varchar(256) - Optional. Specifies the string used to separate words in  cString.
 -- The default delimiter is space.
 -- Note that GETALLWORDS2( ) uses   cStringSplitting as a single delimiter.
 -- Return Value table
 -- Remarks GETALLWORDS2() by default assumes that words are delimited by space. If you specify another string as delimiter, this function ignores spaces and uses only the specified string.
 -- Example
 -- SELECT WORD FROM TABLE(VFP.GETALLWORDS2('We hold these truths to be self-evident,
 that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty
 and the pursuit of Happiness.')) AS A where WORDNUM = 30 ;  -- Displays 'Liberty'
 -- SELECT WORDNUM  FROM TABLE(VFP.GETALLWORDS2('SQL Procedural Language DB2')) AS A ORDER BY WORDNUM DESC FETCH FIRST 1 ROW ONLY; -- Displays 4
 -- See Also GETWORDNUM() , GETWORDCOUNT() ,  GETALLWORDS()  User-Defined Functions
BEGIN ATOMIC
    DECLARE nEndString, nLenSrtingSplitting, BegOfWord SMALLINT;
    DECLARE cString  VARCHAR( 4000 );
    DECLARE cStringSplitting VARCHAR( 256 );
    SET  cString = cString1,  cStringSplitting = cStringSplitting1, BegOfWord =  1  ;
    SET  cString  =  COALESCE(cString, ''), cStringSplitting  =  COALESCE(cStringSplitting, ' '), nLenSrtingSplitting  =  LENGTH(cStringSplitting), nEndString  =  1  + LENGTH(cString);

    IF nLenSrtingSplitting >  0   THEN
               WHILE BegOfWord < (nEndString - nLenSrtingSplitting +  1  )  AND  LOCATE(SUBSTR(cString, BegOfWord, nLenSrtingSplitting), cStringSplitting) >  0      DO
                     SET   BegOfWord =   BegOfWord  +  nLenSrtingSplitting; --  skip break strings, if any
               END WHILE;
               SET  cString = SUBSTR(cString, BegOfWord);
    END IF;
RETURN WITH
   TEMP1 ( STRING) AS (VALUES (cString) ),
   TEMP2 ( WORDNUM, STARTOFWORD, WORD, STRING_LEFT) AS
   (SELECT  SMALLINT( 1 ), BegOfWord,
   SUBSTR(STRING, 1 , CASE WHEN LOCATE(cStringSplitting, STRING) =  0  OR nLenSrtingSplitting =  0  THEN LENGTH(STRING) ELSE LOCATE(cStringSplitting,STRING) -  1  END),
   CASE WHEN nLenSrtingSplitting =  0  THEN '' ELSE VFP.MYLTRIM(SUBSTR(STRING, CASE LOCATE(cStringSplitting, STRING) WHEN   0  THEN LENGTH(STRING) + nLenSrtingSplitting ELSE LOCATE(cStringSplitting,STRING) END), cStringSplitting)  END
   FROM TEMP1 WHERE STRING <> ''
   UNION ALL
     SELECT WORDNUM +  1 ,  nEndString - length(STRING_LEFT),
     SUBSTR(STRING_LEFT, 1 , CASE LOCATE(cStringSplitting,STRING_LEFT) WHEN  0  THEN LENGTH(STRING_LEFT) ELSE LOCATE(cStringSplitting,STRING_LEFT) -  1  END),
     VFP.MYLTRIM(SUBSTR(STRING_LEFT, CASE LOCATE(cStringSplitting,STRING_LEFT) WHEN  0  THEN LENGTH(STRING_LEFT) + nLenSrtingSplitting ELSE LOCATE(cStringSplitting,STRING_LEFT) END), cStringSplitting)
     FROM TEMP2 WHERE STRING_LEFT <> '' )
  SELECT WORDNUM, WORD, STARTOFWORD, LENGTH(WORD) FROM TEMP2 ORDER BY  1 ;
END


Код: 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.
31.
CREATE FUNCTION VFP.GETALLWORDS
(cString1 VARCHAR( 4000 ), cDelimiters VARCHAR( 256 ))
RETURNS table (WORDNUM SMALLINT, WORD VARCHAR( 4000 ), STARTOFWORD SMALLINT, LENGTHOFWORD SMALLINT)
SPECIFIC  GETALLWORDS
DETERMINISTIC NO EXTERNAL ACTION MODIFIES SQL DATA
-- GETALLWORDS() User-Defined Function Inserts the words from a string into the table.
 -- GETALLWORDS( cString[,  cDelimiters])
 -- Parameters
 -- cString   varchar(4000) - Specifies the string whose words will be inserted into the table  GETALLWORDS. 
 -- cDelimiters  varchar(256) - Optional. Specifies one or more optional characters used to separate words in  cString.
 -- The default delimiters are space, tab, carriage return, and line feed. Note that GETALLWORDS( ) uses each of the characters in  cDelimiters as individual delimiters, not the entire string as a single delimiter. 
 -- Return Value table 
 -- Remarks GETALLWORDS() by default assumes that words are delimited by spaces or tabs. If you specify another character as delimiter, this function ignores spaces and tabs and uses only the specified character.
 -- Example
 -- SELECT *  FROM TABLE(VFP.GETALLWORDS('The default delimiters are space, tab, carriage return, and line feed.
 If you specify another character as delimiter, this function ignores spaces and tabs and uses only the specified character.')) AS A;
 -- See Also GETWORDNUM() , GETWORDCOUNT() User-Defined Functions 
BEGIN ATOMIC
     DECLARE cCharSplitting VARCHAR( 1 ) DEFAULT '';
     DECLARE cString  VARCHAR( 4000 );
     SET  cString = cString1;
     IF  LENGTH(cDelimiters) >  0   THEN
        IF LOCATE(SPACE( 1 ), cDelimiters) >  0  THEN
            SET cCharSplitting = SPACE( 1 );
        ELSE
            SET cCharSplitting = LEFT(cDelimiters, 1 ) ;
        END IF;
        SET cString = TRANSLATE(cString, REPEAT(cCharSplitting,  LENGTH(cDelimiters)), cDelimiters);
     END IF;

   RETURN SELECT WORDNUM, WORD, STARTOFWORD, LENGTHOFWORD  FROM TABLE(VFP.GETALLWORDS2(cString, CAST(cCharSplitting AS VARCHAR( 256 )))) AS GETALLWORDS;
END

Еще раз спасибо за высказанные мнения и полезные советы.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33407905
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> А с каким компилятором пишуться программы на C/C++ для DB2 ?
> А интересно было бы сравнить разницу в скорости ?

Если вы на виндовой платформе это делаете, то можете скачать MinGW (www.mingw.org) - это будет абсолютно бесплатно (gcc ).
Или можете воспользоваться MS Visual С++ (любая версия)
Ежели вы под Linux хотите - то там всегда gcc есть.Под AIX наверно icc или опять же gcc. Как и под Solaris.

Кстати, был такой пример, когда я генерил строку случайных символов таким образом: CHR(INT(RAND()*25+65))||CHR(INT(RAND()*25+65))||CHR(INT(RAND()*25+65))||...
А потом реализовал то же самое, но на C++...
Разница в производительности была на порядок. Причем естественно зависила от длины строки.

Если вам действительно не лень, и действительно хочется добиться крутой производительности, то реализуйте эту функцию на C++. В принципе могу даже помочь)))
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33410107
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To gardenman
Спасибо.
Если бы я решил переписать свои функции на C, то у меня основное время ушло бы на поиск примеров таких функций для DB2, с какими опциями компилировать, как вызывать из DB2 - поскольку у меня нет такого опыта.
Что касается конвертации строки символов в таблицу, то ведь все равно придется задействовать вызов SQL DB2 только уже из функции написанной на C и там, вероятно, разница в скорости не будет столь значительной.
Что касается работы со строками, то разница в скорости конечно будет большой.
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33410283
Herr Developer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Интересно, если тоже самое и сделать на Java или .NET языке (Windows only), насколько бы это было бы конкурентноспособным по сравнению с C/C++...
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33410890
ggv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ggv
Гость
Игорь - в дистре db2 идет просто куча примеров на все случаИ жизнИ.

ACRUS - только вчера общался с разработчиками приложений DB2 (и эти приложения используете и вы - только не знаете), которые пишут на ASM.
В отношении SP у них такое же мнение, как и у gardenman и у меня. С поправкой - если надо, то уж лучше на С
...
Рейтинг: 0 / 0
Пакетное выполнение команд, сравнение - строк 2 вопроса
    #33411107
gardenman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Что касается конвертации строки символов в таблицу, то ведь все равно придется задействовать вызов SQL DB2

Основные ресурсы при работе виртуальной машины SQL - это распредение/освобожнение памяти особенно когда работаете с такими типами как VARCHAR/LOB. У DB2 при написании внешних функций есть отличная штука - SCRATCHPAD (поищите тут по форуму). Этим можно очень эффективно пользоваться. Поэтому когда я говорю что производительность можно увеличить на порядок - это правда.
...
Рейтинг: 0 / 0
31 сообщений из 31, показаны все 2 страниц
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Пакетное выполнение команд, сравнение - строк 2 вопроса
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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