ROW
Тип данных ROW был представлен в MariaDB 10.3.0.
Синтаксис
ROW (<field name> <data type> [{, <field name> <data type>}... ]) Описание
ROW — это тип данных для переменных хранимых процедур.
Возможности
Поля ROW как обычные переменные
Поля (члены) типа ROW действуют как обычные переменные и могут использоваться во всех частях запроса, где разрешено использование переменных хранимой процедуры:
- Присваивание с использованием оператора
:=и команды SET:
a.x:= 10; a.x:= b.x; SET a.x= 10, a.y=20, a.z= b.z;
- Передача в функции и операторы:
SELECT f1(rec.a), rec.a<10;
- Операторы (список выбора, WHERE, HAVING, LIMIT и т. д.):
SELECT var.a, t1.b FROM t1 WHERE t1.b=var.b LIMIT var.c;
-
INSERTзначения:
INSERT INTO t1 VALUES (rec.a, rec.b, rec.c);
-
SELECT .. INTOцели
SELECT a,b INTO rec.a, rec.b FROM t1 WHERE t1.id=10;
- Динамические параметры SQL (EXECUTE и EXECUTE IMMEDIATE)
EXECUTE IMMEDIATE 'CALL proc_with_out_param(?)' USING rec.a;
Переменные типа ROW в качестве целей FETCH
Переменные типа ROW допускаются в качестве целей FETCH:
FETCH cur INTO rec;
где cur — CURSOR, а rec — переменная хранимой процедуры типа ROW.
Обратите внимание, что в настоящее время попытка использовать FETCH для переменной типа ROW возвращает следующую ошибку:
ERROR 1328 (HY000): Incorrect number of FETCH variables
FETCH данных из курсора cur в переменную типа ROW rec выполняется следующим образом:
- Количество полей в
curдолжно совпадать с количеством полей вrec. В противном случае будет сообщено об ошибке.
- Присваивание выполняется слева направо. Первое поле курсора присваивается первому полю переменной, второе поле курсора — второму полю переменной и т. д.
- Имена полей в
recне имеют значения и могут отличаться от имен полей вcur.
См. примеры FETCH (ниже) для примеров использования с sql_mode=ORACLE и sql_mode=DEFAULT.
Переменные типа ROW в качестве целей SELECT...INTO
Переменные типа ROW допускаются в качестве целей SELECT..INTO с некоторыми отличиями в зависимости от используемого sql_mode.
- При использовании
sql_mode=ORACLE, переменныеtable%ROWTYPEиcursor%ROWTYPEмогут использоваться в качестве целейSELECT...INTO.
- Использование нескольких переменных
ROWв спискеSELECT..INTOприведет к ошибке.
- Использование переменных
ROWс количеством столбцов, отличным от количества в спискеSELECT..INTO, приведет к ошибке.
См. примеры SELECT...INTO (ниже) для примеров использования с sql_mode=ORACLE и sql_mode=DEFAULT.
Не реализованные возможности
Следующие возможности запланированы, но пока не реализованы:
- Возврат выражения типа ROW из хранимой функции (см. MDEV-12252). Для этого потребуется изменение грамматики, чтобы поддерживать имена полей после скобок:
SELECT f1().x FROM DUAL;
- Возврат выражения типа ROW из встроенной функции гибридного типа, такой как
CASE,IF, и т. д. - ROW из ROWs
Примеры
Объявление ROW в хранимой процедуре
DELIMITER $$ CREATE PROCEDURE p1() BEGIN DECLARE r ROW (c1 INT, c2 VARCHAR(10)); SET r.c1= 10; SET r.c2= 'test'; INSERT INTO t1 VALUES (r.c1, r.c2); END; $$ DELIMITER ; CALL p1();
Примеры FETCH
Полный пример FETCH для sql_mode=ORACLE:
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a INT, b VARCHAR(32));
INSERT INTO t1 VALUES (10,'b10');
INSERT INTO t1 VALUES (20,'b20');
INSERT INTO t1 VALUES (30,'b30');
SET sql_mode=oracle;
DROP PROCEDURE IF EXISTS p1;
DELIMITER $$
CREATE PROCEDURE p1 AS
rec ROW(a INT, b VARCHAR(32));
CURSOR c IS SELECT a,b FROM t1;
BEGIN
OPEN c;
LOOP
FETCH c INTO rec;
EXIT WHEN c%NOTFOUND;
SELECT ('rec=(' || rec.a ||','|| rec.b||')');
END LOOP;
CLOSE c;
END;
$$
DELIMITER ;
CALL p1();
Полный пример FETCH для sql_mode=DEFAULT:
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a INT, b VARCHAR(32));
INSERT INTO t1 VALUES (10,'b10');
INSERT INTO t1 VALUES (20,'b20');
INSERT INTO t1 VALUES (30,'b30');
SET sql_mode=DEFAULT;
DROP PROCEDURE IF EXISTS p1;
DELIMITER $$
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE rec ROW(a INT, b VARCHAR(32));
DECLARE c CURSOR FOR SELECT a,b FROM t1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN c;
read_loop:
LOOP
FETCH c INTO rec;
IF done THEN
LEAVE read_loop;
END IF;
SELECT CONCAT('rec=(',rec.a,',',rec.b,')');
END LOOP;
CLOSE c;
END;
$$
DELIMITER ;
CALL p1();
Примеры SELECT...INTO
Пример SELECT...INTO для sql_mode=DEFAULT:
SET sql_mode=DEFAULT; DROP TABLE IF EXISTS t1; DROP PROCEDURE IF EXISTS p1; CREATE TABLE t1 (a INT, b VARCHAR(32)); INSERT INTO t1 VALUES (10,'b10'); DELIMITER $$ CREATE PROCEDURE p1() BEGIN DECLARE rec1 ROW(a INT, b VARCHAR(32)); SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ DELIMITER ; CALL p1();
Результат приведённого выше примера:
+--------+--------+ | rec1.a | rec1.b | +--------+--------+ | 10 | b10 | +--------+--------+
Пример SELECT...INTO для sql_mode=ORACLE:
SET sql_mode=ORACLE; DROP TABLE IF EXISTS t1; DROP PROCEDURE IF EXISTS p1; CREATE TABLE t1 (a INT, b VARCHAR(32)); INSERT INTO t1 VALUES (10,'b10'); DELIMITER $$ CREATE PROCEDURE p1 AS rec1 ROW(a INT, b VARCHAR(32)); BEGIN SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ DELIMITER ; CALL p1();
Результат приведённого выше примера:
+--------+--------+ | rec1.a | rec1.b | +--------+--------+ | 10 | b10 | +--------+--------+
Пример для sql_mode=ORACLE, использующий переменные table%ROWTYPE в качестве целей SELECT..INTO:
SET sql_mode=ORACLE; DROP TABLE IF EXISTS t1; DROP PROCEDURE IF EXISTS p1; CREATE TABLE t1 (a INT, b VARCHAR(32)); INSERT INTO t1 VALUES (10,'b10'); DELIMITER $$ CREATE PROCEDURE p1 AS rec1 t1%ROWTYPE; BEGIN SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ DELIMITER ; CALL p1();
Результат приведённого выше примера:
+--------+--------+ | rec1.a | rec1.b | +--------+--------+ | 10 | b10 | +--------+--------+
Пример для sql_mode=ORACLE, использующий переменные cursor%ROWTYPE в качестве целей SELECT..INTO:
SET sql_mode=ORACLE; DROP TABLE IF EXISTS t1; DROP PROCEDURE IF EXISTS p1; CREATE TABLE t1 (a INT, b VARCHAR(32)); INSERT INTO t1 VALUES (10,'b10'); DELIMITER $$ CREATE PROCEDURE p1 AS CURSOR cur1 IS SELECT * FROM t1; rec1 cur1%ROWTYPE; BEGIN SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ DELIMITER ; CALL p1();
Результат приведённого выше примера:
+--------+--------+ | rec1.a | rec1.b | +--------+--------+ | 10 | b10 | +--------+--------+
См. также
© 2023 MariaDB
Licensed under the Creative Commons Attribution 3.0 Unported License and the GNU Free Documentation License.
https://mariadb.com/kb/en/row/