Не удается правильно объявить переменную в цикле процедуры

0

Это заставляет меня бананы. Я не гуру mysql на любом участке. Моя цель - добавить большое количество столбцов в таблицу. Я пробовал это несколько способов, и процедура зажимает DECLARE @FooA NVARCHAR (MAX) ;. Не знаю, почему.

Я ценю любые указатели...

USE mydatabase;
DELIMITER $$
DROP PROCEDURE IF EXISTS RepeatLoopProc$$
CREATE PROCEDURE RepeatLoopProc()
BEGIN
   DECLARE x INT;
   DECLARE sn VARCHAR(30);
   DECLARE dr VARCHAR(48);
   DECLARE @FooA NVARCHAR(MAX);
   SET x = 0;
   WHILE (x <= 150) DO
     SET sn = CONCAT('drivesn_', x);
     SET dr = CONCAT('driveinf_', x);
     SET x = x + 1;
     SET @FooA = 'ALTER TABLE DRIVE_MASTER ADD ' + sn + ' VARCHAR(30), ADD ' + dr + ' VARCHAR(48)';
     EXEC sp_executesql @FooA;
   END WHILE;
END$$
DELIMITER ;

Когда я это делаю, я получаю:

ERROR 1064 (42000): 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 '@FooA NVARCHAR(MAX);

Мой лоб убирается, когда он врезается в мой стол.

Конечной целью является добавление столбцов drivesn_0, driveinf_0, drivesn_1, driveinf_1 и т.д., Вплоть до drivesn_150 и driveinf_150. Тип VARCHAR (30) и VARCHAR (48) для каждого соответственно.

  • 1
    MySQL не использует + для объединения строк, вы должны использовать функцию CONCAT() .
  • 2
    Если вы добавляете в таблицу большое количество похожих столбцов, возможно, у вас плохо спроектированная схема. Повторяющиеся элементы должны быть в строках, а не в столбцах.
Теги:
declare
centos6

2 ответа

1

@variables не являются DECLAREd, а идентификаторы объявленных переменных не начинаются с @.

Кроме того, инструкции ALTER обычно воссоздают таблицу за кулисами (эквивалентную чему-то вроде CREATE TABLE newversion... INSERT INTO newversion SELECT * FROM oldversion... DROP TABLE oldversion... RENAME newversion). Таким образом, вам будет намного лучше создать один оператор ALTER в цикле и выполнить его только один раз.


Пример:

   ...
   SET @FooA = 'ALTER TABLE DRIVE_MASTER';
   SET x = 0;
   WHILE (x <= 150) DO
     SET sn = CONCAT('drivesn_', x);
     SET dr = CONCAT('driveinf_', x);
     SET @FooA = CONCAT(@FooA 
                       , CASE WHEN x != 0 THEN ', ' ELSE '' END
                       , 'ADD ', sn, ' VARCHAR(30), ADD ', dr, ' VARCHAR(48)'
                 );
     SET x = x + 1;
   END WHILE;
   EXEC sp_executesql @FooA;
   ...

... но то, что сказал Бармар в комментариях, является хорошим советом, вы, вероятно, должны иметь другую таблицу, например DRIVE_MASTER_DETAILS(x int, sn VARCHAR(30), dr VARCHAR(48))

  • 0
    Это то, что я думаю, я делаю. Изменение производится только один раз за цикл, добавляя два столбца за один раз.
  • 0
    Да, нет, я говорил только один раз изменить; даже делая два столбца за раз, вы все равно будете воссоздавать таблицу 151 раз. На очень больших столах даже один раз может быть мучительно долго. Смотрите пример, который я добавил для получения дополнительной информации.
0

У меня уже есть несколько таблиц. В основном я использую это, чтобы каталогизировать серийные номера дисков в хостах. Хост может иметь до 150 дисков. Другие таблицы содержат информацию о сетевом интерфейсе (macaddrs и т.д.). Все они связаны общим значением индекса. Для системы с 150 дисками я не вижу другого способа, кроме 150 столбцов. Либо это, либо мне не хватает фундаментальной концепции.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню