SQL001. Отбор множества записей по ключам
Описание
Если нужно отобрать записи по ключам, то намного быстрее будет засунуть эти ID в строку, распарсить и вытягивать каждую запись по по ключу по отдельности в цикле.
Областью применения данного способа отбора записей может быть подготовка набора данных, записи которого выбираются на основании другого набора данных, указанных пользователем.
Например, при построении отчета “Движение товарно-материальных ценностей по складу”, когда пользователь указывает (ставит галочки) в клиентском приложении по каким именно товарно-материальным ценностям отбирать объекты-движения. Клиентское приложение на основании отмеченных пользователем записей формирует строку-параметр, в которой через запятую перечислены коды элементов (записей) справочника “Товарно-материальные ценности”.
Пример
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
См. также
SUBSTRING(), CHAR_LENGTH(), LEFT(), RIGHT(), OVERLAY(), POSITION()
SQL007.Отбор множества записей по ключам из другой таблицы (обход конструкции IN)
Обсуждение