Инструменты пользователя

Инструменты сайта


sql001.otbor_mnozhestva_zapisej_po_kljucham

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Both sides previous revision Предыдущая версия
sql001.otbor_mnozhestva_zapisej_po_kljucham [2009/02/18 19:04]
peaktop
sql001.otbor_mnozhestva_zapisej_po_kljucham [2016/03/10 13:59] (текущий)
wildsery Исправлены две ошибки зацикливания - когда входной параметр пустой, и когда входной параметр имеет "слово" длиннее буфера. Добавлены входные параметры - разделитель и пустое значение. Добавлен выходной счётчик номера строки.
Строка 1: Строка 1:
 +====== SQL001. Отбор множества записей по ключам ======
 +
 +
 +===== Описание =====
 +
 +Если нужно отобрать записи по ключам,​ то намного быстрее будет засунуть эти ID в строку,​ распарсить и вытягивать каждую запись по по ключу по отдельности в цикле.
 +
 +Областью применения данного способа отбора записей может быть подготовка набора данных,​ записи которого выбираются на основании другого набора данных,​ указанных пользователем. ​
 +
 +Например,​ при построении отчета "​Движение товарно-материальных ценностей по складу",​ когда пользователь указывает (ставит галочки) в клиентском приложении по каким именно товарно-материальным ценностям отбирать объекты-движения. Клиентское приложение на основании отмеченных пользователем записей формирует строку-параметр,​ в которой через запятую перечислены коды элементов (записей) справочника "​Товарно-материальные ценности"​.
 +
 +===== Пример =====
 +<code sql>
 +CREATE PROCEDURE CONVERT_IDS_TO_ROWS(
 +  IDS VARCHAR(32700)
 +)RETURNS (
 +  ID INTEGER
 +)AS
 +  DECLARE I INTEGER = 1;
 +  DECLARE J INTEGER = 1;
 +BEGIN
 +  IDS = TRIM(:IDS);
 +  WHILE (:I <= CHAR_LENGTH(:​IDS)) DO
 +  BEGIN
 +    IF (','​ = SUBSTRING(:​IDS FROM :I FOR 1)) THEN
 +    BEGIN
 +      ID = SUBSTRING(:​IDS FROM :J FOR :I - :J);
 +      SUSPEND;
 +      I = :I + 1;
 +      J = :I;
 +    END
 +    I = :I + 1;
 +  END
 +  IF (:I > :J) THEN
 +  BEGIN
 +    ID = SUBSTRING(:​IDS FROM :J FOR :I - :J);
 +    SUSPEND;
 +  END
 +END
 +
 + 
 +CREATE PROCEDURE LIST_TO_ROWS (
 +    A_LST BLOB SUB_TYPE TEXT,
 +    A_DELIMITER CHAR(1) = ',',​
 +    A_NULL VARCHAR(1) = ''​)
 +RETURNS (
 +    LINE INTEGER,
 +    ITEM VARCHAR(32000))
 +AS
 +  DECLARE POS_   ​INTEGER;​
 +  DECLARE OFFSET INTEGER = 1;
 +  DECLARE BEG    INTEGER;
 +  DECLARE BUF    VARCHAR(32000);​
 +BEGIN
 +  IF (A_LST IS NULL) THEN EXIT;
 +  LINE = 0;
 +
 +  WHILE (0=0) DO BEGIN
 +    BUF = SUBSTRING(A_LST FROM OFFSET FOR 32000);
 +    POS_ = 1; BEG = 1;
 +    WHILE (POS_ <= CHAR_LENGTH(BUF) AND POS_ <= 32000) DO BEGIN
 +      IF (SUBSTRING(BUF FROM POS_ FOR 1) = A_DELIMITER) THEN BEGIN
 +        IF (POS_ > BEG) THEN
 +          ITEM = SUBSTRING(BUF FROM BEG FOR POS_ - BEG);
 +        ELSE
 +          ITEM = A_NULL;
 +        SUSPEND;
 +        LINE = LINE + 1;
 +        BEG = POS_ + 1;
 +      END
 +      POS_ = POS_ + 1;
 +    END
 +    IF (BEG = 1 AND POS_ > 32000) THEN LEAVE;
 +    IF (OFFSET + POS_ - 2 = CHAR_LENGTH(A_LST)) THEN LEAVE;
 +    OFFSET = OFFSET + BEG - 1;
 +    IF (OFFSET > CHAR_LENGTH(A_LST)) THEN LEAVE;
 +  END
 +
 +  IF (BEG = 1 AND POS_ > 32000) THEN BEGIN
 +    ITEM = '#​N/​A';​
 +  END
 +  ELSE IF (POS_ > BEG) THEN BEGIN
 +    ITEM = SUBSTRING(BUF FROM BEG FOR POS_ - BEG);
 +  END
 +  ELSE BEGIN
 +    ITEM = A_NULL;
 +  END
 +  SUSPEND;
 +END
 +</​code>​
 +
 +===== См. также =====
 +[[SUBSTRING()]],​ [[CHAR_LENGTH()]],​ [[LEFT()]], ​ [[RIGHT()]], ​ [[overlay|OVERLAY()]], ​ [[POSITION()]]
 +
 +
 +[[SQL007.Отбор множества записей по ключам из другой таблицы (обход конструкции IN)]]
 +
 +===== Источник =====
 +
 +Форум [[http://​www.sql.ru/​forum/​actualtopics.aspx?​bid=2|SQL.RU]],​ автор: [[http://​www.sql.ru/​forum/​memberinfo.aspx?​mid=68203|WildSery]]
  
sql001.otbor_mnozhestva_zapisej_po_kljucham.txt · Последние изменения: 2016/03/10 13:59 — wildsery