Хранимая процедура для динамического оператора create, в котором количество столбцов постоянно меняется - PullRequest
0 голосов
/ 02 мая 2018

Мне нужно создать хранимую процедуру для создания динамического оператора create, который будет генерировать новый оператор create при каждом запуске.
У меня есть table_A, который имеет один столбец, и этот столбец содержит список имен столбцов, которые должны быть в операторе создания.
Пример:

     Table_A:  columns   
      abcd   
      hijk   
      defg    

Мой оператор создания должен выглядеть так:

    create table table_B (
    abcd varchar(255),
    hijk  varchar(255),
    defg varchar(255)
    );

Через несколько дней количество столбцов в Table_A может изменяться / увеличиваться / уменьшаться, например:

  Table_A: columns         
        abcd
        pqrs
        defg
        ghij

Моя инструкция создания должна выглядеть так:

    create table table_B ( 
    abcd varchar(255),
    pqrs  varchar(255),
    defg varchar(255),
    ghij varchar (255)
    );

Мне нужно написать хранимую процедуру с задействованными курсорами.

Я начал с чего-то вроде:

    Delimiter $$
    DROP PROCEDURE IF EXISTS sp_test2 $$
    CREATE PROCEDURE sp_test2()
    BEGIN
    DECLARE DONE INT DEFAULT 0;
    DECLARE col1 varchar(255);
    DECLARE curA CURSOR FOR     select col AS column_name from Table_A;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = 1;
    OPEN curA;
    DROP TABLE IF EXISTS Table_B;
    while done = 0 do  
    fetch next from CurA into col;
    if done = 0 then 
    set @SQL_TXT = concat('CREATE TABLE Table_B (',col1,' varchar(255))');
    -- select @SQL_TXT
    PREPARE stmt_name FROM @SQL_TXT;
    EXECUTE stmt_name;
    DEALLOCATE PREPARE stmt_name;
    end if;
    end while;
    close curA;
    end

    call sp_test2()    

Это прекрасно работает, когда у меня есть только одна строка в таблице (а это только один столбец в таблице создания). Как мне это сделать, когда у меня несколько столбцов.

1 Ответ

0 голосов
/ 02 мая 2018

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

Но если нужно, вот несколько способов ...

Попробуйте заменить / переставить эту часть (из исходного вопроса / проблемы):

DROP TABLE IF EXISTS Table_B;    
while done = 0 do  
fetch next from CurA into col;
if done = 0 then 
set @SQL_TXT = concat('CREATE TABLE Table_B (',col1,' varchar(255))');
-- select @SQL_TXT
PREPARE stmt_name FROM @SQL_TXT;
EXECUTE stmt_name;
DEALLOCATE PREPARE stmt_name;
end if;
end while;
close curA;

с / как-то так:

DROP TABLE IF EXISTS Table_B;
SET @SQL_TXT = '';
while done = 0 do  
    fetch next from CurA into col;
    if done = 0 then 
        set @SQL_TXT = concat(@SQL_TXT, ', `', col1, '` varchar(255)');
    end if;
end while;
close curA;
SET @SQL_TXT = CONCAT('CREATE TABLE Table_B (', SUBSTRING(@SQL_TXT, 2), ')');
PREPARE stmt_name FROM @SQL_TXT;
EXECUTE stmt_name;
DEALLOCATE PREPARE stmt_name;

Цикл строит ваш список полей, SUBSTRING () удаляет ведущие ',', а конечный конкат объединяет список полей с фактическим CREATE.


Или вы можете просто построить запрос следующим образом:

SET @SQL_TXT 
   = SELECT CONCAT('CREATE TABLE Table_B ('
                   , GROUP_CONCAT(CONCAT('`', col, '` VARCHAR(255)') SEPARATOR ',')
                   , ');' AS theQuery
     FROM Table_A
;

Также не в обоих случаях я разделял имя поля символом `; имена полей, такие как «123», не могут использоваться без разделителей.

...