2015-09-03 3 views
5

Как написать цикл, который выполняется n раз в MySql без использования хранимой процедуры.Цикл n раз без использования хранимой процедуры

Это, как я это сделать с хранимой процедурой:

DELIMITER $$ 
DROP PROCEDURE IF EXISTS test$$ 
CREATE PROCEDURE test() 
BEGIN 
    DECLARE count INT DEFAULT 0; 
    WHILE count < 10 DO 
     /**Sql statement**/ 
     SET count = count + 1; 
    END WHILE; 
END$$ 
DELIMITER ; 

И тогда я исполню моя процедура так:

call test(); 

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

1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE count INT DEFAULT 0; WHILE count < 10 DO at line' 2

Я просмотрел Интернет для решения с n o удача.

Редактировать На основании комментариев:

выше хранимая процедура делает именно то, что я хочу: Это петли 10 раз и выполнить мое заявление SQL. Теперь я хочу выполнить одно и то же, не используя хранимую процедуру. Что-то вроде:

DECLARE count INT DEFAULT 0; 
    WHILE count < 10 DO 
     /**Sql statement**/ 
     SET count = count + 1; 
    END WHILE; 
+0

Я понятия не имею в mysql, но разве это не потому, что подсчет в зарезервированном ключевом слове? – HoneyBadger

+0

@HoneyBadger Я пробовал с другим именем, он не работает –

+0

Непонятно, что вы просите. У вас есть хранимая процедура, и вы вызываете свою процедуру. После этого вы удалили процедуру и * запустили обычный запрос *, как 'SELECT 10;'? если это так, вы никогда не получите сообщение об ошибке, которое вы отправили. Поэтому покажите нам запрос, который вы пытаетесь запустить. – Alex

ответ

5

MySQL документы на Flow Control Statements говорят:

MySQL supports the IF, CASE, ITERATE, LEAVE LOOP, WHILE, and REPEAT constructs for flow control within stored programs.

Docs на Stored Programs and Views говорят:

Stored program definitions include a body that may use compound statements, loops, conditionals, and declared variables.

Compound-Statement Syntax

This section describes the syntax for the BEGIN ... END compound statement and other statements that can be used in the body of stored programs: Stored procedures and functions, triggers, and events.

A compound statement is a block that can contain other blocks; declarations for variables, condition handlers, and cursors; and flow control constructs such as loops and conditional tests.

Итак, похоже, что вы ок n запускает явный цикл только в хранимой процедуре, функции или триггере.


В зависимости от того, что вы делаете в вашем SQL заявление, это может быть приемлемо использовать таблицу (или представление) чисел (Creating a "Numbers Table" in mysql, MYSQL: Sequential Number Table).

Если ваш запрос является SELECT и это нормально, чтобы вернуть результат ваших SELECT 10 раз, как один длинный набор результатов (в отличие от 10 отдельных наборов результатов), вы можете сделать что-то вроде этого:

SELECT MainQuery.* 
FROM 
    (
     SELECT 1 AS Number 
     UNION ALL SELECT 2 
     UNION ALL SELECT 3 
     UNION ALL SELECT 4 
     UNION ALL SELECT 5 
     UNION ALL SELECT 6 
     UNION ALL SELECT 7 
     UNION ALL SELECT 8 
     UNION ALL SELECT 9 
     UNION ALL SELECT 10 
    ) AS Numbers 
    CROSS JOIN 
    (
     SELECT 'some data' AS Result 
    ) AS MainQuery 

Пример для INSERT

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

Так что, если у вас есть таблица Numbers с int колонке Number со значениями от 1 до, скажем, 100K (как я), и первичный ключ на этой колонке, то вместо этого цикла:

DECLARE count INT DEFAULT 0; 
WHILE count < 10 DO 
    INSERT INTO table_name(col1,col2,col3) 
    VALUES("val1","val2",count); 

    SET count = count + 1; 
END WHILE; 

вы можете написать:

INSERT INTO table_name(col1,col2,col3) 
SELECT ("val1", "val2", Numbers.Number-1) 
FROM Numbers 
WHERE Numbers.Number <= 10; 

Он также будет работать почти в 10 раз быстрее.

+0

вы этого заслуживаете! –

+0

@ LuthandoLoot, спасибо. Вы также можете использовать таблицу чисел с 'INSERT'. Вместо 10 отдельных операторов в цикле вы можете написать один оператор, который вставляет сразу 10 строк. –

+0

Как это сделать только с запросом? –

2

Вы можете сделать это прямо с помощью последовательности последовательности MariaDB. MariaDB - это двоичная замена MySQL.

«Механизм последовательности позволяет создавать восходящие или нисходящие последовательности чисел (положительные целые числа) с заданным начальным значением, конечным значением и приращением».

[Руководство Sequence двигателя]

Вот некоторые образцы:

mysql -uroot -p 
    Enter password: xxxxxxx 
    Welcome to the MariaDB monitor. Commands end with ; or \g. 
    Your MariaDB connection id is 5 
    Server version: 10.0.20-MariaDB-log Homebrew 

    Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others. 

    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 

    MariaDB [(none)]> use tmp 
    Database changed 
    MariaDB [tmp]> select version(); 
    +---------------------+ 
    | version()   | 
    +---------------------+ 
    | 10.0.20-MariaDB-log | 
    +---------------------+ 
    1 row in set (0.00 sec) 

    MariaDB [tmp]> select * from seq_1_to_10; 
    +-----+ 
    | seq | 
    +-----+ 
    | 1 | 
    | 2 | 
    | 3 | 
    | 4 | 
    | 5 | 
    | 6 | 
    | 7 | 
    | 8 | 
    | 9 | 
    | 10 | 
    +-----+ 
    10 rows in set (0.00 sec) 

    MariaDB [tmp]> select * from seq_1_to_10_step_2; 
    +-----+ 
    | seq | 
    +-----+ 
    | 1 | 
    | 3 | 
    | 5 | 
    | 7 | 
    | 9 | 
    +-----+ 
    5 rows in set (0.00 sec) 

MariaDB [tmp]> SELECT DAYNAME('1980-12-05' + INTERVAL (seq) YEAR) day, 
    ->  '1980-12-05' + INTERVAL (seq) YEAR date FROM seq_0_to_40; 
+-----------+------------+ 
| day  | date  | 
+-----------+------------+ 
| Friday | 1980-12-05 | 
| Saturday | 1981-12-05 | 
| Sunday | 1982-12-05 | 
| Monday | 1983-12-05 | 
| Wednesday | 1984-12-05 | 
| Thursday | 1985-12-05 | 
| Friday | 1986-12-05 | 
| Saturday | 1987-12-05 | 
| Monday | 1988-12-05 | 
| Tuesday | 1989-12-05 | 
| Wednesday | 1990-12-05 | 
| Thursday | 1991-12-05 | 
| Saturday | 1992-12-05 | 
| Sunday | 1993-12-05 | 
| Monday | 1994-12-05 | 
| Tuesday | 1995-12-05 | 
| Thursday | 1996-12-05 | 
| Friday | 1997-12-05 | 
| Saturday | 1998-12-05 | 
| Sunday | 1999-12-05 | 
| Tuesday | 2000-12-05 | 
| Wednesday | 2001-12-05 | 
| Thursday | 2002-12-05 | 
| Friday | 2003-12-05 | 
| Sunday | 2004-12-05 | 
| Monday | 2005-12-05 | 
| Tuesday | 2006-12-05 | 
| Wednesday | 2007-12-05 | 
| Friday | 2008-12-05 | 
| Saturday | 2009-12-05 | 
| Sunday | 2010-12-05 | 
| Monday | 2011-12-05 | 
| Wednesday | 2012-12-05 | 
| Thursday | 2013-12-05 | 
| Friday | 2014-12-05 | 
| Saturday | 2015-12-05 | 
| Monday | 2016-12-05 | 
| Tuesday | 2017-12-05 | 
| Wednesday | 2018-12-05 | 
| Thursday | 2019-12-05 | 
| Saturday | 2020-12-05 | 
+-----------+------------+ 
41 rows in set (0.00 sec) 

MariaDB [tmp]> 

Вот один Пример:

MariaDB [(none)]> use tmp 
Database changed 
MariaDB [tmp]> SELECT * FROM seq_1_to_5, 
    -> (SELECT * FROM animals) AS x 
    -> ORDER BY seq; 
+-----+------+-----------+-----------------+ 
| seq | id | name  | specie   | 
+-----+------+-----------+-----------------+ 
| 1 | 1 | dougie | dog-poodle  | 
| 1 | 6 | tweety | bird-canary  | 
| 1 | 5 | spotty | turtle-spotted | 
| 1 | 4 | mr.turtle | turtle-snapping | 
| 1 | 3 | cadi  | cat-persian  | 
| 1 | 2 | bonzo  | dog-pitbull  | 
| 2 | 4 | mr.turtle | turtle-snapping | 
| 2 | 3 | cadi  | cat-persian  | 
| 2 | 2 | bonzo  | dog-pitbull  | 
| 2 | 1 | dougie | dog-poodle  | 
| 2 | 6 | tweety | bird-canary  | 
| 2 | 5 | spotty | turtle-spotted | 
| 3 | 6 | tweety | bird-canary  | 
| 3 | 5 | spotty | turtle-spotted | 
| 3 | 4 | mr.turtle | turtle-snapping | 
| 3 | 3 | cadi  | cat-persian  | 
| 3 | 2 | bonzo  | dog-pitbull  | 
| 3 | 1 | dougie | dog-poodle  | 
| 4 | 2 | bonzo  | dog-pitbull  | 
| 4 | 1 | dougie | dog-poodle  | 
| 4 | 6 | tweety | bird-canary  | 
| 4 | 5 | spotty | turtle-spotted | 
| 4 | 4 | mr.turtle | turtle-snapping | 
| 4 | 3 | cadi  | cat-persian  | 
| 5 | 5 | spotty | turtle-spotted | 
| 5 | 4 | mr.turtle | turtle-snapping | 
| 5 | 3 | cadi  | cat-persian  | 
| 5 | 2 | bonzo  | dog-pitbull  | 
| 5 | 1 | dougie | dog-poodle  | 
| 5 | 6 | tweety | bird-canary  | 
+-----+------+-----------+-----------------+ 
30 rows in set (0.00 sec) 

MariaDB [tmp]> 
+0

спасибо Bernd, но я не вижу, где вы делаете Loop/Iteration в этом примере –

+0

The Sequence Engine сделает это за вас. Если вы используете табличное имя типа seq_from_to_step, оно создает цикл for. Вы можете использовать его напрямую с помощью select * from seq_1_to_10. Я отредактирую свой ответ. –

+0

Красивая! Поскольку я использую Марию, это ПУТЬ лучше, чем любые другие. Я собирался сосать его и написать хранимую процедуру для 1 вещи ... Создание 20 UUID. 'SELECT UUID() FROM seq_1_to_20' Гораздо лучше! Я тоже должен был читать на своих двигателях. Я, вероятно, упускаю некоторые приятные вещи – Oberst

0

Это не возможно.

Я прочитал всю документацию MySQL, и ее предложения могут быть объявлены только в теле функции/процедуры.

Смежные вопросы