Какой код можно использовать в качестве агрегатора строк для Sybase? (Как и Оракул Стрэгг) - PullRequest
2 голосов
/ 24 июня 2010

Во время моих путешествий в Oracle функция 'stragg' или 'String Aggregator' спасала мне жизнь, когда мне приходилось создавать динамические запросы SQL на лету.

Вы можете прочитать об этом здесь: http://www.oratechinfo.co.uk/delimited_lists_to_collections.html

Основное использование было:

select stragg(fruit) from food;

fruit
-----------
apple,pear,banana,strawberry

1 row(s) returned

Простое в использовании, объединение chr (13) превратило его в длинный список, а выбор информации из системных таблиц дал 5-минутное решение для динамически генерируемого SQL, например, триггеры аудита.

Теперь меня обвинили в переносе функциональности оракула, связанной с одитингом, в Sybase, и для этой цели идеально подойдет функция, аналогичная Stragg.

* 1013 Е.Г. *

select @my_table = 'table_of_fruit'

select 'insert into '+@mytable+'_copy (' +char(10)
   + stragg(c.name) +char(10)
   + 'select '
   + stragg('inserted.'+c.name) + char(10)
   + 'from '+@mytable
from syscolumns c
where objectid(@mytable) = c.id


------------------------------------------
insert into table_of_fruit_copy
(fruit, sweetness, price) 
select fruit, sweetness,price 
from inserted

Готово. Простой.

Кроме того, я не знаю, как заставить функцию агрегации строк работать в Sybase.

Кто-нибудь знает о попытке сделать что-то подобное или код, который мог бы работать так же, как и Stragg, который мог бы использоваться таким образом?

Альтернативой на данный момент является печать кода на основе сложных курсоров и тому подобного (пример LOC: 500) или операторы выбора, объединяющие статические строки и столбцы из пользовательских таблиц (пример LOC: 200). Стрэгг значительно уменьшил бы сложность этого кода и очень помог бы в будущем (пример LOC: кто знает, может быть, 50?)

p.s. Я вызываю эти селекты через скрипт оболочки, затем отправляю их в файл, затем запускаю файл через iSQL. Не самое лучшее решение, но оно лучше, чем альтернативы.

Ответы [ 2 ]

3 голосов
/ 12 декабря 2010

Есть три отдельных ответа

Вопрос

Вы прокомментировали простоту, к которой необходимо обратиться, прежде чем мы найдем решение.

Общим требованием является возможность иметь список значений с разделителями, скажем A, B, C, D, и обрабатывать эти данные, как если бы они были набором строк в таблице, или наоборот

  1. Это одна из десятка худших практик программирования , о которых я недавно читал.

  2. В целом, типы Sybase, как правило, имеют более академическую и относительную квалификацию, чем типы Oracle, поэтому мы просто не делаем такого рода вещи в SybaseLand или DB2Land.

  3. За 20 лет работы с Sybase мне пришлось кодировать это как часть моего проекта только один раз, и это было для нетехнического Аудитора, который загрузил набор результатов в MS Access.

  4. С другой стороны, мне приходилось кодировать это как минимум 12 раз при создании текстовых файлов для импорта в базы данных Oracle (выполнение внешних требований выходит за рамки моего проекта, но я удовлетворяю любое такое требование бесплатно). Очевидно, что целевые базы данных были нестандартными и нереляционными (загрузка столбца с более чем одной базовой датой разбивает 1NF и создает аномалии обновления), что типично для действий типов Oracle, необходимых для получения некоторой скорости.

  5. Следовательно, нет, это не простота, по крайней мере, в смысле этого принципа. Это по определению, сложность.

  6. Ваша ссылка на "массивы" неверна. Все коммерческие dbms обрабатывают массивы в соответствии с ISO / IEC / ANSI SQL (операторы STRAGGR и LIST являются нестандартным SQL, поэтому не SQL). Sybase очень сильна в обработке массивов. Если бы это был массив, вам не понадобилось бы специальное ручное кодирование, чтобы справиться с ним (и вы это делаете, согласно вашему вопросу). Это не массив, нет определения для ячеек. Это одна объединенная скалярная строка.

  7. Поворот - это совершенно другой процесс, использующий обработку множеств; не требует обработки строк. (Я хорошо понимаю, что Oracle безнадежен в скалярных подзапросах, и поэтому люди Oracle привыкли писать их как [очень неэффективные] соединения или встроенные представления, а затем фильтровать: все, что можно поднять до обработки множеств через скалярные подзапросы) и он будет работать намного быстрее. Особенно ваши Pivots.)

  8. Даже автор в вашей ссылке публикует следующее. Пожалуйста, ознакомьтесь с предостережениями:

Это так просто: если вы хотите иметь систему без логических ограничений на количество элементов данных, передаваемых данному процессу, то забудьте о следующих механизмах! Это просто неправильный подход к проблеме.

  1. Следовательно, знают , что бы вы ни делали, это нестандартное, нереляционное и ограниченное; и идти вперед с открытыми глазами. Нет смысла притворяться, что: он не сломается; это не ограничено; это «массив»; или что у Sybase нет изящной маленькой функции, которую имеет Oracle. Любой профессионал увидит все это. И если длина строки превышена, ради Бога, отправьте некоторый индикатор обратно вызывающей стороне («! Превышено» в строке), идентифицирующее это условие.

  2. По сути, вы поворачиваете механизм обработки множеств на его голову и переводите его в режим обработки строк, поэтому он будет очень медленным. Цикл WHILE значительно быстрее, чем курсор, но оба находятся в одном классе - процессоры строк.

Альтернативой на данный момент является печать кода на основе сложных курсоров и подобных

  1. Какие 200 или 500 LoC?Возможно, я что-то упустил, но мой код - это те же несколько строк кода, которые указаны в «Использование табличной функции» в вашей ссылке. Максимум 20 , если считать хорошее форматирование;петля;инициализация;обработка ошибок.В этом нет ничего «сложного».Выполните точную обратную операцию, чтобы канкатировать одну строку из нескольких строк.Для этого мы используем хранимые процедуры (чего у оракула на самом деле нет, PL / SQL - другое животное).Если у вас ASE 15.0.2 или выше, вы можете использовать пользовательскую функцию, которую затем можете использовать вместо столбца.Сохраненные процедуры лучше подходят для истинных массивов.

    • оператор объединения в Sybase - знак плюс.Для обращения (разложения строки CSV) вам понадобятся функции CHARINDEX и SUBSTRING

    • Возможно, вам понадобится справочное руководство по функциям , если ни для чего другого, чтобы избежать написания кода, где у нас есть функции.

Аналогично, у нас нет функции RANK () .Мы вполне довольны 4 строками кода, необходимыми для подзапроса.Это требуется только для Oracle, потому что подзапросы повреждены.


Хорошо, я ответил на ваш вопрос, а теперь рассмотрим подходы.

  • Вы будете знать, что код, использующий Oracle Расширения к стандарту SQL, необходимо изменить.

  • Sybaseнамного более автоматизирован, чем Oracle;если вы ознакомитесь с его набором функций, во многих случаях вы можете получить тот же результат (как вы это делали в Oracle) без написания какого-либо кода.Написание блоков кода для кода - это цепная банда, потрясающий метод строительства дорог в контексте бульдозеров.Даже если у вашей компании были веские причины использовать этот метод, вам нужно знать, что функции работают совершенно по-другому, например.триггеры, поэтому я публикую так много деталей.

  • Еще одна проблема, которая вас раздражает, заключается в том, что Oracle на самом деле не совместим с ANSI SQL (во многих местах растягиваются определения, чтобы казался совместимым)и Sybase, учитывая свою клиентскую базу, строго соответствует требованиям SQL.Таким образом, в дополнение к тому, что одна и та же функция работает по-разному или в другом развертывании, вы должны знать, что изменения кода могут потребоваться для повышения уровня кода Oracle до уровней соответствия ANSI, просто для выполнения на платформе, совместимой с ANSI SQL.

Я не уверен, пытаетесь ли вы написать код для содержимого триггера или пытаетесь записать изменения в базу данных.Я предоставлю оба ответа.

Аудит

Сохранение изменений в базе данных

У нас очень надежная, быстрая и настраиваемая подсистема аудита, пригодная для высокихобъемы и требования аудита на банковском уровне.Заставьте своего администратора баз данных настроить отдельную базу данных sybaudit и точно настроить, какие изменения необходимо зафиксировать.Это средство будет работать намного быстрее, чем любой код, который вы или я можем написать в триггере (в 100 раз быстрее, чем ваша построчная обработка, необходимая для вышеперечисленного, так как она выполняется внутри механизма, внутри вашего исполняющего потока).И, конечно, время установки - это часть вашего времени кодирования.

Триггеры

Опять же, я не уверен точно , что вы пытаетесь достичь, но при условии, что выЕсли вы хотите скопировать каждую вставку в какую-либо таблицу в КОПИРУЮ этой таблицы (внутри Trigger), предоставленный вами пример кода не будет работать (и я не считаю проблемы с синтаксисом).

  1. Если обратиться к вашему примеру, вам нужно проделать способ больше работы, чтобы иметь дело с различными типами данных;размеры столбцов;; уточнениемасштаб;и т.д. И, возможно, функция UPDATE () для определения того, какие столбцы изменились (конечно, для триггера UPDATE).Если все, что вы пытаетесь сделать, это преобразовать различные типы данных в строки, проверьте функцию CONVERT ().

    • Триггеры транзакционные.

    • Никогда не помещайте код обработки строки в триггер (это задушит таблицу)

    • Нельзя поместить динамический SQL в триггер.

  2. Но в Sybase даже в этом нет необходимости. См. Руководство пользователя , глава 19 посвящена триггерам, с несколькими вариантами и примерами. Внутри триггера вы сможете просто:

    INSERT table_copy
        SELECT column_list  -- never use * unless you want the db fixed in cement
            FROM inserted
    
  3. Если вы пытаетесь скопировать вставки в все таблицы в одну таблицу аудита, то остерегайтесь. Тогда я понимаю ваш пример немного больше. Вы будете вынуждены использовать высокосимметричный многопоточный сервер (оракул не является сервером в смысле архитектуры) в однопоточном режиме через вашу таблицу. Аудит многопоточный.

Наконец, использование ручных методов любого рода не требуется, поэтому, если бы вы могли немного больше рассказать о своем PS, то, что вы хотите выполнить, это требование, я могу определить программный метод для вас. Похоже, вы пытаетесь использовать подход PL / SQL (который очень ограничен).

0 голосов
/ 19 января 2015

Просто используйте функцию LIST(). Это прямая замена функции stragg(). Пример

SELECT LIST(state, ', ') FROM cities

Результат:

name
CA, CA, MA, NY
...