SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 19.01.2016 18:10:03

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

возврат таблицы из хранимой процедуры для использования в in()

Всем здравствуйте!

Есть следующая задачка - нужно в конструкции in() селекта подзапроса использовать значение поля, представленного в виде перечня неких чисел. А поскольку в in() нужно перечислить через запятую значения или воспользоваться подзапросом, - то мне нужно каким то образом преобразовать значение поля вида ("111,222,333") в in(111, 222, 333) или in(... таблица-последовательность этих чисел ...)



Мой упрощенный запрос


select "ттп".*
from "таблица товаров приходов" "ттп"
where 1
    and "ттп"."тип товара" = "запчасть"
    and ("ттп".count) <> (
        select sum(count)
        from "таблица товаров приходов" /* т.е. из этой же таблицы  */
        where 1
            and "код прихода" = "ттп"."код прихода"
            and "ттп"."тип товара" <> "запчасть"
            and "ттп"."код товара" in(/*сдесь собираюсь использовать значение поля запчасти "ттз"."перечень кодов товаров" таблицы main_table вида ("111,222,333", "222,111", "555", null и т.п.)*/)
    )
 


Т.е., таблица "таблица товаров приходов" хранит товары и запчасти. Смысл запроса - вывести все запчасти, количество которых "count" не равно сумме остальных типов товаров данной таблицы, но в пределах каждого конкретного прихода.


Прочитал в разных статьях, что нативной функции для разбивки строки по разделителю не существует. Нашел пример хран. проц. аналога PHP explode()
И что вернуть таблицу можно тоже только из хран. процедуры.

Я в них новичок, и пока смог "придумать" только такую:





DROP PROCEDURE if exists explode;
DELIMITER //
CREATE PROCEDURE `explode`(IN `mylist` VARCHAR(255))
-- body:
-- RESULT (`part` LONG VARCHAR)
BEGIN


    drop table if exists `xxxx`;
    create table `xxxx` (
        `part` varchar(255),
        KEY `part` (`part`)
    ) engine=myisam collate 'utf8_general_ci';
/* ТАБЛИЦА xxxx удаляется и создается */
/*движок вероятно потом использую memory*/


/* здесь я планировал в цикле разобрать входной параметр mylist, и заполнить врем. таблицу xxxx разбитыми частями*/


/* и вернуть ее чтобы использовать в селекте в in(result) */
SELECT part
FROM xxxx
where 1
;
 
END//
DELIMITER ;

call explode('111,222,333');
 


Этот код полностью работает.

Пока я понимаю так, что смогу использовать возвращаемую из хр. проц. таблицу в конструкции in() .
Проблема в том, что не получается сделать работающий запрос.
Пытался делать по примеру данной статьи http://citforum.ru/database/sql_any/sql_062.shtml
Но запутался, когда дошло дело до таблицы CURSOR.

Согласно статье, в хр. процедуре нужно не только создать селект, но и в операторе RESULT перечислить поля возвращаемой таблицы.

На данном этапе (с RESULT) я получаю ошибку "Error in query (1064): Syntax error near '(`part` LONG VARCHAR) BEGIN drop table if exists `xxxx`; create t' at line 3", далее по статье продвинуться не могу. Также не нашел что означает конструкция "body:", но ни с ней, ни без нее не работатает без ошибки.

Т.е., хранимая процедура explode на данный момент ошибок не выдает, пока не раскомментирую RESULT ... Пока мыслей больше нет, нужна помощь )

Неактивен

 

#2 19.01.2016 22:32:09

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: возврат таблицы из хранимой процедуры для использования в in()

в mysql нет оператора result

раз у вас есть процедура, разбивающая строку по разделителю, то сделайте её в виде функции (create function ..) которая будет проводить сравнение с кодом товара и возвращать 0 или 1

...
and "ттп"."тип товара" <> "запчасть"
            and ваша_функция("ттп"."код товара", "ттз"."перечень кодов товаров");

Неактивен

 

#3 19.01.2016 23:29:32

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: возврат таблицы из хранимой процедуры для использования в in()

Строку превратить в аргумент IN можно сформировав запрос из строки с помощью PREPARE

Неактивен

 

#4 20.01.2016 10:54:50

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

Re: возврат таблицы из хранимой процедуры для использования в in()

rgbeast написал:

Строку превратить в аргумент IN можно сформировав запрос из строки с помощью PREPARE

Пожалуйста, здесь поподробнее )))

Неактивен

 

#5 20.01.2016 11:01:36

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

Re: возврат таблицы из хранимой процедуры для использования в in()

rgbeast написал:

Строку превратить в аргумент IN можно сформировав запрос из строки с помощью PREPARE

Пока мое предположение, конечно - не уверен можно ли так. Например, - превратить строку "111,222,333" в строку вида ":id111,:id222,:id333", и подставить ее в in(). Не это ли, rgbeast, имеете в виду?

Неактивен

 

#6 20.01.2016 11:03:37

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: возврат таблицы из хранимой процедуры для использования в in()

По PREPARE имел в виду то, что строку можно сделать частью запроса по следующей схеме:
http://webew.ru/articles/178.webew

Неактивен

 

#7 20.01.2016 11:21:31

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

Re: возврат таблицы из хранимой процедуры для использования в in()

rgbeast написал:

По PREPARE имел в виду то, что строку можно сделать частью запроса по следующей схеме:
http://webew.ru/articles/178.webew

Либо я что-то недопонял, либо одно из двух - но я в статье не нашел как с помощью PREPARE можно сделать строку аргументом  IN() ...

Неактивен

 

#8 20.01.2016 12:15:38

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

Re: возврат таблицы из хранимой процедуры для использования в in()

Предположим, в хранимой процедуре я всеже буду удалять и создавать временную таблицу, в которую буду инсертить 111, 222, 333. Тогда мне непонятно, как или где в селекте вызывать данную процедуру так, чтобы в in(я мог написать так: select part from temp_table).

Копия селекта из первого поста


select "ттп".*
from "таблица товаров приходов" "ттп"
where 1
    and "ттп"."тип товара" = "запчасть"
    and ("ттп".count) <> (
        select sum(count)
        from "таблица товаров приходов" /* т.е. из этой же таблицы  */
        where 1
            and "код прихода" = "ттп"."код прихода"
            and "ттп"."тип товара" <> "запчасть"
            and "ттп"."код товара" in(/*<strong>если получится так сделать, то планирую написать здесь select part from temp_table) , где temp_table будет пересоздаваться с помощью хранимой процедуры, в которой будет разбиваться строка "111,222,333" и инсертиться в врем. таблицу temp_table</strong>*/)
    )
 



По моей логике, процедура должна вызываться в самом селекте, чтобы временная таблица пересоздавалась для каждого товара (не запчасти), но где именно можно и нужно ее вызывать - не ясно.

Неактивен

 

#9 20.01.2016 13:11:02

klow
Старожил
Зарегистрирован: 06.12.2014
Сообщений: 411

Re: возврат таблицы из хранимой процедуры для использования в in()

А существующая функция FIND_IN_SET не подойдет для задачи?
Пример:

... and FIND_IN_SET("ттп"."код товара", "111,222,333")>0

Отредактированно klow (20.01.2016 13:11:54)

Неактивен

 

#10 20.01.2016 13:50:38

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: возврат таблицы из хранимой процедуры для использования в in()

bannndi написал:

rgbeast написал:

По PREPARE имел в виду то, что строку можно сделать частью запроса по следующей схеме:
http://webew.ru/articles/178.webew

Либо я что-то недопонял, либо одно из двух - но я в статье не нашел как с помощью PREPARE можно сделать строку аргументом  IN() ...

PREPARE имя_выражения FROM 'SELECT ... and `ттп`.`код товара` in (?)';
SET @var = '111,222,333';
EXECUTE имя_выражения USING @var;

Неактивен

 

#11 20.01.2016 15:01:46

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

Re: возврат таблицы из хранимой процедуры для использования в in()

klow написал:

А существующая функция FIND_IN_SET не подойдет для задачи?
Пример:

... and FIND_IN_SET("ттп"."код товара", "111,222,333")>0

Очень даже подойдет! Спасибо большущее, klow! Плюсанул бы, если бы был доступен такой функционал!

Неактивен

 

#12 20.01.2016 15:17:35

bannndi
Участник
Зарегистрирован: 19.01.2016
Сообщений: 7

Re: возврат таблицы из хранимой процедуры для использования в in()

vasya написал:

bannndi написал:

rgbeast написал:

По PREPARE имел в виду то, что строку можно сделать частью запроса по следующей схеме:
http://webew.ru/articles/178.webew

Либо я что-то недопонял, либо одно из двух - но я в статье не нашел как с помощью PREPARE можно сделать строку аргументом  IN() ...

PREPARE имя_выражения FROM 'SELECT ... and `ттп`.`код товара` in (?)';
SET @var = '111,222,333';
EXECUTE имя_выражения USING @var;

vasya, ясно, спасибо, этот момент я протестировал, работает. Вопрос только в том, как использовать данную возможность в подзапросе селекта из первого поста, непосредственно в "and "ттп"."код товара" in(......) "

Сложность для меня именно в этом на данном этапе.

Неактивен

 

#13 10.10.2016 16:43:04

BSBAlex
Участник
Зарегистрирован: 07.10.2016
Сообщений: 16

Re: возврат таблицы из хранимой процедуры для использования в in()

А если скорость выполнения не критична, то можно использовать временную таблицу и процедуру, работающую с этой таблицей.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson