Подтвердить что ты не робот

Заполнение наборов результатов в MySQL

Я пытаюсь написать хранимую процедуру в MySQL, которая будет выполнять несколько простой запрос выбора, а затем перебирать результаты, чтобы решить, выполнять ли дополнительные запросы, преобразовывать данные или вообще отбрасывать данные. Фактически, я хочу реализовать это:

$result = mysql_query("SELECT something FROM somewhere WHERE some stuff");
while ($row = mysql_fetch_assoc($result)) {
    // check values of certain fields, decide to perform more queries, or not
    // tack it all into the returning result set
}

Только, я хочу это только в MySQL, поэтому его можно назвать процедурой. Я знаю, что для триггеров существует синтаксис FOR EACH ROW ..., но я не могу найти упоминания ничего подобного для использования вне синтаксиса CREATE TRIGGER .... Я прочитал некоторые из циклов в MySQL, но пока все, что я могу себе представить, это то, что я буду реализовывать что-то вроде этого:

SET @S = 1;
LOOP
    SELECT * FROM somewhere WHERE some_conditions LIMIT @S, 1
    -- IF NO RESULTS THEN
    LEAVE
    -- DO SOMETHING
    SET @S = @S + 1;
END LOOP

Хотя даже это несколько туманно в моем сознании.

Для справки, хотя я не думаю, что это обязательно релевантно, первоначальный запрос объединяет четыре таблицы вместе, чтобы сформировать модель иерархических разрешений, а затем, основываясь на том, насколько высока цепочка для конкретного разрешения, она будет извлекать дополнительную информацию о дочерних элементах, для которых это разрешение должно быть унаследовано.

4b9b3361

Ответ 1

Что-то вроде этого должно сделать трюк (однако, прочитайте после фрагмента для получения дополнительной информации)

CREATE PROCEDURE GetFilteredData()
BEGIN
  DECLARE bDone INT;

  DECLARE var1 CHAR(16);    -- or approriate type
  DECLARE Var2 INT;
  DECLARE Var3 VARCHAR(50);

  DECLARE curs CURSOR FOR  SELECT something FROM somewhere WHERE some stuff;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

  DROP TEMPORARY TABLE IF EXISTS tblResults;
  CREATE TEMPORARY TABLE IF NOT EXISTS tblResults  (
    --Fld1 type,
    --Fld2 type,
    --...
  );

  OPEN curs;

  SET bDone = 0;
  REPEAT
    FETCH curs INTO var1,, b;

    IF whatever_filtering_desired
       -- here for whatever_transformation_may_be_desired
       INSERT INTO tblResults VALUES (var1, var2, var3 ...);
    END IF;
  UNTIL bDone END REPEAT;

  CLOSE curs;
  SELECT * FROM tblResults;
END

Несколько вещей, чтобы рассмотреть...

Относительно фрагмента выше:

  • может потребовать передать часть запроса в Хранимую процедуру, возможно, особенно критерии поиска, чтобы сделать ее более общей.
  • Если этот метод должен вызываться несколькими сеансами и т.д., возможно, захочет передать идентификатор сеанса сортировки для создания уникального имени временной таблицы (на самом деле ненужная проблема, поскольку разные сеансы не используют одно и то же пространство имен временных файлов; Грубер, ниже)
  • Необходимо указать несколько частей, таких как объявления переменных, запрос SELECT и т.д.

В более общем смысле: пытается избежать необходимости использования курсора.

Я намеренно назвал переменную курсора curs [e], потому что курсоры - это смешанное благо. Они могут помочь нам внедрить сложные бизнес-правила, которые могут быть трудно выразить в декларативной форме SQL, но затем мы вынуждены использовать процедурную (императивную) форму SQL, которая является общей особенностью SQL, которая не является ни очень дружественной/экспрессивным, программируемым и часто менее эффективным по производительности.

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

Ответ 2

Использовать курсоры.

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