Как создать представление или таблицу из подготовленного оператора (выберите запрос) - PullRequest
1 голос
/ 01 августа 2020

Я пытаюсь создать представление из следующего подготовленного оператора:

CREATE VIEW myview AS -- this line is not working
SELECT CONCAT(GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total FROM mydb.source_table' SEPARATOR '\n UNION ALL \n'),'\nORDER BY Total ASC')
INTO @sql
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'mydb' 
    AND TABLE_NAME   = 'source_table'
    AND COLUMN_NAME NOT IN ('ID', 'Name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;

Я все еще не понимаю, как обрабатывать синтаксис group_concat.

Мне просто нужна помощь в том, как создать представление с подготовленным выше оператором.

UPDATE 1: Хранимая процедура

Как было предложено @nbk, я должен создать 5 хранимых процедур в одном столбце, чтобы иметь возможность data и использовать их для СОЗДАНИЯ ТАБЛИЧНОГО запроса. Вот версия хранимой процедуры приведенных выше кодов.

CREATE DEFINER=`admin`@`%` PROCEDURE `sp_result`()
BEGIN
    SELECT CONCAT(GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns FROM mydb.source_table' SEPARATOR '\n UNION ALL \n'), '\n LIMIT 0, 1 \n')
    INTO @sql
    FROM  INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = 'mydb' 
        AND TABLE_NAME   = 'source_table'
        AND COLUMN_NAME NOT IN ('ID', 'Name');

    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DROP PREPARE stmt;
END

Вот результат этой хранимой процедуры:

+-----------+
| MyColumns |
+-----------+
| Abc       |
+-----------+

Чтобы этот подход был мне полезен, я хочу, чтобы указанное выше Результат должен быть одним из столбцов моего запроса CREATE TABLE:

Вот мои попытки, но безуспешные:

Первая попытка: отдельный запрос

CREATE TABLE my_table AS SELECT id, name, mydb.sp_result() FROM source_table; -- Error Code: 1305. FUNCTION project_x.best_vendor1_name does not exist

Вторая попытка : Вставлено в последнюю часть хранимой процедуры

CREATE TABLE my_table AS SELECT @sql FROM source_table; -- no effect

Здесь я действительно не знаю, как СОЗДАТЬ ТАБЛИЦУ с использованием возвращаемых хранимой процедурой данных.

ОБНОВЛЕНИЕ 2: Проиллюстрировать инкапсуляцию

CREATE DEFINER=`root`@`%` PROCEDURE `proc_column_sum`()
BEGIN
DROP TABLE IF EXISTS table2;
SELECT CONCAT('
    CREATE TABLE table2 AS (',GROUP_CONCAT('
        SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total 
        FROM testdb.products ' 
        SEPARATOR '\n UNION ALL \n'), -- runtime syntax error somewhere here
    '\n ORDER BY Total ASC)') -- missing closing single quote right after ASC
INTO @sql
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb' 
    AND TABLE_NAME   = 'products'
    AND COLUMN_NAME NOT IN ('ID', 'Name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;
END

1 Ответ

1 голос
/ 02 августа 2020

Вы должны поместить CREATE TABLE в подготовленный оператор.

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

CREATE DEFINER=`root`@`%` PROCEDURE `proc_column_sum`()
BEGIN
SELECT 
CONCAT('CREATE TEMPORARY TABLE IF NOT EXISTS table2 AS (',GROUP_CONCAT('SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total FROM testdb.products ' SEPARATOR '\n UNION ALL \n'),'\nORDER BY Total ASC)')
INTO @sql
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb' 
    AND TABLE_NAME   = 'products'
    AND COLUMN_NAME NOT IN ('ID', 'Name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;
END

вы вызываете ее, затем

call proc_column_sum();
SELECT * FROM table2

Но при таком подходе вы каждый раз вызываете процедуру для получения новейших данных.

Я могу понять, что пошло не так в вашем запросе

CREATE DEFINER=`root`@`%` PROCEDURE `proc_column_sum`()
BEGIN
DROP TABLE IF EXISTS table2;
SELECT CONCAT('
    CREATE TABLE IF NOT EXISTS table2 AS (',GROUP_CONCAT('
    SELECT ''', COLUMN_NAME,''' MyColumns, SUM(`', COLUMN_NAME,'`) Total 
    FROM testdb.products ' 
    SEPARATOR '\n UNION ALL \n')
    ,'\nORDER BY Total ASC)')
INTO @sql
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'testdb' 
    AND TABLE_NAME   = 'products'
    AND COLUMN_NAME NOT IN ('ID', 'Name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;
END
...